Mail Archives: cygwin/2022/09/20/13:21:34
X-Recipient: | archive-cygwin AT delorie DOT com
|
X-Original-To: | cygwin AT cygwin DOT com
|
Delivered-To: | cygwin AT cygwin DOT com
|
DMARC-Filter: | OpenDMARC Filter v1.4.1 sourceware.org AD0713858C74
|
Authentication-Results: | sourceware.org;
|
| dmarc=none (p=none dis=none) header.from=lyx.org
|
Authentication-Results: | sourceware.org; spf=none smtp.mailfrom=lyx.org
|
Date: | Tue, 20 Sep 2022 19:20:08 +0200
|
From: | Enrico Forestieri <forenr AT lyx DOT org>
|
To: | cygwin AT cygwin DOT com
|
Subject: | Re: FIFO issues
|
Message-ID: | <Yyn2SEWN3R80ItR8@GIOVE>
|
Mail-Followup-To: | cygwin AT cygwin DOT com
|
MIME-Version: | 1.0
|
In-Reply-To: | <58359837-fd07-50a0-d5f8-b07bf425b7df@cornell.edu>
|
X-Spam-Status: | No, score=1.1 required=5.0 tests=BAYES_00, KAM_DMARC_STATUS,
|
| KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_BARRACUDACENTRAL, SPF_HELO_NONE, SPF_NONE,
|
| TXREP autolearn=no autolearn_force=no version=3.4.6
|
X-Spam-Level: | *
|
X-Spam-Checker-Version: | SpamAssassin 3.4.6 (2021-04-09) on
|
| server2.sourceware.org
|
X-BeenThere: | cygwin AT cygwin DOT com
|
X-Mailman-Version: | 2.1.29
|
List-Id: | General Cygwin discussions and problem reports <cygwin.cygwin.com>
|
List-Unsubscribe: | <https://cygwin.com/mailman/options/cygwin>,
|
| <mailto:cygwin-request AT cygwin DOT com?subject=unsubscribe>
|
List-Archive: | <https://cygwin.com/pipermail/cygwin/>
|
List-Post: | <mailto:cygwin AT cygwin DOT com>
|
List-Help: | <mailto:cygwin-request AT cygwin DOT com?subject=help>
|
List-Subscribe: | <https://cygwin.com/mailman/listinfo/cygwin>,
|
| <mailto:cygwin-request AT cygwin DOT com?subject=subscribe>
|
Errors-To: | cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com
|
Sender: | "Cygwin" <cygwin-bounces+archive-cygwin=delorie DOT com AT cygwin DOT com>
|
--rtiBEQW2d4pROHZG
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Tue, Sep 20, 2022 at 06:18:54PM -0700, Ken Brown wrote:
>
> On 9/20/2022 2:54 AM, Enrico Forestieri wrote:
> >
> > I compared the behavior of read() and select() on 3 different platforms.
> > My conclusion is that, actually, read() behaves the same on all of them,
> > whereas cygwin differs in the way select() works.
>
> Then I'm even more confused than I was before. Are you saying that
> there are situations in which read() reports EOF but select() does not
> report read ready? Could you post the code you used for testing?
I simply introduced a timeout for select() such that it returns on any
platform. On cygwin, when using "O_RDONLY | O_NONBLOCK" for the input
pipe, select() always returns 1, while on all other platforms it returns 0
unless a client actually opens it for writing.
As the "if (FD_ISSET(infd, &readfds))" block would not be entered on the
other platforms, I replaced it with "if (TRUE)" so that the read() is
always executed. In this conditions, the output is the same on all
platforms, meaning that the issue is the select() and not the read() call.
This is the attached fifocomm-test.c file.
--
Enrico
--rtiBEQW2d4pROHZG
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename="fifocomm-test.c"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/select.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define FIFO_IN "/tmp/pipe.in"
#define FIFO_OUT "/tmp/pipe.out"
#define FALSE 0
#define TRUE 1
typedef int bool;
void openpipes(void);
void closepipes(void);
int startpipe(char *name, bool inputpipe);
void endpipe(char *name, int fd);
int infd;
int outfd;
int count = 0;
int main(void)
{
int nsel;
bool done = FALSE;
char const *msg = "You sent: ";
int mlen = strlen(msg);
fd_set readfds;
FD_ZERO(&readfds);
openpipes();
do {
FD_SET(infd, &readfds);
struct timeval wait_tm = { 0l, 200000l }; /* 200 millisecs */
do {
nsel = select(infd + 1, &readfds, 0, 0, &wait_tm);
} while (nsel == -1 && (errno == EINTR || errno == EAGAIN));
if (nsel == -1) {
perror("select");
exit(4);
}
if (TRUE) {
char buf[100] = "You sent: ";
int status;
int count = 0;
strcpy(buf, msg);
while ((status = read(infd, buf + mlen, sizeof(buf) - mlen - 1))) {
if (status > 0) {
buf[mlen + status] = '\0';
if (write(outfd, buf, strlen(buf)) < 0) {
if (buf[mlen + status - 1] == '\n')
buf[mlen + status - 1] = '\0';
fprintf(stderr, "Error sending message: '%s': %s\n",
buf, strerror(errno));
}
if (strncasecmp(buf + mlen, "quit", 4) == 0)
done = TRUE;
} else if (errno == EAGAIN) {
/* Nothing to read, continue */
break;
} else {
/* An error occurred, bail out */
perror("read");
done = TRUE;
break;
}
}
if (!done) {
sleep(3);
closepipes();
openpipes();
errno = 0;
}
}
} while (!done);
closepipes();
return 0;
}
void openpipes(void)
{
fprintf(stderr, "%d) Opening pipes\n", ++count);
infd = startpipe(FIFO_IN, TRUE);
if (infd == -1)
exit(1);
outfd = startpipe(FIFO_OUT, FALSE);
if (outfd == -1)
exit(2);
if (fcntl(outfd, F_SETFL, O_NONBLOCK) < 0) {
fprintf(stderr, "Could not set flags on pipe %s: %s\n",
FIFO_OUT, strerror(errno));
exit(3);
}
}
void closepipes()
{
fprintf(stderr, "%d) Closing pipes\n", count);
endpipe(FIFO_IN, infd);
endpipe(FIFO_OUT, outfd);
}
int startpipe(char *name, bool inputpipe)
{
static bool stalepipe = FALSE;
int fd;
if (access(name, F_OK) == 0) {
if (inputpipe) {
/* Let's see whether we have a stale pipe */
fd = open(name, O_WRONLY | O_NONBLOCK);
if (fd >= 0) {
/* pipe exists and is used by another process */
close(fd);
} else if (errno == ENXIO) {
/* No process is reading from the other end */
fprintf(stderr, "Removing stale pipe %s\n", name);
stalepipe = TRUE;
endpipe(name, -1);
}
} else if (stalepipe) {
fprintf(stderr, "Removing stale pipe %s\n", name);
endpipe(name, -1);
stalepipe = FALSE;
}
if (access(name, F_OK) == 0) {
fprintf(stderr, "Pipe %s already exists and is in use.\n", name);
return -1;
}
}
if (mkfifo(name, 0600) < 0) {
fprintf(stderr, "Could not create pipe %s: %s\n",
name, strerror(errno));
return -1;
}
fd = open(name, inputpipe ? (O_RDONLY | O_NONBLOCK) : O_RDWR);
if (fd < 0) {
fprintf(stderr, "Could not open pipe %s: %s\n",
name, strerror(errno));
endpipe(name, -1);
return -1;
}
return fd;
}
void endpipe(char *name, int fd)
{
if (fd >= 0 && close(fd) < 0)
fprintf(stderr, "Could not close pipe %s: %s\n",
name, strerror(errno));
if (remove(name) < 0)
fprintf(stderr, "Could not remove pipe %s: %s\n",
name, strerror(errno));
}
--rtiBEQW2d4pROHZG
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
--
Problem reports: https://cygwin.com/problems.html
FAQ: https://cygwin.com/faq/
Documentation: https://cygwin.com/docs.html
Unsubscribe info: https://cygwin.com/ml/#unsubscribe-simple
--rtiBEQW2d4pROHZG--
- Raw text -