On 9/20/2022 1:20 PM, Enrico Forestieri wrote:
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.

I've just sent a patch to the cygwin-patches list that makes Cygwin behave the same as Linux. Thanks for reporting this problem.

Ken

P.S. I'm attaching a simplified test case that I used for testing the patch.
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/select.h>
#include <errno.h>
#include <sys/stat.h>

#define FIFO_PATH "/tmp/myfifo"

int
main ()
{
  int fd, tmpfd, nsel;
  fd_set readfds;
  struct timeval wait_tm = { 0l, 200000l }; /* 200 millisecs */

  if (unlink (FIFO_PATH) < 0  && errno != ENOENT)
    {
      perror ("unlink");
      exit (1);
    }

  if (mkfifo (FIFO_PATH, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH
              | S_IWOTH) < 0)
    {
      perror ("mkfifo");
      exit (1);
    }

  printf ("Opening a FIFO for reading with O_NONBLOCK\n");
  if ((fd = open (FIFO_PATH, O_RDONLY | O_NONBLOCK)) < 0)
    {
      perror ("open");
      exit (1);
    }

  printf ("Testing for read ready...\n");
  FD_ZERO (&readfds);
  FD_SET (fd, &readfds);
  nsel = select (fd + 1, &readfds, NULL, NULL, &wait_tm);
  printf ("  select returned %d\n", nsel);

  printf ("Opening and closing FIFO for writing...\n");
  if ((tmpfd = open (FIFO_PATH, O_WRONLY)) < 0)
    {
      perror ("open");
      exit (1);
    }
  if (close (tmpfd) < 0)
    {
      perror ("close");
      exit (1);
    }

  FD_ZERO (&readfds);
  FD_SET (fd, &readfds);
  nsel = select (fd + 1, &readfds, NULL, NULL, &wait_tm);
  printf ("  now select returned %d\n", nsel);
}
-- 
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

Reply via email to