From 0c38954e0033f4ef112fc2b6d8244c798dce30da Mon Sep 17 00:00:00 2001 From: Tristan Labelle Date: Wed, 14 Jun 2023 15:44:39 -0400 Subject: [PATCH] Clamp the length for WriteFile calls on win32 pipes. --- src/io.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/io.c b/src/io.c index f853d9bbf..e31e28c82 100644 --- a/src/io.c +++ b/src/io.c @@ -2510,6 +2510,23 @@ _dispatch_operation_perform(dispatch_operation_t op) } bSuccess = TRUE; } else if (GetFileType(hFile) == FILE_TYPE_PIPE) { + // WriteFile with more bytes than are available in the + // buffer of a NOWAIT pipe will immediately return 0, + // so clamp our requested write length to make progress. + IO_STATUS_BLOCK iosb; + FILE_PIPE_LOCAL_INFORMATION fpli; + NTSTATUS status = _dispatch_NtQueryInformationFile(hFile, + &iosb, &fpli, sizeof(fpli), FilePipeLocalInformation); + if (NT_SUCCESS(status)) { + // WriteQuotaAvailable is unreliable in the presence + // of a blocking reader, when it can return zero, so only + // account for it otherwise + if (fpli.WriteQuotaAvailable > 0) { + len = MIN(len, fpli.WriteQuotaAvailable); + } + len = MIN(len, fpli.OutboundQuota); + } + OVERLAPPED ovlOverlapped = {}; bSuccess = WriteFile(hFile, buf, (DWORD)len, (LPDWORD)&processed, &ovlOverlapped);