ext/libuv/src/win/pipe.c in libuv-1.3.0 vs ext/libuv/src/win/pipe.c in libuv-2.0.0
- old
+ new
@@ -178,10 +178,22 @@
return INVALID_HANDLE_VALUE;
}
+static void close_pipe(uv_pipe_t* pipe) {
+ assert(pipe->u.fd == -1 || pipe->u.fd > 2);
+ if (pipe->u.fd == -1)
+ CloseHandle(pipe->handle);
+ else
+ close(pipe->u.fd);
+
+ pipe->u.fd = -1;
+ pipe->handle = INVALID_HANDLE_VALUE;
+}
+
+
int uv_stdio_pipe_server(uv_loop_t* loop, uv_pipe_t* handle, DWORD access,
char* name, size_t nameSize) {
HANDLE pipeHandle;
int err;
char* ptr = (char*)handle;
@@ -231,18 +243,22 @@
static int uv_set_pipe_handle(uv_loop_t* loop,
uv_pipe_t* handle,
HANDLE pipeHandle,
+ int fd,
DWORD duplex_flags) {
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_MODE_INFORMATION mode_info;
DWORD mode = PIPE_READMODE_BYTE | PIPE_WAIT;
DWORD current_mode = 0;
DWORD err = 0;
+ if (handle->handle != INVALID_HANDLE_VALUE)
+ return UV_EBUSY;
+
if (!SetNamedPipeHandleState(pipeHandle, &mode, NULL, NULL)) {
err = GetLastError();
if (err == ERROR_ACCESS_DENIED) {
/*
* SetNamedPipeHandleState can fail if the handle doesn't have either
@@ -290,10 +306,11 @@
handle->flags |= UV_HANDLE_EMULATE_IOCP;
}
}
handle->handle = pipeHandle;
+ handle->u.fd = fd;
handle->flags |= duplex_flags;
return 0;
}
@@ -525,10 +542,11 @@
}
if (uv_set_pipe_handle(loop,
handle,
handle->pipe.serv.accept_reqs[0].pipeHandle,
+ -1,
0)) {
err = GetLastError();
goto error;
}
@@ -578,11 +596,11 @@
SwitchToThread();
}
if (pipeHandle != INVALID_HANDLE_VALUE &&
- !uv_set_pipe_handle(loop, handle, pipeHandle, duplex_flags)) {
+ !uv_set_pipe_handle(loop, handle, pipeHandle, -1, duplex_flags)) {
SET_REQ_SUCCESS(req);
} else {
SET_REQ_ERROR(req, GetLastError());
}
@@ -641,10 +659,11 @@
assert(pipeHandle != INVALID_HANDLE_VALUE);
if (uv_set_pipe_handle(loop,
(uv_pipe_t*) req->handle,
pipeHandle,
+ -1,
duplex_flags)) {
err = GetLastError();
goto error;
}
@@ -735,15 +754,12 @@
handle->flags &= ~UV_HANDLE_WRITABLE;
eof_timer_destroy(handle);
}
if ((handle->flags & UV_HANDLE_CONNECTION)
- && handle->handle != INVALID_HANDLE_VALUE) {
- CloseHandle(handle->handle);
- handle->handle = INVALID_HANDLE_VALUE;
- }
-
+ && handle->handle != INVALID_HANDLE_VALUE)
+ close_pipe(handle);
}
void uv_pipe_close(uv_loop_t* loop, uv_pipe_t* handle) {
if (handle->flags & UV_HANDLE_READING) {
@@ -784,11 +800,11 @@
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
return;
}
- if (uv_set_pipe_handle(loop, handle, req->pipeHandle, 0)) {
+ if (uv_set_pipe_handle(loop, handle, req->pipeHandle, -1, 0)) {
CloseHandle(req->pipeHandle);
req->pipeHandle = INVALID_HANDLE_VALUE;
SET_REQ_ERROR(req, GetLastError());
uv_insert_pending_req(loop, (uv_req_t*) req);
handle->reqs_pending++;
@@ -1768,12 +1784,11 @@
}
} else {
/* This pipe is not readable. We can just close it to let the other end */
/* know that we're done writing. */
- CloseHandle(handle->handle);
- handle->handle = INVALID_HANDLE_VALUE;
+ close_pipe(handle);
}
if (req->cb) {
req->cb(req, 0);
}
@@ -1836,12 +1851,11 @@
HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) {
return;
}
/* Force both ends off the pipe. */
- CloseHandle(pipe->handle);
- pipe->handle = INVALID_HANDLE_VALUE;
+ close_pipe(pipe);
/* Stop reading, so the pending read that is going to fail will */
/* not be reported to the user. */
uv_read_stop((uv_stream_t*) pipe);
@@ -1872,10 +1886,31 @@
NTSTATUS nt_status;
IO_STATUS_BLOCK io_status;
FILE_ACCESS_INFORMATION access;
DWORD duplex_flags = 0;
+ if (os_handle == INVALID_HANDLE_VALUE)
+ return UV_EBADF;
+
+ /* In order to avoid closing a stdio file descriptor 0-2, duplicate the
+ * underlying OS handle and forget about the original fd.
+ * We could also opt to use the original OS handle and just never close it,
+ * but then there would be no reliable way to cancel pending read operations
+ * upon close.
+ */
+ if (file <= 2) {
+ if (!DuplicateHandle(INVALID_HANDLE_VALUE,
+ os_handle,
+ INVALID_HANDLE_VALUE,
+ &os_handle,
+ 0,
+ FALSE,
+ DUPLICATE_SAME_ACCESS))
+ return uv_translate_sys_error(GetLastError());
+ file = -1;
+ }
+
/* Determine what kind of permissions we have on this handle.
* Cygwin opens the pipe in message mode, but we can support it,
* just query the access flags and set the stream flags accordingly.
*/
nt_status = pNtQueryInformationFile(os_handle,
@@ -1897,10 +1932,14 @@
duplex_flags |= UV_HANDLE_WRITABLE;
if (access.AccessFlags & FILE_READ_DATA)
duplex_flags |= UV_HANDLE_READABLE;
if (os_handle == INVALID_HANDLE_VALUE ||
- uv_set_pipe_handle(pipe->loop, pipe, os_handle, duplex_flags) == -1) {
+ uv_set_pipe_handle(pipe->loop,
+ pipe,
+ os_handle,
+ file,
+ duplex_flags) == -1) {
return UV_EINVAL;
}
uv_pipe_connection_init(pipe);