win,pipe: minimal fix to uv_read_cb->uv_read_start recursion bug (#4784)

Starting a new read after uv_read_cb returns causes memory corruption on
the OVERLAPPED read_req if uv_read_stop+uv_read_start was called during
the callback after the latest refactoring. This apparently also forces
the kernel to deadlock us, since it apparently cannot cancel the second
read while the first one is pending (reads apparently are not permitted
to finish out of order). Avoid that simply by not issuing another read
(set more=0) if there is already a read pending (from uv_read_start).

There are probably better things we could do here (such as bring back
`uv_active_tcp_streams_threshold`), but the current `alloc_cb` design
may not currently permit that without making breaking changes. We could
also detect in `uv_read_start` that we are inside of of the `read_cb`
for that stream, and defer the actual zero-read until the read_cb
returns, but that would likely be a larger change.

Fix #4738
This commit is contained in:
Jameson Nash 2025-07-10 09:08:36 -04:00 committed by GitHub
parent 454637403a
commit 7026ae0fe2
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -2149,7 +2149,8 @@ void uv__process_pipe_read_req(uv_loop_t* loop,
} else {
/* The zero-read completed without error, indicating there is data
* available in the kernel buffer. */
while (handle->flags & UV_HANDLE_READING) {
while (handle->flags & UV_HANDLE_READING &&
!(handle->flags & UV_HANDLE_READ_PENDING)) {
bytes_requested = 65536;
/* Depending on the type of pipe, read either IPC frames or raw data. */
if (handle->ipc)