3.3.0: Possible regression in cygwin DLL (Win10); fixed in snapshot
Takashi Yano
takashi.yano@nifty.ne.jp
Sat Nov 6 06:10:47 GMT 2021
# This topic is moved from cygwin@cygwin.com mailing list.
Hi Ken,
On Fri, 5 Nov 2021 16:08:31 -0400
Ken Brown wrote:
> On 11/5/2021 3:41 PM, Takashi Yano via Cygwin wrote:
> > Thanks much for the detailed steps. I could reproduce the problem.
> >
> > It seems that the cause is the overhaul for the pipe implementation.
> > I also found the workaround for this issue. Please try:
> > export CYGWIN=pipe_byte
> >
> > Corinna, Ken,
> > What about setting pipe mode to byte by default?
>
> I have a vague recollection that this caused some other problem, but I'll have
> to review the email discussions from a few months ago. I'm traveling at the
> moment and won't get to this for a few days.
>
> In the meantime, could you explain (probably on cygwin-developers) why message
> mode causes the reported issue? Also, does the problem occur only when there
> are non-Cygwin apps involved?
I digged deeper this problem and might find the cause.
Perhaps, C# program sometimes writes 0 byte to stdout.
As a result, if stdout is a message pipe, raw_read() returns
0 byte and EOF is falsely detected. So, setting pipe type
to byte solves the issue.
I used the following two test programs. The output of
second test program (do_pipe) is like:
res=1
len=0 <<<<< Look here!!
res=1
len=14
res=0
len=0
/* C# program which is supposed to write 0 byte msg. */
/* Filename: produce.cs */
/* Compile this with "csc produce.cs" */
using System;
namespace Produce
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World.");
}
}
}
/* End of produce.cs */
/* Filename: do_pipe.c */
/* Compile this with "x86_64-w64-mingw32-gcc do_pipe.c -o do_pipe" */
#include <windows.h>
#include <stdio.h>
#if 0
#define PTYPE PIPE_TYPE_BYTE
#else
#define PTYPE PIPE_TYPE_MESSAGE
#endif
int main()
{
HANDLE hr, hw;
STARTUPINFO si;
PROCESS_INFORMATION pi;
char buf[1024];
BOOL res;
SECURITY_ATTRIBUTES sec_none = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
hr = CreateNamedPipe("\\\\.\\pipe\\pipe-test1",
PIPE_ACCESS_INBOUND, PTYPE,
1, 4096, 4096, NMPWAIT_USE_DEFAULT_WAIT, &sec_none);
hw = CreateFile("\\\\.\\pipe\\pipe-test1",
GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, &sec_none,
OPEN_EXISTING, 0, 0);
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
si.dwFlags = STARTF_USESTDHANDLES;
si.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
si.hStdOutput = hw;
si.hStdError = GetStdHandle(STD_ERROR_HANDLE);
CreateProcess(NULL, "produce", NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
CloseHandle(hw);
do {
DWORD len;
res = ReadFile(hr, buf, sizeof(buf), &len, NULL);
printf("res=%d\n", res);
printf("len=%d\n", len);
} while (res);
CloseHandle(hr);
WaitForSingleObject(pi.hProcess, INFINITE);
return 0;
}
/* End of do_pipe.c */
Therefore, the following patch instead of setting pipe type to byte
also resolves the issue.
diff --git a/winsup/cygwin/fhandler_pipe.cc b/winsup/cygwin/fhandler_pipe.cc
index 43771e8f7..bc06d157c 100644
--- a/winsup/cygwin/fhandler_pipe.cc
+++ b/winsup/cygwin/fhandler_pipe.cc
@@ -393,7 +393,8 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
}
}
- if (nbytes_now == 0 || status == STATUS_BUFFER_OVERFLOW)
+ if ((nbytes_now == 0 && !NT_SUCCESS (status))
+ || status == STATUS_BUFFER_OVERFLOW)
break;
}
ReleaseMutex (read_mtx);
I am not sure which is the better solution.
P.S.
Unfortunately, these solutions do not resolve the issue
which is another issue with C# program:
https://cygwin.com/pipermail/cygwin/2021-March/247987.html
This still needs FILE_SYNCHRONOUS_IO_NONALERT flag.
--
Takashi Yano <takashi.yano@nifty.ne.jp>
More information about the Cygwin-developers
mailing list