On Aug 31 21:31, Takashi Yano wrote:
> On Tue, 31 Aug 2021 20:45:41 +0900
> Takashi Yano wrote:
> > On Tue, 31 Aug 2021 12:18:57 +0200
> > Corinna Vinschen wrote:
> > > Please try the attached patch on top of topic/pipe.
> >
> > Thanks for the new patch. I have confirmed that above issue
> > is fixed and select() for write pipe seems to work as expected.
> >
> >
> > BTW, I found one minor difference between Linux and this pipe
> > implementation.
> >
> > The test case is attached. The test case uses non-bloking I/O.
> > If this STC runs on Linux, the result is:
> >
> > 1024/1024
> > 1740/1740
> > 2958/2958
> > 5028/5028
> > 8547/8547
> > 14529/14529
> > 24699/24699
> > 41988/41988
> > 22227/71379
> > 65536/121344
> > 65536/206284
> > Total: 247KB in 0.000612 second, 403517.628166KB/s
> >
> > On cygwin 3.2.0, the result is similar to Linux.
> >
> > 1024/1024
> > 1740/1740
> > 2957/2957
> > 5026/5026
> > 8544/8544
> > 14524/14524
> > 24690/24690
> > 41972/41972
> > 65536/71352
> > 65536/121298
> > 65536/206206
> > Total: 290KB in 0.062653 second, 4628.669018KB/s
> >
> >
> > However, on topic/pipe implementation, the result is
> >
> > 1024/1024
> > 1740/1740
> > 2957/2957
> > 5026/5026
> > 8544/8544
> > 14524/14524
> > 24690/24690
> > -1/41972
> > w-1/71352
> > w-1/121298
> > w-1/206206
> > wTotal: 57KB in 0.000330 second, 172989.377845KB/s
> >
> > In non-blocking mode, writing more than pipe space will fail with
> > EAGAIN in this implementation.
> >
> > In Linux and cygwin 3.2.0, it seems to write as much as writable.
> >
> > Is this difficult to be fixed?
>
> The following patch almost fixes the issue, but atomicity is the problem.
Thanks, I took the liberty to use your idea to implement a loop trying
to write again. For me the output is now
1024/1024
1740/1740
2958/2958
5028/5028
8547/8547
14529/14529
24699/24699
7011/41988
65536/71379
65536/121344
65536/206284
Total: 256KB in 0.017771 second, 14405.248913KB/s
Could you try again with this patch? I'm glad if we can straighten
out the bugs :)
diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
index 2dec0a84817c..0aed8456bb0b 100644
--- a/winsup/cygwin/fhandler_pipe.cc
+++ b/winsup/cygwin/fhandler_pipe.cc
@@ -352,8 +352,30 @@ fhandler_pipe::raw_write (const void *ptr, size_t len)
else
len1 = (ULONG) left;
nbytes_now = 0;
- status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
- (PVOID) ptr, len1, NULL, NULL);
+ while (true)
+ {
+ status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
+ (PVOID) ptr, len1, NULL, NULL);
+ if (evt || !NT_SUCCESS (status) || io.Information > 0)
+ break;
+
+ FILE_PIPE_LOCAL_INFORMATION fpli;
+ IO_STATUS_BLOCK qio;
+
+ if (!NT_SUCCESS (NtQueryInformationFile (query_hdl, &qio, &fpli,
+ sizeof (fpli), FilePipeLocalInformation)))
+ len1 >>= 1;
+ else
+ {
+ fpli.WriteQuotaAvailable = fpli.InboundQuota
+ - fpli.ReadDataAvailable;
+ if (len1 > fpli.WriteQuotaAvailable
+ && fpli.WriteQuotaAvailable > 0)
+ len1 = fpli.InboundQuota - fpli.ReadDataAvailable;
+ else
+ break;
+ }
+ }
if (evt && status == STATUS_PENDING)
{
waitret = cygwait (evt);
@@ -378,7 +400,7 @@ fhandler_pipe::raw_write (const void *ptr, size_t len)
/* NtWriteFile returns success with # of bytes written == 0
if writing on a non-blocking pipe fails because the pipe
buffer doesn't have sufficient space. */
- if (nbytes_now == 0)
+ if (nbytes_now == 0 && nbytes == 0)
set_errno (EAGAIN);
ptr = ((char *) ptr) + chunk;
nbytes += nbytes_now;