Skip to content

Instantly share code, notes, and snippets.

@piscisaureus
Created August 11, 2011 02:02
Show Gist options
  • Select an option

  • Save piscisaureus/1138757 to your computer and use it in GitHub Desktop.

Select an option

Save piscisaureus/1138757 to your computer and use it in GitHub Desktop.
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