[PATCH v8] Cygwin: pipe: Switch pipe mode to blocking mode by default

Corinna Vinschen corinna-cygwin@cygwin.com
Thu Oct 24 10:21:04 GMT 2024


On Oct 24 17:58, Takashi Yano wrote:
> On Wed, 23 Oct 2024 11:00:33 +0200
> Corinna Vinschen wrote:
> > This new implementation of raw_write() skips the mechanism added in
> > commit 170e6badb621 ("Cygwin: pipe: improve writing when pipe buffer is
> > almost full") for non-blocking pipes, if the pipe has less space than
> > is requested by user-space.
> > 
> > Rather than trying to write multiple of 4K chunks or smaller multiple of
> > 2 chunks if < 4K, it just writes as much as possible in one go, i.e.
> > 
> > Before:
> > 
> >   $ ./x 40000
> >   pipe capacity: 65536
> >   write: writable 1, 40000 25536
> >   write: writable 1, 24576 960
> >   write: writable 0, 512 448
> >   write: writable 0, 256 192
> >   write: writable 0, 128 64
> >   write: writable 0, 64 0
> >   write: writable 0, -1 / Resource temporarily unavailable
> > 
> > After:
> > 
> >   $ ./x 40000
> >   pipe capacity: 65536
> >   write: writable 1, 40000 25536
> >   write: writable 1, 25536 0
> >   write: writable 0, -1 / Resource temporarily unavailable
> > 
> > This way, we get into the EAGAIN case much faster again, which was
> > one reason for 170e6badb621.
> > 
> > Does this make more sense, and if so, why?  If this is really the
> > way to go, the comment starting at line 634 (after applying your patch)
> > will have to be changed as well.
> 
> Perhaps, I did not understand intent of 170e6badb621. Could you please
> provide the test program (./x)? I will check my code.

I attached it.  If you call it with just the number of bytes per write,
e.g. `./x 12345', the writes are blocking.  If you add another parameter,
e.g. `./x 12345 1', the writes are nonblocking.

> > > +  int64_t unique_id = 0;
> > 
> > unique_id will be set by the following nt_create() anyway.
> > Is there a case where it's not set?  I don't see this.
> 
> Without initialization, compiler complains... due to false positive?

It does for you?  For some reason it doesn't complain for me.
I'm using a gcc 12.4.0 cross compiler on Linux.  Weird.

Anyway, if it complains for you, it's ok to initialize, of course.


Corinna
-------------- next part --------------
#define _GNU_SOURCE
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/select.h>

char buf[32 * 4096];

void
handler (int sig)
{
  fprintf (stderr, "SIGALRM ");
}

int
main (int argc, char **argv)
{
  int fd[2], max;
  ssize_t ret;
  ssize_t to_write, written = 0;
  struct sigaction sa = { 0 };
  fd_set fds;
  struct timeval tv = { 0 };

  int nonblock = (argc == 3) ? O_NONBLOCK : 0;

  if (argc < 2 || argc > 3)
    return 1;
  if (pipe2 (fd, nonblock) == -1)
    return 2;
  to_write = strtol (argv[1], NULL, 0);
  if (to_write < 1 || to_write > sizeof buf)
    return 3;
  sa.sa_handler = handler;
  if (sigaction (SIGALRM, &sa, NULL) == -1)
    return 4;
  max = 65536;//fcntl (fd[1], F_GETPIPE_SZ);
  fprintf (stderr, "pipe capacity: %d\n", max);
  do
    {
      sleep (1);
      alarm (2);
      FD_ZERO (&fds);
      FD_SET (fd[1], &fds);
      ret = select (fd[1] + 1, NULL, &fds, NULL, &tv);
      fprintf (stderr, "write: writable %d, ", FD_ISSET (fd[1], &fds));
      ret = write (fd[1], buf, to_write);
      alarm (0);
      if (ret < 0)
	fprintf (stderr, "%zd / %s\n", ret, strerror (errno));
      else
	{
	  written += ret;
	  fprintf (stderr, "%zd %zd\n", ret, (ssize_t) max - written);
	}
    }
  while (ret >= 0);
}


More information about the Cygwin-patches mailing list