Created
August 11, 2011 02:02
-
-
Save piscisaureus/1138757 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| From c9f1146f99b67c2b8354c2ed9a47808fb85a30b1 Mon Sep 17 00:00:00 2001 | |
| From: Bert Belder <bertbelder@gmail.com> | |
| Date: Thu, 11 Aug 2011 04:00:39 +0200 | |
| Subject: [PATCH 1/2] Windows: fix pipe shutdown | |
| --- | |
| src/win/pipe.c | 91 +++++++++++++++++++++++++++++++++++++++---------------- | |
| src/win/req.c | 7 ++++ | |
| 2 files changed, 71 insertions(+), 27 deletions(-) | |
| diff --git a/src/win/pipe.c b/src/win/pipe.c | |
| index db2aa50..04e0f04 100644 | |
| --- a/src/win/pipe.c | |
| +++ b/src/win/pipe.c | |
| @@ -144,23 +144,58 @@ static int uv_set_pipe_handle(uv_pipe_t* handle, HANDLE pipeHandle) { | |
| } | |
| +static DWORD WINAPI pipe_shutdown_thread_proc(void* parameter) { | |
| + int errno; | |
| + uv_pipe_t* handle; | |
| + uv_shutdown_t* req; | |
| + | |
| + req = (uv_shutdown_t*) parameter; | |
| + assert(req); | |
| + handle = (uv_pipe_t*) req->handle; | |
| + assert(handle); | |
| + | |
| + FlushFileBuffers(handle->handle); | |
| + | |
| + /* Post completed */ | |
| + if (!PostQueuedCompletionStatus(LOOP->iocp, | |
| + 0, | |
| + 0, | |
| + &req->overlapped)) { | |
| + uv_fatal_error(GetLastError(), "PostQueuedCompletionStatus"); | |
| + } | |
| + | |
| + return 0; | |
| +} | |
| + | |
| + | |
| void uv_pipe_endgame(uv_pipe_t* handle) { | |
| uv_err_t err; | |
| int status; | |
| unsigned int uv_alloced; | |
| + DWORD result; | |
| if (handle->flags & UV_HANDLE_SHUTTING && | |
| !(handle->flags & UV_HANDLE_SHUT) && | |
| handle->write_reqs_pending == 0) { | |
| - close_pipe(handle, &status, &err); | |
| - if (handle->shutdown_req->cb) { | |
| - if (status == -1) { | |
| - LOOP->last_error = err; | |
| - } | |
| - handle->shutdown_req->cb(handle->shutdown_req, status); | |
| + /* TODO: Try to avoid using the thread pool. Maybe we can somehow figure */ | |
| + /* out how much data is left in the kernel buffer? */ | |
| + result = QueueUserWorkItem(pipe_shutdown_thread_proc, | |
| + handle->shutdown_req, | |
| + WT_EXECUTELONGFUNCTION); | |
| + if (result) { | |
| + /* Mark the handle as shut now to avoid going through this again. */ | |
| + handle->flags |= UV_HANDLE_SHUT; | |
| + | |
| + } else { | |
| + /* Failure. */ | |
| + uv_set_sys_error(GetLastError()); | |
| + handle->shutdown_req->cb(handle->shutdown_req, -1); | |
| + handle->flags &= ~UV_HANDLE_SHUTTING; | |
| + DECREASE_PENDING_REQ_COUNT(handle); | |
| } | |
| - handle->reqs_pending--; | |
| + | |
| + return; | |
| } | |
| if (handle->flags & UV_HANDLE_CLOSING && | |
| @@ -718,7 +753,10 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { | |
| break; | |
| } | |
| - /* TODO: do we need to check avail > 0? */ | |
| + if (avail == 0) { | |
| + // Nothing to read after all | |
| + break; | |
| + } | |
| buf = handle->alloc_cb((uv_stream_t*)handle, avail); | |
| assert(buf.len > 0); | |
| @@ -728,27 +766,12 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { | |
| buf.len, | |
| &bytes, | |
| NULL)) { | |
| - if (bytes > 0) { | |
| - /* Successful read */ | |
| - handle->read_cb((uv_stream_t*)handle, bytes, buf); | |
| - /* Read again only if bytes == buf.len */ | |
| - if (bytes <= buf.len) { | |
| - break; | |
| - } | |
| - } else { | |
| - /* Connection closed */ | |
| - handle->flags &= ~UV_HANDLE_READING; | |
| - handle->flags |= UV_HANDLE_EOF; | |
| - LOOP->last_error.code = UV_EOF; | |
| - LOOP->last_error.sys_errno_ = ERROR_SUCCESS; | |
| - handle->read_cb((uv_stream_t*)handle, -1, buf); | |
| + /* Successful read */ | |
| + handle->read_cb((uv_stream_t*)handle, bytes, buf); | |
| + /* Read again only if bytes == buf.len */ | |
| + if (bytes <= buf.len) { | |
| break; | |
| } | |
| - } else { | |
| - /* Ouch! serious error. */ | |
| - uv_set_sys_error(GetLastError()); | |
| - handle->read_cb((uv_stream_t*)handle, -1, buf); | |
| - break; | |
| } | |
| } | |
| @@ -826,3 +849,17 @@ void uv_process_pipe_connect_req(uv_pipe_t* handle, uv_connect_t* req) { | |
| DECREASE_PENDING_REQ_COUNT(handle); | |
| } | |
| + | |
| + | |
| +void uv_process_pipe_shutdown_req(uv_pipe_t* handle, uv_shutdown_t* req) { | |
| + assert(handle->type == UV_NAMED_PIPE); | |
| + | |
| + CloseHandle(handle->handle); | |
| + handle->handle = INVALID_HANDLE_VALUE; | |
| + | |
| + if (req->cb) { | |
| + ((uv_shutdown_cb) req->cb)(req, 0); | |
| + } | |
| + | |
| + DECREASE_PENDING_REQ_COUNT(handle); | |
| +} | |
| diff --git a/src/win/req.c b/src/win/req.c | |
| index 6308188..8e0c093 100644 | |
| --- a/src/win/req.c | |
| +++ b/src/win/req.c | |
| @@ -110,6 +110,13 @@ void uv_process_reqs() { | |
| DELEGATE_STREAM_REQ((uv_connect_t*) req, connect, handle); | |
| break; | |
| + case UV_SHUTDOWN: | |
| + /* Tcp shutdown requests don't come here. */ | |
| + assert(((uv_shutdown_t*) req)->handle->type == UV_NAMED_PIPE); | |
| + uv_process_pipe_shutdown_req( | |
| + (uv_pipe_t*) ((uv_shutdown_t*) req)->handle, req); | |
| + break; | |
| + | |
| case UV_WAKEUP: | |
| uv_process_async_wakeup_req((uv_async_t*) req->data, req); | |
| break; | |
| -- | |
| 1.7.3.1.msysgit.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment