Cygwin/MSYS2 in version 3.5.4 or later relies in having the WriteQuotaAvailable member of a NtQueryInformationFile(FilePipeLocalInformation) query properly filled.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57424
``` A bisect of cygwin1.dll led to this commit: 49018bf5774fc90ddddc762a8462030c5d528643 is the first broken commit commit 49018bf5774fc90ddddc762a8462030c5d528643 Author: Takashi Yano takashi.yano@nifty.ne.jp Date: Mon Jul 1 17:44:53 2024 +0900 Cygwin: pty: Avoid client deadlock when pty master stops to read. ``` [cygwin commit cygwin-3_5-branch](https://www.cygwin.com/cgit/newlib-cygwin/commit/?h=cygwin-3_5-branch&id...)
[cygwin commit main branch](https://www.cygwin.com/cgit/newlib-cygwin/commit/?id=c4fb5da2787693ea3bf20b2...)
Installing cygwin/msys2 and reproducing this issue might need also the last patches from bug #55138 and #53574.
From: Bernhard Übelacker bernhardu@mailbox.org
Cygwin/MSYS2 in version 3.5.4 or later relies in having the WriteQuotaAvailable member of a NtQueryInformationFile(FilePipeLocalInformation) query properly filled.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=57424 --- dlls/ntdll/tests/pipe.c | 1 - server/named_pipe.c | 4 +++- 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/tests/pipe.c b/dlls/ntdll/tests/pipe.c index cf98d555455..14a6148a2c5 100644 --- a/dlls/ntdll/tests/pipe.c +++ b/dlls/ntdll/tests/pipe.c @@ -2309,7 +2309,6 @@ static void test_pipe_local_info(HANDLE pipe, BOOL is_server, DWORD state) ok(local_info.ReadDataAvailable == 0, "ReadDataAvailable = %lu\n", local_info.ReadDataAvailable); ok(local_info.OutboundQuota == 200, "OutboundQuota = %lu\n", local_info.OutboundQuota); - todo_wine ok(local_info.WriteQuotaAvailable == (is_server ? 200 : 100), "WriteQuotaAvailable = %lu\n", local_info.WriteQuotaAvailable); ok(local_info.NamedPipeState == state, "%s NamedPipeState = %lu, expected %lu\n", diff --git a/server/named_pipe.c b/server/named_pipe.c index 6e4ae371a1b..8cc7f36f408 100644 --- a/server/named_pipe.c +++ b/server/named_pipe.c @@ -854,10 +854,12 @@ static void pipe_end_get_file_info( struct fd *fd, obj_handle_t handle, unsigned pipe_info->ReadDataAvailable = pipe_end_get_avail( pipe_end );
pipe_info->OutboundQuota = pipe->outsize; - pipe_info->WriteQuotaAvailable = 0; /* FIXME */ pipe_info->NamedPipeState = pipe_end->state; pipe_info->NamedPipeEnd = pipe_end->obj.ops == &pipe_server_ops ? FILE_PIPE_SERVER_END : FILE_PIPE_CLIENT_END; + + pipe_info->WriteQuotaAvailable = pipe_info->NamedPipeEnd == FILE_PIPE_CLIENT_END + ? pipe_info->InboundQuota : pipe_info->OutboundQuota; break; } case FileStandardInformation:
Jinoh Kang (@iamahuman) commented about server/named_pipe.c:
pipe_info->ReadDataAvailable = pipe_end_get_avail( pipe_end ); pipe_info->OutboundQuota = pipe->outsize;
pipe_info->WriteQuotaAvailable = 0; /* FIXME */ pipe_info->NamedPipeState = pipe_end->state; pipe_info->NamedPipeEnd = pipe_end->obj.ops == &pipe_server_ops ? FILE_PIPE_SERVER_END : FILE_PIPE_CLIENT_END;
pipe_info->WriteQuotaAvailable = pipe_info->NamedPipeEnd == FILE_PIPE_CLIENT_END
? pipe_info->InboundQuota : pipe_info->OutboundQuota;
Since you're removing the FIXME, you need to account for the number of outstanding (written but unread) bytes from the available write quota to be correct.
For example, if the pipe is full (no space left), this should be 0. To implement this, you could subtract `pipe_end_get_avail( pipe_end->connection )` from the quota so it reflects the remaining available space. You should also check how native handles disconnected pipes (`pipe_end->connection == NULL`).
Also, tests would be nice: it seems like the "outstanding message not read by the other end" case is missing from the tests.
If cumbersome, you can ignore what I said; just keep the FIXME and remove the `proper` wording from the commit message.