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);