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

Corinna Vinschen corinna-cygwin@cygwin.com
Mon Oct 28 09:55:31 GMT 2024


Hi Takashi,

On Oct 27 17:57, Takashi Yano wrote:
> Hi Corinna,
> 
> On Thu, 24 Oct 2024 12:21:04 +0200
> Corinna Vinschen wrote:
> > > > 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.
> 
> Thanks for the test case.
> I think I could restore the previous behaviour. Please try v9 patch.
> 
> CYGWIN_NT-10.0-19045 HP-Z230 3.5.4-1.x86_64 2024-08-25 16:52 UTC x86_64 Cygwin
> $ ./a.exe 40000 1
> pipe capacity: 65536
> write: writable 1, 40000 25536
> write: writable 1, 24576 960
> write: writable 0, -1 / Resource temporarily unavailable
> 
> Just after the commit 170e6badb621 (master branch)

Oops.  You tested in the wrong spot.  The original patch wasn't quite
polished, the followup patches 1ed909e047a2 and 686e46ce7148 are also
required to show the intended behaviour, and the intended behaviour is
the same in the blocking and non-blocking case...

> $ ./a.exe 40000 1
> pipe capacity: 65536
> write: writable 1, 40000 25536
> write: writable 1, 24576 960
> write: writable 0, -1 / Resource temporarily unavailable

So this should actually be:

  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

just as in the blocking case.

The ideal commit for testing the intendend behaviour is f78009cb1ccf,
because that's your regression fix slowing down writes.

As I wrote in the commit message of 170e6badb621, the idea is to defer
EAGAIN/EINTR when the write buffer starts to be filled up. 

The code I came up with does NOT resemble Linux closely, because the way
Linux pipe buffers work is by some simple but fast paging mechanism,
which may even lead to pipes being smaller than PIPE_BUF.  Nevertheless,
except in some border cases, Linux often still returns some non-0 value
when our former code already returned EAGAIN/EINTR.

While this was mainly a problem in the blocking case, I thought the
buffer usage computation should be identical between blocking and
non-blocking, just as on Linux.

> Please try:
> $ ./a.out `expr 65536 - 4096 + 543` 1
> pipe capacity: 65536
> write: writable 1, 61983 3553
> write: writable 0, 543 3010
> write: writable 0, 543 2467
> write: writable 0, 543 1924
> write: writable 0, 543 1381
> write: writable 0, 543 838
> write: writable 0, 543 295
> write: writable 0, -1 / Resource temporarily unavailable

The intended behaviour (after commit 686e46ce7148) is:

  pipe capacity: 65536
  write: writable 1, 61983 3553
  write: writable 0, 2048 1505
  write: writable 0, 1024 481
  write: writable 0, 256 225
  write: writable 0, 128 97
  write: writable 0, 64 33
  write: writable 0, 32 1
  write: writable 0, -1 / Resource temporarily unavailable

> $ ./a.out `expr 65536 - 4096 + 1234` 1
> pipe capacity: 65536
> write: writable 1, 62674 2862
> write: writable 0, 1234 1628
> write: writable 0, 1234 394
> write: writable 0, -1 / Resource temporarily unavailable

And here:

  pipe capacity: 65536
  write: writable 1, 62674 2862
  write: writable 0, 2048 814
  write: writable 0, 512 302
  write: writable 0, 256 46
  write: writable 0, 32 14
  write: writable 0, 8 6
  write: writable 0, 4 2
  write: writable 0, 2 0
  write: writable 0, -1 / Resource temporarily unavailable

And if somebody has a better idea instead of the "next-less-power-of-2"
writing, I'm all ears. We can always come up with another method, as
long as it's the same usage in the blocking and non-blocking case.


Thanks,
Corinna


More information about the Cygwin-patches mailing list