From 9b4db6777c14a069ea042d972c54d00868d22004 Mon Sep 17 00:00:00 2001 From: Trevor Norris Date: Tue, 3 Mar 2015 12:44:32 -0700 Subject: [PATCH] uv: float win pipe patch Float patch to fix pipe on Windows. Original commit message: win: fix pipe blocking writes In the code path for pipe blocking writes, WriteFile is already posting a completion packet to the I/O completion port. POST_COMPLETION_FOR_REQ was causing the same request to get returned twice by GetCompletionStatusEx. Also on the same code path, we were waiting on the wrong event. We need to update queued_bytes and write_queue_size when a blocking write request completes asynchronously. Ref: https://github.com/libuv/libuv/pull/238 --- deps/uv/src/win/pipe.c | 12 ++++++------ deps/uv/src/win/req-inl.h | 11 +++++++++++ 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 57fab065aa34..8039cac3c4f2 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -1347,7 +1347,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->queued_bytes = bufs[0].len; handle->write_queue_size += req->queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ @@ -1372,12 +1372,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, /* Request completed immediately. */ req->queued_bytes = 0; } else { - assert(ipc_header_req != NULL); /* Request queued by the kernel. */ - if (WaitForSingleObject(ipc_header_req->overlapped.hEvent, INFINITE) != + req->queued_bytes = bufs[0].len; + handle->write_queue_size += req->queued_bytes; + if (WaitForSingleObject(req->overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); - CloseHandle(ipc_header_req->overlapped.hEvent); + CloseHandle(req->overlapped.hEvent); return uv_translate_sys_error(err); } } @@ -1386,7 +1387,6 @@ static int uv_pipe_write_impl(uv_loop_t* loop, REGISTER_HANDLE_REQ(loop, handle, req); handle->reqs_pending++; handle->write_reqs_pending++; - POST_COMPLETION_FOR_REQ(loop, req); return 0; } else { result = WriteFile(handle->handle, @@ -1404,7 +1404,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->queued_bytes = uv__count_bufs(bufs, nbufs); + req->queued_bytes = bufs[0].len; handle->write_queue_size += req->queued_bytes; } diff --git a/deps/uv/src/win/req-inl.h b/deps/uv/src/win/req-inl.h index 46c7d9b106a8..0c825a3cd344 100644 --- a/deps/uv/src/win/req-inl.h +++ b/deps/uv/src/win/req-inl.h @@ -93,6 +93,17 @@ INLINE static uv_req_t* uv_overlapped_to_req(OVERLAPPED* overlapped) { INLINE static void uv_insert_pending_req(uv_loop_t* loop, uv_req_t* req) { req->next_req = NULL; if (loop->pending_reqs_tail) { +#ifdef _DEBUG + /* Ensure the request is not already in the queue, or the queue + * will get corrupted. + */ + uv_req_t* current = loop->pending_reqs_tail; + do { + assert(req != current); + current = current->next_req; + } while(current != loop->pending_reqs_tail); +#endif + req->next_req = loop->pending_reqs_tail->next_req; loop->pending_reqs_tail->next_req = req; loop->pending_reqs_tail = req;