diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index 465f8a67c83..09164c65eb0 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -11,8 +11,10 @@ /build/gyp /test/run-tests +/test/run-tests.exe /test/run-tests.dSYM /test/run-benchmarks +/test/run-benchmarks.exe /test/run-benchmarks.dSYM *.sln @@ -22,6 +24,6 @@ *.vcxproj.user _UpgradeReport_Files/ UpgradeLog*.XML -build/Debug -build/Release -build/ipch +Debug +Release +ipch diff --git a/deps/uv/BSDmakefile b/deps/uv/BSDmakefile new file mode 100644 index 00000000000..227ee743a9e --- /dev/null +++ b/deps/uv/BSDmakefile @@ -0,0 +1,2 @@ +all: + @echo "I need GNU make. Please run \`gmake\` instead." diff --git a/deps/uv/all.gyp b/deps/uv/all.gyp index 115e5428ef9..b3036f56ef8 100644 --- a/deps/uv/all.gyp +++ b/deps/uv/all.gyp @@ -142,6 +142,7 @@ 'src/win/handle.c', 'src/win/internal.h', 'src/win/loop-watcher.c', + 'src/win/ntdll.h', 'src/win/pipe.c', 'src/win/process.c', 'src/win/req.c', @@ -150,6 +151,7 @@ 'src/win/tcp.c', 'src/win/timer.c', 'src/win/util.c', + 'src/win/winapi.c', ] }, { # Not Windows i.e. POSIX 'cflags': [ diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 53d566af589..aa60253d82a 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -74,8 +74,14 @@ endif # Need _GNU_SOURCE for strdup? RUNNER_CFLAGS=$(CFLAGS) -D_GNU_SOURCE +RUNNER_LINKFLAGS=$(LINKFLAGS) + +ifeq (SunOS,$(uname_S)) +RUNNER_LINKFLAGS += -pthreads +else +RUNNER_LINKFLAGS += -pthread +endif -RUNNER_LINKFLAGS=$(LINKFLAGS) -pthreads RUNNER_LIBS= RUNNER_SRC=test/runner-unix.c diff --git a/deps/uv/src/eio/config_freebsd.h b/deps/uv/src/eio/config_freebsd.h index b740cdd8787..3c93d260f79 100644 --- a/deps/uv/src/eio/config_freebsd.h +++ b/deps/uv/src/eio/config_freebsd.h @@ -7,6 +7,9 @@ /* fdatasync(2) is available */ /* #undef HAVE_FDATASYNC */ +/* utimes(2) is available */ +#define HAVE_UTIMES 1 + /* futimes(2) is available */ #define HAVE_FUTIMES 1 diff --git a/deps/uv/src/uv-unix.c b/deps/uv/src/uv-unix.c index 5e2d98c75eb..a2bbb002bb1 100644 --- a/deps/uv/src/uv-unix.c +++ b/deps/uv/src/uv-unix.c @@ -48,9 +48,13 @@ #include /* pipe2() requires linux >= 2.6.27 and glibc >= 2.9 */ #define HAVE_PIPE2 \ - defined(LINUX_VERSION_CODE) && defined(__GLIBC_PREREQ) && LINUX_VERSION_CODE >= 0x2061B && __GLIBC_PREREQ(2, 9)) + defined(LINUX_VERSION_CODE) && defined(__GLIBC_PREREQ) && \ + LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && __GLIBC_PREREQ(2, 9)) #endif +/* XXX disabling HAVE_PIPE2 for now can't compile on 2.6.18 */ +#undef HAVE_PIPE2 + #ifdef __sun # include # include diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 21470f9c91f..bc703fddbd9 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -70,6 +70,9 @@ void uv_init() { /* Initialize winsock */ uv_winsock_startup(); + /* Fetch winapi function pointers */ + uv_winapi_init(); + /* Intialize event loop */ uv_loop_init(); } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index a10bba259a3..87f9be1b7ad 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -24,7 +24,9 @@ #include "uv.h" #include "../uv-common.h" + #include "tree.h" +#include "ntdll.h" /* @@ -234,4 +236,13 @@ void uv_set_sys_error(int sys_errno); void uv_set_error(uv_err_code code, int sys_errno); +/* + * Windows api functions that we need to retrieve dynamically + */ +void uv_winapi_init(); + +extern sRtlNtStatusToDosError pRtlNtStatusToDosError; +extern sNtQueryInformationFile pNtQueryInformationFile; + + #endif /* UV_WIN_INTERNAL_H_ */ diff --git a/deps/uv/src/win/ntdll.h b/deps/uv/src/win/ntdll.h new file mode 100644 index 00000000000..d5db6ca4be1 --- /dev/null +++ b/deps/uv/src/win/ntdll.h @@ -0,0 +1,130 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef UV_WIN_NTDLL_H_ +#define UV_WIN_NTDLL_H_ + +#include + + +#ifndef _NTDEF_ + typedef LONG NTSTATUS; + typedef NTSTATUS *PNTSTATUS; +#endif + + +#define STATUS_SUCCESS ((NTSTATUS)0x0) + + +typedef struct _IO_STATUS_BLOCK { + union { + NTSTATUS Status; + PVOID Pointer; + } DUMMYUNIONNAME; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + + +typedef struct _FILE_PIPE_LOCAL_INFORMATION { + ULONG NamedPipeType; + ULONG NamedPipeConfiguration; + ULONG MaximumInstances; + ULONG CurrentInstances; + ULONG InboundQuota; + ULONG ReadDataAvailable; + ULONG OutboundQuota; + ULONG WriteQuotaAvailable; + ULONG NamedPipeState; + ULONG NamedPipeEnd; +} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION; + + +typedef enum _FILE_INFORMATION_CLASS { + FileDirectoryInformation = 1, + FileFullDirectoryInformation, + FileBothDirectoryInformation, + FileBasicInformation, + FileStandardInformation, + FileInternalInformation, + FileEaInformation, + FileAccessInformation, + FileNameInformation, + FileRenameInformation, + FileLinkInformation, + FileNamesInformation, + FileDispositionInformation, + FilePositionInformation, + FileFullEaInformation, + FileModeInformation, + FileAlignmentInformation, + FileAllInformation, + FileAllocationInformation, + FileEndOfFileInformation, + FileAlternateNameInformation, + FileStreamInformation, + FilePipeInformation, + FilePipeLocalInformation, + FilePipeRemoteInformation, + FileMailslotQueryInformation, + FileMailslotSetInformation, + FileCompressionInformation, + FileObjectIdInformation, + FileCompletionInformation, + FileMoveClusterInformation, + FileQuotaInformation, + FileReparsePointInformation, + FileNetworkOpenInformation, + FileAttributeTagInformation, + FileTrackingInformation, + FileIdBothDirectoryInformation, + FileIdFullDirectoryInformation, + FileValidDataLengthInformation, + FileShortNameInformation, + FileIoCompletionNotificationInformation, + FileIoStatusBlockRangeInformation, + FileIoPriorityHintInformation, + FileSfioReserveInformation, + FileSfioVolumeInformation, + FileHardLinkInformation, + FileProcessIdsUsingFileInformation, + FileNormalizedNameInformation, + FileNetworkPhysicalNameInformation, + FileIdGlobalTxDirectoryInformation, + FileIsRemoteDeviceInformation, + FileAttributeCacheInformation, + FileNumaNodeInformation, + FileStandardLinkInformation, + FileRemoteProtocolInformation, + FileMaximumInformation +} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS; + + +typedef ULONG (NTAPI *sRtlNtStatusToDosError) + (NTSTATUS Status); + +typedef NTSTATUS (NTAPI *sNtQueryInformationFile) + (HANDLE FileHandle, + PIO_STATUS_BLOCK IoStatusBlock, + PVOID FileInformation, + ULONG Length, + FILE_INFORMATION_CLASS FileInformationClass); + +#endif /* UV_WIN_NTDLL_H_ */ \ No newline at end of file diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index 766f073686e..589a80368ff 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -173,15 +173,48 @@ void uv_pipe_endgame(uv_pipe_t* handle) { int status; unsigned int uv_alloced; DWORD result; + uv_shutdown_t* req; + NTSTATUS nt_status; + IO_STATUS_BLOCK io_status; + FILE_PIPE_LOCAL_INFORMATION pipe_info; + if (handle->flags & UV_HANDLE_SHUTTING && !(handle->flags & UV_HANDLE_SHUT) && handle->write_reqs_pending == 0) { + req = handle->shutdown_req; + + /* Try to avoid flushing the pipe buffer in the thread pool. */ + nt_status = pNtQueryInformationFile(handle->handle, + &io_status, + &pipe_info, + sizeof pipe_info, + FilePipeLocalInformation); + + if (nt_status != STATUS_SUCCESS) { + /* Failure */ + handle->flags &= ~UV_HANDLE_SHUTTING; + if (req->cb) { + uv_set_sys_error(pRtlNtStatusToDosError(nt_status)); + req->cb(req, -1); + } + DECREASE_PENDING_REQ_COUNT(handle); + return; + } + + if (pipe_info.OutboundQuota == pipe_info.WriteQuotaAvailable) { + /* Short-circuit, no need to call FlushFileBuffers. */ + handle->flags |= UV_HANDLE_SHUT; + if (req->cb) { + req->cb(req, 0); + } + DECREASE_PENDING_REQ_COUNT(handle); + return; + } - /* TODO: Try to avoid using the thread pool. Maybe we can somehow figure */ - /* out how much data is left in the kernel buffer? */ + /* Run FlushFileBuffers in the thhead pool. */ result = QueueUserWorkItem(pipe_shutdown_thread_proc, - handle->shutdown_req, + req, WT_EXECUTELONGFUNCTION); if (result) { /* Mark the handle as shut now to avoid going through this again. */ @@ -189,13 +222,14 @@ void uv_pipe_endgame(uv_pipe_t* handle) { } else { /* Failure. */ - uv_set_sys_error(GetLastError()); - handle->shutdown_req->cb(handle->shutdown_req, -1); handle->flags &= ~UV_HANDLE_SHUTTING; + if (req->cb) { + uv_set_sys_error(GetLastError()); + req->cb(req, -1); + } DECREASE_PENDING_REQ_COUNT(handle); + return; } - - return; } if (handle->flags & UV_HANDLE_CLOSING && @@ -333,6 +367,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { if (pipeHandle != INVALID_HANDLE_VALUE) { break; } + + SwitchToThread(); } if (pipeHandle != INVALID_HANDLE_VALUE && !uv_set_pipe_handle(handle, pipeHandle)) { @@ -754,7 +790,7 @@ void uv_process_pipe_read_req(uv_pipe_t* handle, uv_req_t* req) { } if (avail == 0) { - // Nothing to read after all + /* There is nothing to read after all. */ break; } @@ -863,7 +899,7 @@ void uv_process_pipe_shutdown_req(uv_pipe_t* handle, uv_shutdown_t* req) { handle->handle = INVALID_HANDLE_VALUE; if (req->cb) { - ((uv_shutdown_cb) req->cb)(req, 0); + req->cb(req, 0); } DECREASE_PENDING_REQ_COUNT(handle); diff --git a/deps/uv/src/win/winapi.c b/deps/uv/src/win/winapi.c new file mode 100644 index 00000000000..632b01d099b --- /dev/null +++ b/deps/uv/src/win/winapi.c @@ -0,0 +1,52 @@ +/* Copyright Joyent, Inc. and other Node contributors. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#include + +#include "uv.h" +#include "../uv-common.h" +#include "internal.h" + + +sRtlNtStatusToDosError pRtlNtStatusToDosError; +sNtQueryInformationFile pNtQueryInformationFile; + + +void uv_winapi_init() { + HMODULE module; + + module = GetModuleHandleA("ntdll.dll"); + if (module == NULL) { + uv_fatal_error(GetLastError(), "GetModuleHandleA"); + } + + pRtlNtStatusToDosError = (sRtlNtStatusToDosError) GetProcAddress(module, + "RtlNtStatusToDosError"); + if (pRtlNtStatusToDosError == NULL) { + uv_fatal_error(GetLastError(), "GetProcAddress"); + } + + pNtQueryInformationFile = (sNtQueryInformationFile) GetProcAddress(module, + "NtQueryInformationFile"); + if (pNtQueryInformationFile == NULL) { + uv_fatal_error(GetLastError(), "GetProcAddress"); + } +} \ No newline at end of file diff --git a/deps/uv/test/echo-server.c b/deps/uv/test/echo-server.c index a912dfebba3..f75d38858a0 100644 --- a/deps/uv/test/echo-server.c +++ b/deps/uv/test/echo-server.c @@ -90,7 +90,7 @@ static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { return; } - /* + /* * Scan for the letter Q which signals that we should quit the server. * If we get QS it means close the stream. */ @@ -99,7 +99,7 @@ static void after_read(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { if (buf.base[i] == 'Q') { if (i + 1 < nread && buf.base[i + 1] == 'S') { free(buf.base); - uv_close((uv_handle_t*)handle, NULL); + uv_close((uv_handle_t*)handle, on_close); return; } else { uv_close(server, on_server_close);