diff --git a/CHANGES.rst b/CHANGES.rst index daf31a041..01a3c2a01 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -7,7 +7,7 @@ 1.3.5 (unreleased) ================== -- Nothing changed yet. +- Update the bundled libuv from 1.20.1 to 1.22.0. - Update Python versions tested on Travis, including PyPy to 6.0. See :issue:`1195`. diff --git a/deps/libuv/AUTHORS b/deps/libuv/AUTHORS index bb564ac75..ef3d5e181 100644 --- a/deps/libuv/AUTHORS +++ b/deps/libuv/AUTHORS @@ -336,3 +336,12 @@ Bob Burger Thomas Versteeg zzzjim Alex Arslan +Kyle Farnung +ssrlive <30760636+ssrlive@users.noreply.github.com> +Tobias Nießen +Björn Linse +zyxwvu Shi +Peter Johnson +Paolo Greppi +Shelley Vohr +Ujjwal Sharma diff --git a/deps/libuv/CMakeLists.txt b/deps/libuv/CMakeLists.txt new file mode 100644 index 000000000..a133edb85 --- /dev/null +++ b/deps/libuv/CMakeLists.txt @@ -0,0 +1,380 @@ +# TODO: determine CMAKE_SYSTEM_NAME on OS/390. Currently assumes "OS/390". +cmake_minimum_required(VERSION 3.0) +project(libuv) +enable_testing() + +if(MSVC) + list(APPEND uv_cflags /W4) +elseif(CMAKE_C_COMPILER_ID MATCHES "AppleClang|Clang|GNU") + list(APPEND uv_cflags -fvisibility=hidden --std=gnu89) + list(APPEND uv_cflags -Wall -Wextra -Wstrict-prototypes) + list(APPEND uv_cflags -Wno-unused-parameter) +endif() + +set(uv_sources + src/fs-poll.c + src/inet.c + src/threadpool.c + src/timer.c + src/uv-common.c + src/uv-data-getter-setters.c + src/version.c) + +set(uv_test_sources + test/blackhole-server.c + test/echo-server.c + test/run-tests.c + test/runner.c + test/test-active.c + test/test-async-null-cb.c + test/test-async.c + test/test-barrier.c + test/test-callback-order.c + test/test-callback-stack.c + test/test-close-fd.c + test/test-close-order.c + test/test-condvar.c + test/test-connect-unspecified.c + test/test-connection-fail.c + test/test-cwd-and-chdir.c + test/test-default-loop-close.c + test/test-delayed-accept.c + test/test-dlerror.c + test/test-eintr-handling.c + test/test-embed.c + test/test-emfile.c + test/test-env-vars.c + test/test-error.c + test/test-fail-always.c + test/test-fork.c + test/test-fs-copyfile.c + test/test-fs-event.c + test/test-fs-poll.c + test/test-fs.c + test/test-get-currentexe.c + test/test-get-loadavg.c + test/test-get-memory.c + test/test-get-passwd.c + test/test-getaddrinfo.c + test/test-gethostname.c + test/test-getnameinfo.c + test/test-getsockname.c + test/test-getters-setters.c + test/test-handle-fileno.c + test/test-homedir.c + test/test-hrtime.c + test/test-idle.c + test/test-ip4-addr.c + test/test-ip6-addr.c + test/test-ip6-addr.c + test/test-ipc-heavy-traffic-deadlock-bug.c + test/test-ipc-send-recv.c + test/test-ipc.c + test/test-loop-alive.c + test/test-loop-close.c + test/test-loop-configure.c + test/test-loop-handles.c + test/test-loop-stop.c + test/test-loop-time.c + test/test-multiple-listen.c + test/test-mutexes.c + test/test-osx-select.c + test/test-pass-always.c + test/test-ping-pong.c + test/test-pipe-bind-error.c + test/test-pipe-close-stdout-read-stdin.c + test/test-pipe-connect-error.c + test/test-pipe-connect-multiple.c + test/test-pipe-connect-prepare.c + test/test-pipe-getsockname.c + test/test-pipe-pending-instances.c + test/test-pipe-sendmsg.c + test/test-pipe-server-close.c + test/test-pipe-set-fchmod.c + test/test-pipe-set-non-blocking.c + test/test-platform-output.c + test/test-poll-close-doesnt-corrupt-stack.c + test/test-poll-close.c + test/test-poll-closesocket.c + test/test-poll-oob.c + test/test-poll.c + test/test-process-title-threadsafe.c + test/test-process-title.c + test/test-queue-foreach-delete.c + test/test-ref.c + test/test-run-nowait.c + test/test-run-once.c + test/test-semaphore.c + test/test-shutdown-close.c + test/test-shutdown-eof.c + test/test-shutdown-twice.c + test/test-signal-multiple-loops.c + test/test-signal.c + test/test-socket-buffer-size.c + test/test-spawn.c + test/test-stdio-over-pipes.c + test/test-tcp-alloc-cb-fail.c + test/test-tcp-bind-error.c + test/test-tcp-bind6-error.c + test/test-tcp-close-accept.c + test/test-tcp-close-while-connecting.c + test/test-tcp-close.c + test/test-tcp-connect-error-after-write.c + test/test-tcp-connect-error.c + test/test-tcp-connect-timeout.c + test/test-tcp-connect6-error.c + test/test-tcp-create-socket-early.c + test/test-tcp-flags.c + test/test-tcp-oob.c + test/test-tcp-open.c + test/test-tcp-read-stop.c + test/test-tcp-shutdown-after-write.c + test/test-tcp-try-write.c + test/test-tcp-unexpected-read.c + test/test-tcp-write-after-connect.c + test/test-tcp-write-fail.c + test/test-tcp-write-queue-order.c + test/test-tcp-write-to-half-open-connection.c + test/test-tcp-writealot.c + test/test-thread-equal.c + test/test-thread.c + test/test-threadpool-cancel.c + test/test-threadpool.c + test/test-timer-again.c + test/test-timer-from-check.c + test/test-timer.c + test/test-tmpdir.c + test/test-tty.c + test/test-udp-alloc-cb-fail.c + test/test-udp-bind.c + test/test-udp-create-socket-early.c + test/test-udp-dgram-too-big.c + test/test-udp-ipv6.c + test/test-udp-multicast-interface.c + test/test-udp-multicast-interface6.c + test/test-udp-multicast-join.c + test/test-udp-multicast-join6.c + test/test-udp-multicast-ttl.c + test/test-udp-open.c + test/test-udp-options.c + test/test-udp-send-and-recv.c + test/test-udp-send-hang-loop.c + test/test-udp-send-immediate.c + test/test-udp-send-unreachable.c + test/test-udp-try-send.c + test/test-walk-handles.c + test/test-watcher-cross-stop.c) + +if(WIN32) + list(APPEND uv_defines WIN32_LEAN_AND_MEAN _WIN32_WINNT=0x0600) + list(APPEND uv_libraries + advapi32 + iphlpapi + psapi + shell32 + user32 + userenv + ws2_32) + list(APPEND uv_sources + src/win/async.c + src/win/core.c + src/win/detect-wakeup.c + src/win/dl.c + src/win/error.c + src/win/fs.c + src/win/fs-event.c + src/win/getaddrinfo.c + src/win/getnameinfo.c + src/win/handle.c + src/win/loop-watcher.c + src/win/pipe.c + src/win/thread.c + src/win/poll.c + src/win/process.c + src/win/process-stdio.c + src/win/req.c + src/win/signal.c + src/win/snprintf.c + src/win/stream.c + src/win/tcp.c + src/win/tty.c + src/win/udp.c + src/win/util.c + src/win/winapi.c + src/win/winsock.c) + list(APPEND uv_test_libraries ws2_32) + list(APPEND uv_test_sources src/win/snprintf.c test/runner-win.c) +else() + list(APPEND uv_defines _FILE_OFFSET_BITS=64 _LARGEFILE_SOURCE) + list(APPEND uv_libraries pthread) + list(APPEND uv_sources + src/unix/async.c + src/unix/core.c + src/unix/dl.c + src/unix/fs.c + src/unix/getaddrinfo.c + src/unix/getnameinfo.c + src/unix/loop-watcher.c + src/unix/loop.c + src/unix/pipe.c + src/unix/poll.c + src/unix/process.c + src/unix/signal.c + src/unix/stream.c + src/unix/tcp.c + src/unix/thread.c + src/unix/tty.c + src/unix/udp.c) + list(APPEND uv_test_sources test/runner-unix.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "AIX") + list(APPEND uv_defines + _ALL_SOURCE + _LINUX_SOURCE_COMPAT + _THREAD_SAFE + _XOPEN_SOURCE=500) + list(APPEND uv_libraries perfstat) + list(APPEND uv_sources src/unix/aix.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Android") + list(APPEND uv_libs dl) + list(APPEND uv_sources + src/unix/android-ifaddrs.c + src/unix/linux-core.c + src/unix/linux-inotify.c + src/unix/linux-syscalls.c + src/unix/procfs-exepath.c + src/unix/pthread-fixes.c + src/unix/sysinfo-loadavg.c + src/unix/sysinfo-memory.c) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Android|Darwin|Linux|OS/390") + list(APPEND uv_sources src/unix/proctitle.c) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD") + list(APPEND uv_sources src/unix/freebsd.c) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD|NetBSD|OpenBSD") + list(APPEND uv_sources src/unix/posix-hrtime.c) + list(APPEND uv_libraries kvm) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|NetBSD|OpenBSD") + list(APPEND uv_sources src/unix/bsd-ifaddrs.c src/unix/kqueue.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") + list(APPEND uv_defines _DARWIN_UNLIMITED_SELECT=1 _DARWIN_USE_64_BIT_INODE=1) + list(APPEND uv_sources + src/unix/darwin-proctitle.c + src/unix/darwin.c + src/unix/fsevents.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "Linux") + list(APPEND uv_defines _GNU_SOURCE _POSIX_C_SOURCE=200112) + list(APPEND uv_libraries dl rt) + list(APPEND uv_sources + src/unix/linux-core.c + src/unix/linux-inotify.c + src/unix/linux-syscalls.c + src/unix/procfs-exepath.c + src/unix/sysinfo-loadavg.c + src/unix/sysinfo-memory.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "NetBSD") + list(APPEND uv_sources src/unix/netbsd.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "OpenBSD") + list(APPEND uv_sources src/unix/openbsd.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "OS/390") + list(APPEND uv_defines PATH_MAX=255) + list(APPEND uv_defines _AE_BIMODAL) + list(APPEND uv_defines _ALL_SOURCE) + list(APPEND uv_defines _LARGE_TIME_API) + list(APPEND uv_defines _OPEN_MSGQ_EXT) + list(APPEND uv_defines _OPEN_SYS_FILE_EXT) + list(APPEND uv_defines _OPEN_SYS_IF_EXT) + list(APPEND uv_defines _OPEN_SYS_SOCK_IPV6) + list(APPEND uv_defines _UNIX03_SOURCE) + list(APPEND uv_defines _UNIX03_THREADS) + list(APPEND uv_defines _UNIX03_WITHDRAWN) + list(APPEND uv_defines _XOPEN_SOURCE_EXTENDED) + list(APPEND uv_sources + src/unix/pthread-fixes.c + src/unix/pthread-barrier.c + src/unix/os390.c + src/unix/os390-syscalls.c) +endif() + +if(CMAKE_SYSTEM_NAME STREQUAL "SunOS") + list(APPEND uv_defines __EXTENSIONS__ _XOPEN_SOURCE=500) + list(APPEND uv_libraries kstat nsl sendfile socket) + list(APPEND uv_sources src/unix/no-proctitle.c src/unix/sunos.c) +endif() + +if(CMAKE_SYSTEM_NAME MATCHES "Darwin|DragonFly|FreeBSD|Linux|NetBSD|OpenBSD") + list(APPEND uv_test_libraries util) +endif() + +add_library(uv SHARED ${uv_sources}) +target_compile_definitions(uv PRIVATE ${uv_defines} BUILDING_UV_SHARED=1) +target_compile_options(uv PRIVATE ${uv_cflags}) +target_include_directories(uv PRIVATE include src) +target_link_libraries(uv ${uv_libraries}) + +add_library(uv_a STATIC ${uv_sources}) +target_compile_definitions(uv_a PRIVATE ${uv_defines}) +target_compile_options(uv_a PRIVATE ${uv_cflags}) +target_include_directories(uv_a PRIVATE include src) +target_link_libraries(uv_a ${uv_libraries}) + +if(BUILD_TESTING) + include(CTest) + add_executable(uv_run_tests ${uv_test_sources}) + target_compile_definitions(uv_run_tests PRIVATE ${uv_defines}) + target_compile_options(uv_run_tests PRIVATE ${uv_cflags}) + target_include_directories(uv_run_tests PRIVATE include) + target_link_libraries(uv_run_tests uv ${uv_test_libraries}) + add_test(NAME uv_test + COMMAND uv_run_tests + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + add_executable(uv_run_tests_a ${uv_test_sources}) + target_compile_definitions(uv_run_tests_a PRIVATE ${uv_defines}) + target_compile_options(uv_run_tests_a PRIVATE ${uv_cflags}) + target_include_directories(uv_run_tests_a PRIVATE include) + target_link_libraries(uv_run_tests_a uv_a ${uv_test_libraries}) + add_test(NAME uv_test_a + COMMAND uv_run_tests_a + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) +endif() + +if(UNIX) + # Now for some gibbering horrors from beyond the stars... + include(GNUInstallDirs) + foreach(x ${uv_libraries}) + set(LIBS "${LIBS} -l${x}") + endforeach(x) + file(STRINGS configure.ac configure_ac REGEX ^AC_INIT) + string(REGEX MATCH [0-9]+[.][0-9]+[.][0-9]+ PACKAGE_VERSION "${configure_ac}") + set(includedir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}) + set(libdir ${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}) + set(prefix ${CMAKE_INSTALL_PREFIX}) + configure_file(libuv.pc.in ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc @ONLY) + + install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}) + install(FILES LICENSE DESTINATION ${CMAKE_INSTALL_DOCDIR}) + install(FILES LICENSE ${CMAKE_CURRENT_BINARY_DIR}/libuv.pc + DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) + install(TARGETS uv LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) + install(TARGETS uv_a ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}) +endif() diff --git a/deps/libuv/CONTRIBUTING.md b/deps/libuv/CONTRIBUTING.md index d9bf0472f..f22e124e3 100644 --- a/deps/libuv/CONTRIBUTING.md +++ b/deps/libuv/CONTRIBUTING.md @@ -137,7 +137,10 @@ $ git rebase upstream/v1.x # or upstream/master ### TEST Bug fixes and features should come with tests. Add your tests in the -`test/` directory. Each new test needs to be registered in `test/test-list.h`. If you add a new test file, it needs to be registered in two places: +`test/` directory. Each new test needs to be registered in `test/test-list.h`. + +If you add a new test file, it needs to be registered in three places: +- `CMakeLists.txt`: add the file's name to the `uv_test_sources` list. - `Makefile.am`: add the file's name to the `test_run_tests_SOURCES` list. - `uv.gyp`: add the file's name to the `sources` list in the `run-tests` target. diff --git a/deps/libuv/ChangeLog b/deps/libuv/ChangeLog index 2af2302dc..5cd862152 100644 --- a/deps/libuv/ChangeLog +++ b/deps/libuv/ChangeLog @@ -1,4 +1,166 @@ -2018.04.19, Version 1.20.1 (Stable) +2018.07.11, Version 1.22.0 (Stable) + +Changes since version 1.21.0: + +* unix: remove checksparse.sh (Ben Noordhuis) + +* win: fix mingw build error (Ben Noordhuis) + +* win: fix -Wunused-function warnings in thread.c (Ben Noordhuis) + +* unix,win: merge timers implementation (Ben Noordhuis) + +* win: fix pointer type in pipe.c (Ben Noordhuis) + +* win: fixing build for older MSVC compilers (Michael Fero) + +* zos: clear poll events on every iteration (jBarz) + +* zos: write-protect message queue (jBarz) + +* zos: use correct pointer type in strnlen (jBarz) + +* unix,win: merge handle flags (Ben Noordhuis) + +* doc: update Imran Iqbal's GitHub handle (cjihrig) + +* src: add new error apis to prevent memory leaks (Shelley Vohr) + +* test: make test-condvar call uv_cond_wait (Jamie Davis) + +* fs: change position of uv_fs_lchown (Ujjwal Sharma) + + +2018.06.23, Version 1.21.0 (Stable), e4983a9b0c152932f7553ff4a9ff189d2314cdcb + +Changes since version 1.20.3: + +* unix,windows: map EFTYPE errno (cjihrig) + +* win: perform case insensitive PATH= comparison (cjihrig) + +* win, fs: uv_fs_fchmod support for -A files (Bartosz Sosnowski) + +* src,lib: fix comments (Tobias Nießen) + +* win,process: allow child pipe handles to be opened in overlapped mode (Björn + Linse) + +* src,test: fix idiosyncratic comment style (Bert Belder) + +* test: fs_fchmod_archive_readonly must return a value (Bert Belder) + +* win,pipe: fix incorrect error code returned from uv_pipe_write_impl() (Bert + Belder) + +* win,pipe: properly set uv_write_t.send_handle in uv_write2() (Bert Belder) + +* test: add vectored uv_write() ping-pong tests (Bert Belder) + +* win,pipe: support vectored uv_write() calls (Bert Belder) + +* win,pipe: refactor pipe read cancellation logic (Bert Belder) + +* test: improve output from IPC test helpers (Bert Belder) + +* test: add test for IPC deadlock on Windows ( + +* win,pipe: fix IPC pipe deadlock (Bert Belder) + +* unix: catch some cases of watching fd twice (Ben Noordhuis) + +* test: use custom timeout for getaddrinfo_fail_sync (Ben Noordhuis) + +* Revert "win: add Windows XP support to uv_if_indextoname()" (Bert Belder) + +* win,thread: remove fallback uv_cond implementation (Bert Belder) + +* src,test: s/olny/only (cjihrig) + +* unix: close signal pipe fds on unload (Ben Noordhuis) + +* win: allow setting udp socket options before bind (cjihrig) + +* unix: return UV_ENOTSUP on FICLONE_FORCE failure (cjihrig) + +* win,pipe: remove unreferenced local variable (Bert Belder) + +* win,code: remove GetQueuedCompletionStatus-based poller (Bert Belder) + +* win: remove the remaining dynamic kernel32 imports (Bert Belder) + +* test: speedup process-title-threadsafe on macOS (cjihrig) + +* core: move all include files except uv.h to uv/ (Saúl Ibarra Corretgé) + +* win: move stdint-msvc2008.h to include/uv/ (Ben Noordhuis) + +* build: fix cygwin install (Ben Noordhuis) + +* build,win: remove MinGW Makefile (Saúl Ibarra Corretgé) + +* build: add a cmake build file (Ben Noordhuis) + +* build: add test suite option to cmake build (Ben Noordhuis) + +* unix: set errno in uv_fs_copyfile() (cjihrig) + +* samples: fix inconsistency in parse_opts vs usage (zyxwvu Shi) + +* linux: handle exclusive POLLHUP with UV_DISCONNECT (Brad King) + +* include: declare uv_cpu_times_s in higher scope (Peter Johnson) + +* doc: add uv_fs_fsync() AIX limitations (jBarz) + +* unix,win: add uv_fs_lchown() (Paolo Greppi) + +* unix: disable clang variable length array warning (Peter Johnson) + +* doc: document uv_pipe_t::ipc (Ed Schouten) + +* doc: undocument uv_req_type's UV_REQ_TYPE_PRIVATE (Ed Schouten) + +* doc: document UV_*_MAP() macros (Ed Schouten) + +* win: remove use of min() macro in pipe.c (Peter Johnson) + +* doc: add jbarz as maintainer ( + + +2018.05.08, Version 1.20.3 (Stable), 8cfd67e59195251dff793ee47c185c9d6a8f3818 + +Changes since version 1.20.2: + +* win: add Windows XP support to uv_if_indextoname() (ssrlive) + +* win: fix `'floor' undefined` compiler warning (ssrlive) + +* win, pipe: stop read for overlapped pipe (Bartosz Sosnowski) + +* build: fix utf-8 name of copyright holder (Jérémy Lal) + +* zos: initialize pollfd revents (jBarz) + +* zos,doc: add system V message queue note (jBarz) + +* linux: don't use uv__nonblock_ioctl() on sparc (Ben Noordhuis) + + +2018.04.23, Version 1.20.2 (Stable), c51fd3f66bbb386a1efdeba6812789f35a372d1e + +Changes since version 1.20.1: + +* zos: use custom semaphore (jBarz) + +* win: fix registry API error handling (Kyle Farnung) + +* build: add support for 64-bit AIX (Richard Lau) + +* aix: guard STATIC_ASSERT for glibc work around (Richard Lau) + + +2018.04.19, Version 1.20.1 (Stable), 36ac2fc8edfd5ff3e9be529be1d4a3f0d5364e94 Changes since version 1.20.0: diff --git a/deps/libuv/MAINTAINERS.md b/deps/libuv/MAINTAINERS.md index d85deb006..889ee4988 100644 --- a/deps/libuv/MAINTAINERS.md +++ b/deps/libuv/MAINTAINERS.md @@ -12,8 +12,9 @@ libuv is currently managed by the following individuals: - GPG key: 5735 3E0D BDAA A7E8 39B6 6A1A FF47 D5E4 AD8B 4FDC (pubkey-cjihrig-kb) * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) -* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) +* **Imran Iqbal** ([@imran-iq](https://github.com/imran-iq)) - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) +* **John Barboza** ([@jbarz](https://github.com/jbarz)) * **Santiago Gimeno** ([@santigimeno](https://github.com/santigimeno)) - GPG key: 612F 0EAD 9401 6223 79DF 4402 F28C 3C8D A33C 03BE (pubkey-santigimeno) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) diff --git a/deps/libuv/Makefile.am b/deps/libuv/Makefile.am index ae9d96bcf..04aecab55 100644 --- a/deps/libuv/Makefile.am +++ b/deps/libuv/Makefile.am @@ -17,7 +17,10 @@ ACLOCAL_AMFLAGS = -I m4 AM_CPPFLAGS = -I$(top_srcdir)/include \ -I$(top_srcdir)/src -include_HEADERS=include/uv.h include/uv-errno.h include/uv-threadpool.h include/uv-version.h +include_HEADERS=include/uv.h + +uvincludedir = $(includedir)/uv +uvinclude_HEADERS=include/uv/errno.h include/uv/threadpool.h include/uv/version.h CLEANFILES = @@ -29,6 +32,7 @@ libuv_la_SOURCES = src/fs-poll.c \ src/inet.c \ src/queue.h \ src/threadpool.c \ + src/timer.c \ src/uv-data-getter-setters.c \ src/uv-common.c \ src/uv-common.h \ @@ -42,7 +46,7 @@ endif if WINNT -include_HEADERS += include/uv-win.h include/tree.h +uvinclude_HEADERS += include/uv/win.h include/uv/tree.h AM_CPPFLAGS += -I$(top_srcdir)/src/win \ -DWIN32_LEAN_AND_MEAN \ -D_WIN32_WINNT=0x0600 @@ -71,7 +75,6 @@ libuv_la_SOURCES += src/win/async.c \ src/win/stream-inl.h \ src/win/tcp.c \ src/win/thread.c \ - src/win/timer.c \ src/win/tty.c \ src/win/udp.c \ src/win/util.c \ @@ -82,7 +85,7 @@ libuv_la_SOURCES += src/win/async.c \ else # WINNT -include_HEADERS += include/uv-unix.h +uvinclude_HEADERS += include/uv/unix.h AM_CPPFLAGS += -I$(top_srcdir)/src/unix libuv_la_SOURCES += src/unix/async.c \ src/unix/atomic-ops.h \ @@ -102,7 +105,6 @@ libuv_la_SOURCES += src/unix/async.c \ src/unix/stream.c \ src/unix/tcp.c \ src/unix/thread.c \ - src/unix/timer.c \ src/unix/tty.c \ src/unix/udp.c @@ -121,7 +123,6 @@ EXTRA_DIST = test/fixtures/empty_file \ README.md \ checksparse.sh \ vcbuild.bat \ - Makefile.mingw \ common.gypi \ gyp_uv.py \ uv.gyp @@ -191,6 +192,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-idle.c \ test/test-ip4-addr.c \ test/test-ip6-addr.c \ + test/test-ipc-heavy-traffic-deadlock-bug.c \ test/test-ipc-send-recv.c \ test/test-ipc.c \ test/test-list.h \ @@ -332,19 +334,19 @@ libuv_la_CFLAGS += -D_ALL_SOURCE \ -D_LINUX_SOURCE_COMPAT \ -D_THREAD_SAFE \ -DHAVE_SYS_AHAFS_EVPRODS_H -include_HEADERS += include/uv-aix.h +uvinclude_HEADERS += include/uv/aix.h libuv_la_SOURCES += src/unix/aix.c src/unix/aix-common.c endif if ANDROID -include_HEADERS += include/android-ifaddrs.h \ - include/pthread-barrier.h +uvinclude_HEADERS += include/uv/android-ifaddrs.h \ + include/uv/pthread-barrier.h libuv_la_SOURCES += src/unix/android-ifaddrs.c \ src/unix/pthread-fixes.c endif if CYGWIN -include_HEADERS += include/uv-posix.h +uvinclude_HEADERS += include/uv/posix.h libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/cygwin.c \ src/unix/bsd-ifaddrs.c \ @@ -358,8 +360,8 @@ libuv_la_SOURCES += src/unix/cygwin.c \ endif if DARWIN -include_HEADERS += include/uv-darwin.h \ - include/pthread-barrier.h +uvinclude_HEADERS += include/uv/darwin.h \ + include/uv/pthread-barrier.h libuv_la_CFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 libuv_la_CFLAGS += -D_DARWIN_UNLIMITED_SELECT=1 libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ @@ -372,7 +374,7 @@ test_run_tests_LDFLAGS += -lutil endif if DRAGONFLY -include_HEADERS += include/uv-bsd.h +uvinclude_HEADERS += include/uv/bsd.h libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/freebsd.c \ src/unix/kqueue.c \ @@ -381,7 +383,7 @@ test_run_tests_LDFLAGS += -lutil endif if FREEBSD -include_HEADERS += include/uv-bsd.h +uvinclude_HEADERS += include/uv/bsd.h libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/freebsd.c \ src/unix/kqueue.c \ @@ -390,7 +392,7 @@ test_run_tests_LDFLAGS += -lutil endif if LINUX -include_HEADERS += include/uv-linux.h +uvinclude_HEADERS += include/uv/linux.h libuv_la_CFLAGS += -D_GNU_SOURCE libuv_la_SOURCES += src/unix/linux-core.c \ src/unix/linux-inotify.c \ @@ -417,7 +419,7 @@ libuv_la_SOURCES += src/unix/cygwin.c \ endif if NETBSD -include_HEADERS += include/uv-bsd.h +uvinclude_HEADERS += include/uv/bsd.h libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/kqueue.c \ src/unix/netbsd.c \ @@ -426,7 +428,7 @@ test_run_tests_LDFLAGS += -lutil endif if OPENBSD -include_HEADERS += include/uv-bsd.h +uvinclude_HEADERS += include/uv/bsd.h libuv_la_SOURCES += src/unix/bsd-ifaddrs.c \ src/unix/kqueue.c \ src/unix/openbsd.c \ @@ -435,14 +437,14 @@ test_run_tests_LDFLAGS += -lutil endif if SUNOS -include_HEADERS += include/uv-sunos.h +uvinclude_HEADERS += include/uv/sunos.h libuv_la_CFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 libuv_la_SOURCES += src/unix/no-proctitle.c \ src/unix/sunos.c endif if OS390 -include_HEADERS += include/pthread-barrier.h +uvinclude_HEADERS += include/uv/pthread-barrier.h libuv_la_CFLAGS += -D_UNIX03_THREADS \ -D_UNIX03_SOURCE \ -D_OPEN_SYS_IF_EXT=1 \ diff --git a/deps/libuv/Makefile.mingw b/deps/libuv/Makefile.mingw deleted file mode 100644 index 3acf9e14a..000000000 --- a/deps/libuv/Makefile.mingw +++ /dev/null @@ -1,86 +0,0 @@ -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -CC ?= gcc - -CFLAGS += -Wall \ - -Wextra \ - -Wno-unused-parameter \ - -Wstrict-prototypes \ - -Iinclude \ - -Isrc \ - -Isrc/win \ - -DWIN32_LEAN_AND_MEAN \ - -D_WIN32_WINNT=0x0600 - -INCLUDES = include/stdint-msvc2008.h \ - include/tree.h \ - include/uv-errno.h \ - include/uv-threadpool.h \ - include/uv-version.h \ - include/uv-win.h \ - include/uv.h \ - src/heap-inl.h \ - src/queue.h \ - src/uv-common.h \ - src/win/atomicops-inl.h \ - src/win/handle-inl.h \ - src/win/internal.h \ - src/win/req-inl.h \ - src/win/stream-inl.h \ - src/win/winapi.h \ - src/win/winsock.h - -OBJS = src/fs-poll.o \ - src/inet.o \ - src/threadpool.o \ - src/uv-common.o \ - src/version.o \ - src/win/async.o \ - src/win/core.o \ - src/win/detect-wakeup.o \ - src/win/dl.o \ - src/win/error.o \ - src/win/fs-event.o \ - src/win/fs.o \ - src/win/getaddrinfo.o \ - src/win/getnameinfo.o \ - src/win/handle.o \ - src/win/loop-watcher.o \ - src/win/pipe.o \ - src/win/poll.o \ - src/win/process-stdio.o \ - src/win/process.o \ - src/win/req.o \ - src/win/signal.o \ - src/win/stream.o \ - src/win/tcp.o \ - src/win/thread.o \ - src/win/timer.o \ - src/win/tty.o \ - src/win/udp.o \ - src/win/util.o \ - src/win/winapi.o \ - src/win/winsock.o - -all: libuv.a - -clean: - -$(RM) $(OBJS) libuv.a - -libuv.a: $(OBJS) - $(AR) crs $@ $^ - -$(OBJS): %.o : %.c $(INCLUDES) - $(CC) $(CFLAGS) -c -o $@ $< diff --git a/deps/libuv/README.md b/deps/libuv/README.md index 1aaed1a88..f6e7288de 100644 --- a/deps/libuv/README.md +++ b/deps/libuv/README.md @@ -169,6 +169,16 @@ $ make check $ make install ``` +To build with [CMake](https://cmake.org/): + +```bash +$ mkdir -p out/cmake ; cd out/cmake ; cmake -DBUILD_TESTING=ON ../.. +$ make all test +# Or manually: +$ ./uv_run_tests # shared library build +$ ./uv_run_tests_a # static library build +``` + To build with GYP, first run: ```bash @@ -322,6 +332,13 @@ describes the package in more detail. AIX support for filesystem events is not compiled when building with `gyp`. +### z/OS Notes + +z/OS creates System V semaphores and message queues. These persist on the system +after the process terminates unless the event loop is closed. + +Use the `ipcrm` command to manually clear up System V resources. + ## Patches See the [guidelines for contributing][]. diff --git a/deps/libuv/checksparse.sh b/deps/libuv/checksparse.sh deleted file mode 100755 index d8b50bc4f..000000000 --- a/deps/libuv/checksparse.sh +++ /dev/null @@ -1,253 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2013, Ben Noordhuis -# -# Permission to use, copy, modify, and/or distribute this software for any -# purpose with or without fee is hereby granted, provided that the above -# copyright notice and this permission notice appear in all copies. -# -# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - -SPARSE=${SPARSE:-sparse} - -SPARSE_FLAGS=${SPARSE_FLAGS:-" --D__POSIX__ --Wsparse-all --Wno-do-while --Wno-transparent-union --Iinclude --Isrc -"} - -SOURCES=" -include/tree.h -include/uv-unix.h -include/uv.h -src/fs-poll.c -src/inet.c -src/queue.h -src/unix/async.c -src/unix/core.c -src/unix/dl.c -src/unix/fs.c -src/unix/getaddrinfo.c -src/unix/internal.h -src/unix/loop-watcher.c -src/unix/loop.c -src/unix/pipe.c -src/unix/poll.c -src/unix/process.c -src/unix/signal.c -src/unix/stream.c -src/unix/tcp.c -src/unix/thread.c -src/unix/threadpool.c -src/unix/timer.c -src/unix/tty.c -src/unix/udp.c -src/uv-common.c -src/uv-common.h -src/uv-data-getter-setters.c -" - -TESTS=" -test/benchmark-async-pummel.c -test/benchmark-async.c -test/benchmark-fs-stat.c -test/benchmark-getaddrinfo.c -test/benchmark-loop-count.c -test/benchmark-million-async.c -test/benchmark-million-timers.c -test/benchmark-multi-accept.c -test/benchmark-ping-pongs.c -test/benchmark-pound.c -test/benchmark-pump.c -test/benchmark-sizes.c -test/benchmark-spawn.c -test/benchmark-tcp-write-batch.c -test/benchmark-thread.c -test/benchmark-udp-pummel.c -test/blackhole-server.c -test/dns-server.c -test/echo-server.c -test/run-benchmarks.c -test/run-tests.c -test/runner-unix.c -test/runner-unix.h -test/runner.c -test/runner.h -test/task.h -test/test-active.c -test/test-async.c -test/test-barrier.c -test/test-callback-order.c -test/test-callback-stack.c -test/test-condvar.c -test/test-connection-fail.c -test/test-cwd-and-chdir.c -test/test-delayed-accept.c -test/test-dlerror.c -test/test-embed.c -test/test-env-vars.c -test/test-error.c -test/test-fail-always.c -test/test-fs-copyfile.c -test/test-fs-event.c -test/test-fs-poll.c -test/test-fs.c -test/test-getters-setters.c -test/test-get-currentexe.c -test/test-get-loadavg.c -test/test-get-memory.c -test/test-get-passwd.c -test/test-getaddrinfo.c -test/test-gethostname.c -test/test-getsockname.c -test/test-homedir.c -test/test-hrtime.c -test/test-idle.c -test/test-ip6-addr.c -test/test-ipc-send-recv.c -test/test-ipc.c -test/test-loop-handles.c -test/test-multiple-listen.c -test/test-mutexes.c -test/test-pass-always.c -test/test-ping-pong.c -test/test-pipe-bind-error.c -test/test-pipe-connect-error.c -test/test-pipe-sendmsg.c -test/test-pipe-server-close.c -test/test-platform-output.c -test/test-poll-close.c -test/test-poll.c -test/test-process-title.c -test/test-process-title-threadsafe.c -test/test-ref.c -test/test-run-nowait.c -test/test-run-once.c -test/test-semaphore.c -test/test-shutdown-close.c -test/test-shutdown-eof.c -test/test-signal-multiple-loops.c -test/test-signal.c -test/test-spawn.c -test/test-stdio-over-pipes.c -test/test-tcp-bind-error.c -test/test-tcp-bind6-error.c -test/test-tcp-close-while-connecting.c -test/test-tcp-close-accept.c -test/test-tcp-close.c -test/test-tcp-connect-error-after-write.c -test/test-tcp-connect-error.c -test/test-tcp-connect-timeout.c -test/test-tcp-connect6-error.c -test/test-tcp-flags.c -test/test-tcp-open.c -test/test-tcp-read-stop.c -test/test-tcp-shutdown-after-write.c -test/test-tcp-unexpected-read.c -test/test-tcp-oob.c -test/test-tcp-write-error.c -test/test-tcp-write-to-half-open-connection.c -test/test-tcp-writealot.c -test/test-thread.c -test/test-threadpool-cancel.c -test/test-threadpool.c -test/test-timer-again.c -test/test-timer.c -test/test-tmpdir.c -test/test-tty.c -test/test-udp-dgram-too-big.c -test/test-udp-ipv6.c -test/test-udp-multicast-join.c -test/test-udp-multicast-ttl.c -test/test-udp-open.c -test/test-udp-options.c -test/test-udp-send-and-recv.c -test/test-udp-send-hang-loop.c -test/test-walk-handles.c -test/test-watcher-cross-stop.c -" - -case `uname -s` in -AIX) - SPARSE_FLAGS="$SPARSE_FLAGS -D_AIX=1" - SOURCES="$SOURCES - src/unix/aix-common.c - src/unix/aix.c" - ;; -OS400) - SPARSE_FLAGS="$SPARSE_FLAGS -D__PASE__=1" - SOURCES="$SOURCES - src/unix/aix-common.c - src/unix/ibmi.c - src/unix/posix-poll.c - src/unix/no-fsevents.c - src/unix/no-proctitle.c" - ;; -Darwin) - SPARSE_FLAGS="$SPARSE_FLAGS -D__APPLE__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/darwin.c - src/unix/kqueue.c - src/unix/fsevents.c" - ;; -DragonFly) - SPARSE_FLAGS="$SPARSE_FLAGS -D__DragonFly__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -FreeBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__FreeBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/freebsd.c" - ;; -Linux) - SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1" - SOURCES="$SOURCES - include/uv-linux.h - src/unix/linux-inotify.c - src/unix/linux-core.c - src/unix/linux-syscalls.c - src/unix/linux-syscalls.h" - ;; -NetBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/netbsd.c" - ;; -OpenBSD) - SPARSE_FLAGS="$SPARSE_FLAGS -D__OpenBSD__=1" - SOURCES="$SOURCES - include/uv-bsd.h - src/unix/kqueue.c - src/unix/openbsd.c" - ;; -SunOS) - SPARSE_FLAGS="$SPARSE_FLAGS -D__sun=1" - SOURCES="$SOURCES - include/uv-sunos.h - src/unix/sunos.c" - ;; -esac - -for ARCH in __i386__ __x86_64__ __arm__ __mips__; do - $SPARSE $SPARSE_FLAGS -D$ARCH=1 $SOURCES -done - -# Tests are architecture independent. -$SPARSE $SPARSE_FLAGS -Itest $TESTS diff --git a/deps/libuv/common.gypi b/deps/libuv/common.gypi index 572a1633b..2297bdf0f 100644 --- a/deps/libuv/common.gypi +++ b/deps/libuv/common.gypi @@ -134,7 +134,7 @@ }] ] }], - ['OS in "freebsd dragonflybsd linux openbsd solaris android"', { + ['OS in "freebsd dragonflybsd linux openbsd solaris android aix"', { 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], 'target_conditions': [ @@ -162,6 +162,10 @@ 'cflags': [ '-pthread' ], 'ldflags': [ '-pthread' ], }], + [ 'OS=="aix" and target_arch=="ppc64"', { + 'cflags': [ '-maix64' ], + 'ldflags': [ '-maix64' ], + }], ], }], ['OS=="mac"', { diff --git a/deps/libuv/configure.ac b/deps/libuv/configure.ac index 28fda9d39..aa6e6d16a 100644 --- a/deps/libuv/configure.ac +++ b/deps/libuv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [1.20.1], [https://github.com/libuv/libuv/issues]) +AC_INIT([libuv], [1.22.0], [https://github.com/libuv/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) m4_include([m4/as_case.m4]) diff --git a/deps/libuv/include/uv.h b/deps/libuv/include/uv.h index 41fad4510..a8b305793 100644 --- a/deps/libuv/include/uv.h +++ b/deps/libuv/include/uv.h @@ -45,21 +45,21 @@ extern "C" { # define UV_EXTERN /* nothing */ #endif -#include "uv-errno.h" -#include "uv-version.h" +#include "uv/errno.h" +#include "uv/version.h" #include #include #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include #endif #if defined(_WIN32) -# include "uv-win.h" +# include "uv/win.h" #else -# include "uv-unix.h" +# include "uv/unix.h" #endif /* Expand this list if necessary. */ @@ -142,6 +142,7 @@ extern "C" { XX(EHOSTDOWN, "host is down") \ XX(EREMOTEIO, "remote I/O error") \ XX(ENOTTY, "inappropriate ioctl for device") \ + XX(EFTYPE, "inappropriate file type or format") \ #define UV_HANDLE_TYPE_MAP(XX) \ XX(ASYNC, async) \ @@ -369,7 +370,10 @@ typedef enum { UV_EXTERN int uv_translate_sys_error(int sys_errno); UV_EXTERN const char* uv_strerror(int err); +UV_EXTERN char* uv_strerror_r(int err, char* buf, size_t buflen); + UV_EXTERN const char* uv_err_name(int err); +UV_EXTERN char* uv_err_name_r(int err, char* buf, size_t buflen); #define UV_REQ_FIELDS \ @@ -503,7 +507,7 @@ UV_EXTERN int uv_try_write(uv_stream_t* handle, struct uv_write_s { UV_REQ_FIELDS uv_write_cb cb; - uv_stream_t* send_handle; + uv_stream_t* send_handle; /* TODO: make private and unix-only in v2.x. */ uv_stream_t* handle; UV_WRITE_PRIVATE_FIELDS }; @@ -865,7 +869,13 @@ typedef enum { * flags may be specified to create a duplex data stream. */ UV_READABLE_PIPE = 0x10, - UV_WRITABLE_PIPE = 0x20 + UV_WRITABLE_PIPE = 0x20, + + /* + * Open the child pipe handle in overlapped mode on Windows. + * On Unix it is silently ignored. + */ + UV_OVERLAPPED_PIPE = 0x40 } uv_stdio_flags; typedef struct uv_stdio_container_s { @@ -997,16 +1007,18 @@ UV_EXTERN int uv_queue_work(uv_loop_t* loop, UV_EXTERN int uv_cancel(uv_req_t* req); +struct uv_cpu_times_s { + uint64_t user; + uint64_t nice; + uint64_t sys; + uint64_t idle; + uint64_t irq; +}; + struct uv_cpu_info_s { char* model; int speed; - struct uv_cpu_times_s { - uint64_t user; - uint64_t nice; - uint64_t sys; - uint64_t idle; - uint64_t irq; - } cpu_times; + struct uv_cpu_times_s cpu_times; }; struct uv_interface_address_s { @@ -1133,7 +1145,8 @@ typedef enum { UV_FS_CHOWN, UV_FS_FCHOWN, UV_FS_REALPATH, - UV_FS_COPYFILE + UV_FS_COPYFILE, + UV_FS_LCHOWN } uv_fs_type; /* uv_fs_t is a subclass of uv_req_t. */ @@ -1336,6 +1349,12 @@ UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb); enum uv_fs_event { diff --git a/deps/libuv/include/uv-aix.h b/deps/libuv/include/uv/aix.h similarity index 100% rename from deps/libuv/include/uv-aix.h rename to deps/libuv/include/uv/aix.h diff --git a/deps/libuv/include/android-ifaddrs.h b/deps/libuv/include/uv/android-ifaddrs.h similarity index 100% rename from deps/libuv/include/android-ifaddrs.h rename to deps/libuv/include/uv/android-ifaddrs.h diff --git a/deps/libuv/include/uv-bsd.h b/deps/libuv/include/uv/bsd.h similarity index 100% rename from deps/libuv/include/uv-bsd.h rename to deps/libuv/include/uv/bsd.h diff --git a/deps/libuv/include/uv-darwin.h b/deps/libuv/include/uv/darwin.h similarity index 100% rename from deps/libuv/include/uv-darwin.h rename to deps/libuv/include/uv/darwin.h diff --git a/deps/libuv/include/uv-errno.h b/deps/libuv/include/uv/errno.h similarity index 98% rename from deps/libuv/include/uv-errno.h rename to deps/libuv/include/uv/errno.h index aa4d4509f..8eeb95de3 100644 --- a/deps/libuv/include/uv-errno.h +++ b/deps/libuv/include/uv/errno.h @@ -433,5 +433,11 @@ # define UV__ENOTTY (-4029) #endif +#if defined(EFTYPE) && !defined(_WIN32) +# define UV__EFTYPE UV__ERR(EFTYPE) +#else +# define UV__EFTYPE (-4028) +#endif + #endif /* UV_ERRNO_H_ */ diff --git a/deps/libuv/include/uv-linux.h b/deps/libuv/include/uv/linux.h similarity index 100% rename from deps/libuv/include/uv-linux.h rename to deps/libuv/include/uv/linux.h diff --git a/deps/libuv/include/uv-os390.h b/deps/libuv/include/uv/os390.h similarity index 98% rename from deps/libuv/include/uv-os390.h rename to deps/libuv/include/uv/os390.h index 39e7384db..0267d74cb 100644 --- a/deps/libuv/include/uv-os390.h +++ b/deps/libuv/include/uv/os390.h @@ -22,7 +22,7 @@ #ifndef UV_MVS_H #define UV_MVS_H -#define UV_PLATFORM_SEM_T int +#define UV_PLATFORM_SEM_T long #define UV_PLATFORM_LOOP_FIELDS \ void* ep; \ diff --git a/deps/libuv/include/uv-posix.h b/deps/libuv/include/uv/posix.h similarity index 100% rename from deps/libuv/include/uv-posix.h rename to deps/libuv/include/uv/posix.h diff --git a/deps/libuv/include/pthread-barrier.h b/deps/libuv/include/uv/pthread-barrier.h similarity index 100% rename from deps/libuv/include/pthread-barrier.h rename to deps/libuv/include/uv/pthread-barrier.h diff --git a/deps/libuv/include/stdint-msvc2008.h b/deps/libuv/include/uv/stdint-msvc2008.h similarity index 100% rename from deps/libuv/include/stdint-msvc2008.h rename to deps/libuv/include/uv/stdint-msvc2008.h diff --git a/deps/libuv/include/uv-sunos.h b/deps/libuv/include/uv/sunos.h similarity index 100% rename from deps/libuv/include/uv-sunos.h rename to deps/libuv/include/uv/sunos.h diff --git a/deps/libuv/include/uv-threadpool.h b/deps/libuv/include/uv/threadpool.h similarity index 100% rename from deps/libuv/include/uv-threadpool.h rename to deps/libuv/include/uv/threadpool.h diff --git a/deps/libuv/include/tree.h b/deps/libuv/include/uv/tree.h similarity index 100% rename from deps/libuv/include/tree.h rename to deps/libuv/include/uv/tree.h diff --git a/deps/libuv/include/uv-unix.h b/deps/libuv/include/uv/unix.h similarity index 98% rename from deps/libuv/include/uv-unix.h rename to deps/libuv/include/uv/unix.h index 480a0691e..74a0d643c 100644 --- a/deps/libuv/include/uv-unix.h +++ b/deps/libuv/include/uv/unix.h @@ -42,32 +42,32 @@ #include #include -#include "uv-threadpool.h" +#include "uv/threadpool.h" #if defined(__linux__) -# include "uv-linux.h" +# include "uv/linux.h" #elif defined (__MVS__) -# include "uv-os390.h" +# include "uv/os390.h" #elif defined(__PASE__) -# include "uv-posix.h" +# include "uv/posix.h" #elif defined(_AIX) -# include "uv-aix.h" +# include "uv/aix.h" #elif defined(__sun) -# include "uv-sunos.h" +# include "uv/sunos.h" #elif defined(__APPLE__) -# include "uv-darwin.h" +# include "uv/darwin.h" #elif defined(__DragonFly__) || \ defined(__FreeBSD__) || \ defined(__FreeBSD_kernel__) || \ defined(__OpenBSD__) || \ defined(__NetBSD__) -# include "uv-bsd.h" +# include "uv/bsd.h" #elif defined(__CYGWIN__) || defined(__MSYS__) -# include "uv-posix.h" +# include "uv/posix.h" #endif #ifndef PTHREAD_BARRIER_SERIAL_THREAD -# include "pthread-barrier.h" +# include "uv/pthread-barrier.h" #endif #ifndef NI_MAXHOST diff --git a/deps/libuv/include/uv-version.h b/deps/libuv/include/uv/version.h similarity index 97% rename from deps/libuv/include/uv-version.h rename to deps/libuv/include/uv/version.h index de8f3f339..a990137f8 100644 --- a/deps/libuv/include/uv-version.h +++ b/deps/libuv/include/uv/version.h @@ -31,8 +31,8 @@ */ #define UV_VERSION_MAJOR 1 -#define UV_VERSION_MINOR 20 -#define UV_VERSION_PATCH 1 +#define UV_VERSION_MINOR 22 +#define UV_VERSION_PATCH 0 #define UV_VERSION_IS_RELEASE 1 #define UV_VERSION_SUFFIX "" diff --git a/deps/libuv/include/uv-win.h b/deps/libuv/include/uv/win.h similarity index 95% rename from deps/libuv/include/uv-win.h rename to deps/libuv/include/uv/win.h index 4c6c50a29..d6b8b3a7f 100644 --- a/deps/libuv/include/uv-win.h +++ b/deps/libuv/include/uv/win.h @@ -53,13 +53,13 @@ typedef struct pollfd { #include #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include #endif -#include "tree.h" -#include "uv-threadpool.h" +#include "uv/tree.h" +#include "uv/threadpool.h" #define MAX_PIPENAME_LEN 256 @@ -86,8 +86,8 @@ typedef struct pollfd { #define SIGKILL 9 #define SIGWINCH 28 -/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many */ -/* unix-like platforms. However MinGW doesn't define it, so we do. */ +/* The CRT defines SIGABRT_COMPAT as 6, which equals SIGABRT on many unix-like + * platforms. However MinGW doesn't define it, so we do. */ #ifndef SIGABRT_COMPAT # define SIGABRT_COMPAT 6 #endif @@ -244,7 +244,7 @@ typedef union { CRITICAL_SECTION waiters_count_lock; HANDLE signal_event; HANDLE broadcast_event; - } fallback; + } unused_; /* TODO: retained for ABI compatibility; remove me in v2.x. */ } uv_cond_t; typedef union { @@ -308,8 +308,6 @@ typedef struct { char* errmsg; } uv_lib_t; -RB_HEAD(uv_timer_tree_s, uv_timer_s); - #define UV_LOOP_PRIVATE_FIELDS \ /* The loop's I/O completion port */ \ HANDLE iocp; \ @@ -321,8 +319,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); uv_req_t* pending_reqs_tail; \ /* Head of a single-linked list of closed handles */ \ uv_handle_t* endgame_handles; \ - /* The head of the timers tree */ \ - struct uv_timer_tree_s timers; \ + /* TODO(bnoordhuis) Stop heap-allocating |timer_heap| in libuv v2.x. */ \ + void* timer_heap; \ /* Lists of active loop (prepare / check / idle) watchers */ \ uv_prepare_t* prepare_handles; \ uv_check_t* check_handles; \ @@ -368,10 +366,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); } u; \ struct uv_req_s* next_req; -#define UV_WRITE_PRIVATE_FIELDS \ - int ipc_header; \ - uv_buf_t write_buffer; \ - HANDLE event_handle; \ +#define UV_WRITE_PRIVATE_FIELDS \ + int coalesced; \ + uv_buf_t write_buffer; \ + HANDLE event_handle; \ HANDLE wait_handle; #define UV_CONNECT_PRIVATE_FIELDS \ @@ -459,16 +457,17 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); #define uv_pipe_connection_fields \ uv_timer_t* eof_timer; \ - uv_write_t ipc_header_write_req; \ - int ipc_pid; \ - uint64_t remaining_ipc_rawdata_bytes; \ - struct { \ - void* queue[2]; \ - int queue_len; \ - } pending_ipc_info; \ + uv_write_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \ + DWORD ipc_remote_pid; \ + union { \ + uint32_t payload_remaining; \ + uint64_t dummy; /* TODO: retained for ABI compat; remove this in v2.x. */ \ + } ipc_data_frame; \ + void* ipc_xfer_queue[2]; \ + int ipc_xfer_queue_length; \ uv_write_t* non_overlapped_writes_tail; \ - uv_mutex_t readfile_mutex; \ - volatile HANDLE readfile_thread; + CRITICAL_SECTION readfile_thread_lock; \ + volatile HANDLE readfile_thread_handle; #define UV_PIPE_PRIVATE_FIELDS \ HANDLE handle; \ @@ -478,8 +477,8 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); struct { uv_pipe_connection_fields } conn; \ } pipe; -/* TODO: put the parser states in an union - TTY handles are always */ -/* half-duplex so read-state can safely overlap write-state. */ +/* TODO: put the parser states in an union - TTY handles are always half-duplex + * so read-state can safely overlap write-state. */ #define UV_TTY_PRIVATE_FIELDS \ HANDLE handle; \ union { \ @@ -528,8 +527,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); unsigned char events; #define UV_TIMER_PRIVATE_FIELDS \ - RB_ENTRY(uv_timer_s) tree_entry; \ - uint64_t due; \ + void* heap_node[3]; \ + int unused; \ + uint64_t timeout; \ uint64_t repeat; \ uint64_t start_id; \ uv_timer_cb timer_cb; diff --git a/deps/libuv/libuv.pc.in b/deps/libuv/libuv.pc.in index 55c4b65d5..1d7b86f75 100644 --- a/deps/libuv/libuv.pc.in +++ b/deps/libuv/libuv.pc.in @@ -3,7 +3,7 @@ exec_prefix=${prefix} libdir=@libdir@ includedir=@includedir@ -Name: @PACKAGE_NAME@ +Name: libuv Version: @PACKAGE_VERSION@ Description: multi-platform support library with a focus on asynchronous I/O. URL: http://libuv.org/ diff --git a/deps/libuv/m4/libuv-check-flags.m4 b/deps/libuv/m4/libuv-check-flags.m4 index 59c306355..e347056ae 100644 --- a/deps/libuv/m4/libuv-check-flags.m4 +++ b/deps/libuv/m4/libuv-check-flags.m4 @@ -1,5 +1,5 @@ dnl Macros to check the presence of generic (non-typed) symbols. -dnl Copyright (c) 2006-2008 Diego Pettenà +dnl Copyright (c) 2006-2008 Diego Pettenò dnl Copyright (c) 2006-2008 xine project dnl dnl This program is free software; you can redistribute it and/or modify @@ -316,4 +316,4 @@ AC_DEFUN([CC_ATTRIBUTE_ALIGNED], [ AC_DEFINE_UNQUOTED([ATTRIBUTE_ALIGNED_MAX], [$cc_cv_attribute_aligned], [Define the highest alignment supported]) fi -]) \ No newline at end of file +]) diff --git a/deps/libuv/src/fs-poll.c b/deps/libuv/src/fs-poll.c index ee73d5a2e..6c82dfc1d 100644 --- a/deps/libuv/src/fs-poll.c +++ b/deps/libuv/src/fs-poll.c @@ -83,7 +83,7 @@ int uv_fs_poll_start(uv_fs_poll_t* handle, if (err < 0) goto error; - ctx->timer_handle.flags |= UV__HANDLE_INTERNAL; + ctx->timer_handle.flags |= UV_HANDLE_INTERNAL; uv__handle_unref(&ctx->timer_handle); err = uv_fs_stat(loop, &ctx->fs_req, ctx->path, poll_cb); @@ -248,7 +248,7 @@ static int statbuf_eq(const uv_stat_t* a, const uv_stat_t* b) { #include "win/handle-inl.h" void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); } diff --git a/deps/libuv/src/inet.c b/deps/libuv/src/inet.c index da63a688c..4598ca1e9 100644 --- a/deps/libuv/src/inet.c +++ b/deps/libuv/src/inet.c @@ -19,7 +19,7 @@ #include #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include #endif diff --git a/deps/libuv/src/unix/timer.c b/deps/libuv/src/timer.c similarity index 92% rename from deps/libuv/src/unix/timer.c rename to deps/libuv/src/timer.c index 54dabfe7d..2bf449a73 100644 --- a/deps/libuv/src/unix/timer.c +++ b/deps/libuv/src/timer.c @@ -19,13 +19,22 @@ */ #include "uv.h" -#include "internal.h" +#include "uv-common.h" #include "heap-inl.h" #include #include +static struct heap *timer_heap(const uv_loop_t* loop) { +#ifdef _WIN32 + return (struct heap*) loop->timer_heap; +#else + return (struct heap*) &loop->timer_heap; +#endif +} + + static int timer_less_than(const struct heap_node* ha, const struct heap_node* hb) { const uv_timer_t* a; @@ -81,7 +90,7 @@ int uv_timer_start(uv_timer_t* handle, /* start_id is the second index to be compared in uv__timer_cmp() */ handle->start_id = handle->loop->timer_counter++; - heap_insert((struct heap*) &handle->loop->timer_heap, + heap_insert(timer_heap(handle->loop), (struct heap_node*) &handle->heap_node, timer_less_than); uv__handle_start(handle); @@ -94,7 +103,7 @@ int uv_timer_stop(uv_timer_t* handle) { if (!uv__is_active(handle)) return 0; - heap_remove((struct heap*) &handle->loop->timer_heap, + heap_remove(timer_heap(handle->loop), (struct heap_node*) &handle->heap_node, timer_less_than); uv__handle_stop(handle); @@ -131,7 +140,7 @@ int uv__next_timeout(const uv_loop_t* loop) { const uv_timer_t* handle; uint64_t diff; - heap_node = heap_min((const struct heap*) &loop->timer_heap); + heap_node = heap_min(timer_heap(loop)); if (heap_node == NULL) return -1; /* block indefinitely */ @@ -152,7 +161,7 @@ void uv__run_timers(uv_loop_t* loop) { uv_timer_t* handle; for (;;) { - heap_node = heap_min((struct heap*) &loop->timer_heap); + heap_node = heap_min(timer_heap(loop)); if (heap_node == NULL) break; diff --git a/deps/libuv/src/unix/android-ifaddrs.c b/deps/libuv/src/unix/android-ifaddrs.c index bf30b1417..99fb25a43 100644 --- a/deps/libuv/src/unix/android-ifaddrs.c +++ b/deps/libuv/src/unix/android-ifaddrs.c @@ -23,7 +23,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include "android-ifaddrs.h" +#include "uv/android-ifaddrs.h" #include "uv-common.h" #include diff --git a/deps/libuv/src/unix/core.c b/deps/libuv/src/unix/core.c index 18c8fcd80..066c9bee3 100644 --- a/deps/libuv/src/unix/core.c +++ b/deps/libuv/src/unix/core.c @@ -116,7 +116,7 @@ uint64_t uv_hrtime(void) { void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { assert(!uv__is_closing(handle)); - handle->flags |= UV_CLOSING; + handle->flags |= UV_HANDLE_CLOSING; handle->close_cb = close_cb; switch (handle->type) { @@ -174,8 +174,8 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { case UV_SIGNAL: uv__signal_close((uv_signal_t*) handle); - /* Signal handles may not be closed immediately. The signal code will */ - /* itself close uv__make_close_pending whenever appropriate. */ + /* Signal handles may not be closed immediately. The signal code will + * itself close uv__make_close_pending whenever appropriate. */ return; default: @@ -214,8 +214,8 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value) { } void uv__make_close_pending(uv_handle_t* handle) { - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->next_closing = handle->loop->closing_handles; handle->loop->closing_handles = handle; } @@ -241,15 +241,17 @@ int uv__getiovmax(void) { static void uv__finish_close(uv_handle_t* handle) { - /* Note: while the handle is in the UV_CLOSING state now, it's still possible - * for it to be active in the sense that uv__is_active() returns true. + /* Note: while the handle is in the UV_HANDLE_CLOSING state now, it's still + * possible for it to be active in the sense that uv__is_active() returns + * true. + * * A good example is when the user calls uv_shutdown(), immediately followed * by uv_close(). The handle is considered active at this point because the * completion of the shutdown req is still pending. */ - assert(handle->flags & UV_CLOSING); - assert(!(handle->flags & UV_CLOSED)); - handle->flags |= UV_CLOSED; + assert(handle->flags & UV_HANDLE_CLOSING); + assert(!(handle->flags & UV_HANDLE_CLOSED)); + handle->flags |= UV_HANDLE_CLOSED; switch (handle->type) { case UV_PREPARE: @@ -927,6 +929,11 @@ int uv__io_active(const uv__io_t* w, unsigned int events) { } +int uv__fd_exists(uv_loop_t* loop, int fd) { + return (unsigned) fd < loop->nwatchers && loop->watchers[fd] != NULL; +} + + int uv_getrusage(uv_rusage_t* rusage) { struct rusage usage; diff --git a/deps/libuv/src/unix/fs.c b/deps/libuv/src/unix/fs.c index de678733a..652cdfd73 100644 --- a/deps/libuv/src/unix/fs.c +++ b/deps/libuv/src/unix/fs.c @@ -865,9 +865,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { /* If an error occurred that the sendfile fallback also won't handle, or this is a force clone then exit. Otherwise, fall through to try using sendfile(). */ - if ((errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) || - req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { - err = -errno; + if (errno != ENOTTY && errno != EOPNOTSUPP && errno != EXDEV) { + err = UV__ERR(errno); + goto out; + } else if (req->flags & UV_FS_COPYFILE_FICLONE_FORCE) { + err = UV_ENOTSUP; goto out; } } else { @@ -927,7 +929,11 @@ static ssize_t uv__fs_copyfile(uv_fs_t* req) { } } - return result; + if (result == 0) + return 0; + + errno = UV__ERR(result); + return -1; #endif } @@ -1114,6 +1120,7 @@ static void uv__fs_work(struct uv__work* w) { X(COPYFILE, uv__fs_copyfile(req)); X(FCHMOD, fchmod(req->file, req->mode)); X(FCHOWN, fchown(req->file, req->uid, req->gid)); + X(LCHOWN, lchown(req->path, req->uid, req->gid)); X(FDATASYNC, uv__fs_fdatasync(req)); X(FSTAT, uv__fs_fstat(req->file, &req->statbuf)); X(FSYNC, uv__fs_fsync(req)); @@ -1240,6 +1247,20 @@ int uv_fs_fchown(uv_loop_t* loop, } +int uv_fs_lchown(uv_loop_t* loop, + uv_fs_t* req, + const char* path, + uv_uid_t uid, + uv_gid_t gid, + uv_fs_cb cb) { + INIT(LCHOWN); + PATH; + req->uid = uid; + req->gid = gid; + POST; +} + + int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) { INIT(FDATASYNC); req->file = file; diff --git a/deps/libuv/src/unix/fsevents.c b/deps/libuv/src/unix/fsevents.c index 47d8024b6..ee45299b7 100644 --- a/deps/libuv/src/unix/fsevents.c +++ b/deps/libuv/src/unix/fsevents.c @@ -836,7 +836,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) { handle->cf_cb->data = handle; uv_async_init(handle->loop, handle->cf_cb, uv__fsevents_cb); - handle->cf_cb->flags |= UV__HANDLE_INTERNAL; + handle->cf_cb->flags |= UV_HANDLE_INTERNAL; uv_unref((uv_handle_t*) handle->cf_cb); err = uv_mutex_init(&handle->cf_mutex); diff --git a/deps/libuv/src/unix/internal.h b/deps/libuv/src/unix/internal.h index b6df1ab9d..cd7903710 100644 --- a/deps/libuv/src/unix/internal.h +++ b/deps/libuv/src/unix/internal.h @@ -127,26 +127,6 @@ int uv__pthread_sigmask(int how, const sigset_t* set, sigset_t* oset); typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t; -/* handle flags */ -enum { - UV_CLOSING = 0x01, /* uv_close() called but not finished. */ - UV_CLOSED = 0x02, /* close(2) finished. */ - UV_STREAM_READING = 0x04, /* uv_read_start() called. */ - UV_STREAM_SHUTTING = 0x08, /* uv_shutdown() called but not complete. */ - UV_STREAM_SHUT = 0x10, /* Write side closed. */ - UV_STREAM_READABLE = 0x20, /* The stream is readable */ - UV_STREAM_WRITABLE = 0x40, /* The stream is writable */ - UV_STREAM_BLOCKING = 0x80, /* Synchronous writes. */ - UV_STREAM_READ_PARTIAL = 0x100, /* read(2) read less than requested. */ - UV_STREAM_READ_EOF = 0x200, /* read(2) read EOF. */ - UV_TCP_NODELAY = 0x400, /* Disable Nagle. */ - UV_TCP_KEEPALIVE = 0x800, /* Turn on keep-alive. */ - UV_TCP_SINGLE_ACCEPT = 0x1000, /* Only accept() when idle. */ - UV_HANDLE_IPV6 = 0x10000, /* Handle is bound to a IPv6 socket. */ - UV_UDP_PROCESSING = 0x20000, /* Handle is running the send callback queue. */ - UV_HANDLE_BOUND = 0x40000 /* Handle is bound to an address and port */ -}; - /* loop flags */ enum { UV_LOOP_BLOCK_SIGPROF = 1 @@ -185,6 +165,18 @@ struct uv__stream_queued_fds_s { #define uv__nonblock uv__nonblock_fcntl #endif +/* On Linux, uv__nonblock_fcntl() and uv__nonblock_ioctl() do not commute + * when O_NDELAY is not equal to O_NONBLOCK. Case in point: linux/sparc32 + * and linux/sparc64, where O_NDELAY is O_NONBLOCK + another bit. + * + * Libuv uses uv__nonblock_fcntl() directly sometimes so ensure that it + * commutes with uv__nonblock(). + */ +#if defined(__linux__) && O_NDELAY != O_NONBLOCK +#undef uv__nonblock +#define uv__nonblock uv__nonblock_fcntl +#endif + /* core */ int uv__cloexec_ioctl(int fd, int set); int uv__cloexec_fcntl(int fd, int set); @@ -207,6 +199,7 @@ int uv__io_active(const uv__io_t* w, unsigned int events); int uv__io_check_fd(uv_loop_t* loop, int fd); void uv__io_poll(uv_loop_t* loop, int timeout); /* in milliseconds or -1 */ int uv__io_fork(uv_loop_t* loop); +int uv__fd_exists(uv_loop_t* loop, int fd); /* async */ void uv__async_stop(uv_loop_t* loop); @@ -239,10 +232,6 @@ int uv__tcp_keepalive(int fd, int on, unsigned int delay); /* pipe */ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); -/* timer */ -void uv__run_timers(uv_loop_t* loop); -int uv__next_timeout(const uv_loop_t* loop); - /* signal */ void uv__signal_close(uv_signal_t* handle); void uv__signal_global_once_init(void); @@ -267,7 +256,6 @@ void uv__prepare_close(uv_prepare_t* handle); void uv__process_close(uv_process_t* handle); void uv__stream_close(uv_stream_t* handle); void uv__tcp_close(uv_tcp_t* handle); -void uv__timer_close(uv_timer_t* handle); void uv__udp_close(uv_udp_t* handle); void uv__udp_finish_close(uv_udp_t* handle); uv_handle_type uv__handle_type(int fd); diff --git a/deps/libuv/src/unix/kqueue.c b/deps/libuv/src/unix/kqueue.c index a30fd730f..930f2da71 100644 --- a/deps/libuv/src/unix/kqueue.c +++ b/deps/libuv/src/unix/kqueue.c @@ -261,8 +261,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w = loop->watchers[fd]; if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. */ - /* TODO batch up */ + /* File descriptor that we've stopped watching, disarm it. + * TODO: batch up. */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); diff --git a/deps/libuv/src/unix/linux-core.c b/deps/libuv/src/unix/linux-core.c index b63c25f3c..d09bbcdd6 100644 --- a/deps/libuv/src/unix/linux-core.c +++ b/deps/libuv/src/unix/linux-core.c @@ -51,7 +51,7 @@ #ifdef HAVE_IFADDRS_H # if defined(__ANDROID__) -# include "android-ifaddrs.h" +# include "uv/android-ifaddrs.h" # else # include # endif @@ -388,7 +388,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { * free when we switch over to edge-triggered I/O. */ if (pe->events == POLLERR || pe->events == POLLHUP) - pe->events |= w->pevents & (POLLIN | POLLOUT | UV__POLLPRI); + pe->events |= + w->pevents & (POLLIN | POLLOUT | UV__POLLRDHUP | UV__POLLPRI); if (pe->events != 0) { /* Run signal watchers last. This also affects child process watchers diff --git a/deps/libuv/src/unix/linux-inotify.c b/deps/libuv/src/unix/linux-inotify.c index bcad630fa..7797f8425 100644 --- a/deps/libuv/src/unix/linux-inotify.c +++ b/deps/libuv/src/unix/linux-inotify.c @@ -19,7 +19,7 @@ */ #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "internal.h" #include diff --git a/deps/libuv/src/unix/loop.c b/deps/libuv/src/unix/loop.c index 99ead6cbc..c2a03d770 100644 --- a/deps/libuv/src/unix/loop.c +++ b/deps/libuv/src/unix/loop.c @@ -20,7 +20,7 @@ */ #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "internal.h" #include "heap-inl.h" #include @@ -74,7 +74,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_signal_init; uv__handle_unref(&loop->child_watcher); - loop->child_watcher.flags |= UV__HANDLE_INTERNAL; + loop->child_watcher.flags |= UV_HANDLE_INTERNAL; QUEUE_INIT(&loop->process_handles); err = uv_rwlock_init(&loop->cloexec_lock); @@ -90,7 +90,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_async_init; uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; + loop->wq_async.flags |= UV_HANDLE_INTERNAL; return 0; diff --git a/deps/libuv/src/unix/os390-syscalls.c b/deps/libuv/src/unix/os390-syscalls.c index 21558ea86..1040d6697 100644 --- a/deps/libuv/src/unix/os390-syscalls.c +++ b/deps/libuv/src/unix/os390-syscalls.c @@ -141,7 +141,7 @@ static void init_message_queue(uv__os390_epoll* lst) { } msg; /* initialize message queue */ - lst->msg_queue = msgget(IPC_PRIVATE, 0622 | IPC_CREAT); + lst->msg_queue = msgget(IPC_PRIVATE, 0600 | IPC_CREAT); if (lst->msg_queue == -1) abort(); @@ -215,6 +215,7 @@ uv__os390_epoll* epoll_create1(int flags) { maybe_resize(lst, 1); lst->items[lst->size - 1].fd = lst->msg_queue; lst->items[lst->size - 1].events = POLLIN; + lst->items[lst->size - 1].revents = 0; uv_once(&once, epoll_init); uv_mutex_lock(&global_epoll_lock); QUEUE_INSERT_TAIL(&global_epoll_queue, &lst->member); @@ -252,13 +253,15 @@ int epoll_ctl(uv__os390_epoll* lst, } lst->items[fd].fd = fd; lst->items[fd].events = event->events; + lst->items[fd].revents = 0; } else if (op == EPOLL_CTL_MOD) { - if (fd >= lst->size || lst->items[fd].fd == -1) { + if (fd >= lst->size - 1 || lst->items[fd].fd == -1) { uv_mutex_unlock(&global_epoll_lock); errno = ENOENT; return -1; } lst->items[fd].events = event->events; + lst->items[fd].revents = 0; } else abort(); @@ -273,8 +276,9 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, struct pollfd* pfds; int pollret; int reventcount; + int nevents; - size = _SET_FDS_MSGS(size, 1, lst->size - 1); + _SET_FDS_MSGS(size, 1, lst->size - 1); pfds = lst->items; pollret = poll(pfds, size, timeout); if (pollret <= 0) @@ -283,19 +287,28 @@ int epoll_wait(uv__os390_epoll* lst, struct epoll_event* events, pollret = _NFDS(pollret) + _NMSGS(pollret); reventcount = 0; + nevents = 0; for (int i = 0; i < lst->size && i < maxevents && reventcount < pollret; ++i) { struct epoll_event ev; + struct pollfd* pfd; - if (pfds[i].fd == -1 || pfds[i].revents == 0) + pfd = &pfds[i]; + if (pfd->fd == -1 || pfd->revents == 0) continue; - ev.fd = pfds[i].fd; - ev.events = pfds[i].revents; - events[reventcount++] = ev; + ev.fd = pfd->fd; + ev.events = pfd->revents; + if (pfd->revents & POLLIN && pfd->revents & POLLOUT) + reventcount += 2; + else if (pfd->revents & (POLLIN | POLLOUT)) + ++reventcount; + + pfd->revents = 0; + events[nevents++] = ev; } - return reventcount; + return nevents; } @@ -491,7 +504,7 @@ ssize_t os390_readlink(const char* path, char* buf, size_t len) { size_t strnlen(const char* str, size_t maxlen) { - void* p = memchr(str, 0, maxlen); + char* p = memchr(str, 0, maxlen); if (p == NULL) return maxlen; else diff --git a/deps/libuv/src/unix/pipe.c b/deps/libuv/src/unix/pipe.c index 2c578dcb3..0718bc81b 100644 --- a/deps/libuv/src/unix/pipe.c +++ b/deps/libuv/src/unix/pipe.c @@ -134,6 +134,9 @@ void uv__pipe_close(uv_pipe_t* handle) { int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { int err; + if (uv__fd_exists(handle->loop, fd)) + return UV_EEXIST; + err = uv__nonblock(fd, 1); if (err) return err; @@ -146,7 +149,7 @@ int uv_pipe_open(uv_pipe_t* handle, uv_file fd) { return uv__stream_open((uv_stream_t*)handle, fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); } @@ -196,7 +199,7 @@ void uv_pipe_connect(uv_connect_t* req, if (new_sock) { err = uv__stream_open((uv_stream_t*)handle, uv__stream_fd(handle), - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); } if (err == 0) diff --git a/deps/libuv/src/unix/poll.c b/deps/libuv/src/unix/poll.c index f3b0bf4e4..3d5022b22 100644 --- a/deps/libuv/src/unix/poll.c +++ b/deps/libuv/src/unix/poll.c @@ -68,6 +68,9 @@ static void uv__poll_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { int err; + if (uv__fd_exists(loop, fd)) + return UV_EEXIST; + err = uv__io_check_fd(loop, fd); if (err) return err; diff --git a/deps/libuv/src/unix/process.c b/deps/libuv/src/unix/process.c index 3a3cfd6f0..101c9c53d 100644 --- a/deps/libuv/src/unix/process.c +++ b/deps/libuv/src/unix/process.c @@ -239,9 +239,9 @@ static int uv__process_open_stream(uv_stdio_container_t* container, flags = 0; if (container->flags & UV_WRITABLE_PIPE) - flags |= UV_STREAM_READABLE; + flags |= UV_HANDLE_READABLE; if (container->flags & UV_READABLE_PIPE) - flags |= UV_STREAM_WRITABLE; + flags |= UV_HANDLE_WRITABLE; return uv__stream_open(container->data.stream, pipefds[0], flags); } diff --git a/deps/libuv/src/unix/signal.c b/deps/libuv/src/unix/signal.c index b9d0a5608..01aa55f3f 100644 --- a/deps/libuv/src/unix/signal.c +++ b/deps/libuv/src/unix/signal.c @@ -54,8 +54,7 @@ static void uv__signal_unregister_handler(int signum); static uv_once_t uv__signal_global_init_guard = UV_ONCE_INIT; static struct uv__signal_tree_s uv__signal_tree = RB_INITIALIZER(uv__signal_tree); -static int uv__signal_lock_pipefd[2]; - +static int uv__signal_lock_pipefd[2] = { -1, -1 }; RB_GENERATE_STATIC(uv__signal_tree_s, uv_signal_s, tree_entry, @@ -64,7 +63,7 @@ RB_GENERATE_STATIC(uv__signal_tree_s, static void uv__signal_global_reinit(void); static void uv__signal_global_init(void) { - if (!uv__signal_lock_pipefd[0]) + if (uv__signal_lock_pipefd[0] == -1) /* pthread_atfork can register before and after handlers, one * for each child. This only registers one for the child. That * state is both persistent and cumulative, so if we keep doing @@ -74,15 +73,11 @@ static void uv__signal_global_init(void) { if (pthread_atfork(NULL, NULL, &uv__signal_global_reinit)) abort(); - if (uv__make_pipe(uv__signal_lock_pipefd, 0)) - abort(); - - if (uv__signal_unlock()) - abort(); + uv__signal_global_reinit(); } -static void uv__signal_global_reinit(void) { +UV_DESTRUCTOR(static void uv__signal_global_fini(void)) { /* We can only use signal-safe functions here. * That includes read/write and close, fortunately. * We do all of this directly here instead of resetting @@ -90,11 +85,26 @@ static void uv__signal_global_reinit(void) { * uv__signal_global_once_init is only called from uv_loop_init * and this needs to function in existing loops. */ - uv__close(uv__signal_lock_pipefd[0]); - uv__signal_lock_pipefd[0] = -1; - uv__close(uv__signal_lock_pipefd[1]); - uv__signal_lock_pipefd[1] = -1; - uv__signal_global_init(); + if (uv__signal_lock_pipefd[0] != -1) { + uv__close(uv__signal_lock_pipefd[0]); + uv__signal_lock_pipefd[0] = -1; + } + + if (uv__signal_lock_pipefd[1] != -1) { + uv__close(uv__signal_lock_pipefd[1]); + uv__signal_lock_pipefd[1] = -1; + } +} + + +static void uv__signal_global_reinit(void) { + uv__signal_global_fini(); + + if (uv__make_pipe(uv__signal_lock_pipefd, 0)) + abort(); + + if (uv__signal_unlock()) + abort(); } @@ -103,7 +113,6 @@ void uv__signal_global_once_init(void) { } - static int uv__signal_lock(void) { int r; char data; @@ -387,7 +396,7 @@ static int uv__signal_start(uv_signal_t* handle, */ first_handle = uv__signal_first_handle(signum); if (first_handle == NULL || - (!oneshot && (first_handle->flags & UV__SIGNAL_ONE_SHOT))) { + (!oneshot && (first_handle->flags & UV_SIGNAL_ONE_SHOT))) { err = uv__signal_register_handler(signum, oneshot); if (err) { /* Registering the signal handler failed. Must be an invalid signal. */ @@ -398,7 +407,7 @@ static int uv__signal_start(uv_signal_t* handle, handle->signum = signum; if (oneshot) - handle->flags |= UV__SIGNAL_ONE_SHOT; + handle->flags |= UV_SIGNAL_ONE_SHOT; RB_INSERT(uv__signal_tree_s, &uv__signal_tree, handle); @@ -455,20 +464,20 @@ static void uv__signal_event(uv_loop_t* loop, handle = msg->handle; if (msg->signum == handle->signum) { - assert(!(handle->flags & UV_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); handle->signal_cb(handle, handle->signum); } handle->dispatched_signals++; - if (handle->flags & UV__SIGNAL_ONE_SHOT) + if (handle->flags & UV_SIGNAL_ONE_SHOT) uv__signal_stop(handle); /* If uv_close was called while there were caught signals that were not * yet dispatched, the uv__finish_close was deferred. Make close pending * now if this has happened. */ - if ((handle->flags & UV_CLOSING) && + if ((handle->flags & UV_HANDLE_CLOSING) && (handle->caught_signals == handle->dispatched_signals)) { uv__make_close_pending((uv_handle_t*) handle); } @@ -496,11 +505,11 @@ static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { if (w1->signum < w2->signum) return -1; if (w1->signum > w2->signum) return 1; - /* Handlers without UV__SIGNAL_ONE_SHOT set will come first, so if the first + /* Handlers without UV_SIGNAL_ONE_SHOT set will come first, so if the first * handler returned is a one-shot handler, the rest will be too. */ - f1 = w1->flags & UV__SIGNAL_ONE_SHOT; - f2 = w2->flags & UV__SIGNAL_ONE_SHOT; + f1 = w1->flags & UV_SIGNAL_ONE_SHOT; + f2 = w2->flags & UV_SIGNAL_ONE_SHOT; if (f1 < f2) return -1; if (f1 > f2) return 1; @@ -549,8 +558,8 @@ static void uv__signal_stop(uv_signal_t* handle) { if (first_handle == NULL) { uv__signal_unregister_handler(handle->signum); } else { - rem_oneshot = handle->flags & UV__SIGNAL_ONE_SHOT; - first_oneshot = first_handle->flags & UV__SIGNAL_ONE_SHOT; + rem_oneshot = handle->flags & UV_SIGNAL_ONE_SHOT; + first_oneshot = first_handle->flags & UV_SIGNAL_ONE_SHOT; if (first_oneshot && !rem_oneshot) { ret = uv__signal_register_handler(handle->signum, 1); assert(ret == 0); diff --git a/deps/libuv/src/unix/stream.c b/deps/libuv/src/unix/stream.c index 5ec6bf4de..4d62a23f1 100644 --- a/deps/libuv/src/unix/stream.c +++ b/deps/libuv/src/unix/stream.c @@ -220,7 +220,7 @@ static void uv__stream_osx_select(void* arg) { uv_sem_wait(&s->async_sem); /* Should be processed at this stage */ - assert((s->events == 0) || (stream->flags & UV_CLOSING)); + assert((s->events == 0) || (stream->flags & UV_HANDLE_CLOSING)); } } } @@ -248,7 +248,7 @@ static void uv__stream_osx_select_cb(uv_async_t* handle) { if ((events & POLLOUT) && uv__io_active(&stream->io_watcher, POLLOUT)) uv__stream_io(stream->loop, &stream->io_watcher, POLLOUT); - if (stream->flags & UV_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return; /* NOTE: It is important to do it here, otherwise `select()` might be called @@ -342,7 +342,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { if (err) goto failed_async_init; - s->async.flags |= UV__HANDLE_INTERNAL; + s->async.flags |= UV_HANDLE_INTERNAL; uv__handle_unref(&s->async); err = uv_sem_init(&s->close_sem, 0); @@ -407,12 +407,14 @@ int uv__stream_open(uv_stream_t* stream, int fd, int flags) { stream->flags |= flags; if (stream->type == UV_TCP) { - if ((stream->flags & UV_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) + if ((stream->flags & UV_HANDLE_TCP_NODELAY) && uv__tcp_nodelay(fd, 1)) return UV__ERR(errno); /* TODO Use delay the user passed in. */ - if ((stream->flags & UV_TCP_KEEPALIVE) && uv__tcp_keepalive(fd, 1, 60)) + if ((stream->flags & UV_HANDLE_TCP_KEEPALIVE) && + uv__tcp_keepalive(fd, 1, 60)) { return UV__ERR(errno); + } } #if defined(__APPLE__) @@ -447,7 +449,7 @@ void uv__stream_flush_write_queue(uv_stream_t* stream, int error) { void uv__stream_destroy(uv_stream_t* stream) { assert(!uv__io_active(&stream->io_watcher, POLLIN | POLLOUT)); - assert(stream->flags & UV_CLOSED); + assert(stream->flags & UV_HANDLE_CLOSED); if (stream->connect_req) { uv__req_unregister(stream->loop, stream->connect_req); @@ -522,7 +524,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { stream = container_of(w, uv_stream_t, io_watcher); assert(events & POLLIN); assert(stream->accepted_fd == -1); - assert(!(stream->flags & UV_CLOSING)); + assert(!(stream->flags & UV_HANDLE_CLOSING)); uv__io_start(stream->loop, &stream->io_watcher, POLLIN); @@ -565,7 +567,8 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; } - if (stream->type == UV_TCP && (stream->flags & UV_TCP_SINGLE_ACCEPT)) { + if (stream->type == UV_TCP && + (stream->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) { /* Give other processes a chance to accept connections. */ struct timespec timeout = { 0, 1 }; nanosleep(&timeout, NULL); @@ -590,7 +593,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { case UV_TCP: err = uv__stream_open(client, server->accepted_fd, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) { /* TODO handle error */ uv__close(server->accepted_fd); @@ -674,14 +677,14 @@ static void uv__drain(uv_stream_t* stream) { uv__stream_osx_interrupt_select(stream); /* Shutdown? */ - if ((stream->flags & UV_STREAM_SHUTTING) && - !(stream->flags & UV_CLOSING) && - !(stream->flags & UV_STREAM_SHUT)) { + if ((stream->flags & UV_HANDLE_SHUTTING) && + !(stream->flags & UV_HANDLE_CLOSING) && + !(stream->flags & UV_HANDLE_SHUT)) { assert(stream->shutdown_req); req = stream->shutdown_req; stream->shutdown_req = NULL; - stream->flags &= ~UV_STREAM_SHUTTING; + stream->flags &= ~UV_HANDLE_SHUTTING; uv__req_unregister(stream->loop, req); err = 0; @@ -689,7 +692,7 @@ static void uv__drain(uv_stream_t* stream) { err = UV__ERR(errno); if (err == 0) - stream->flags |= UV_STREAM_SHUT; + stream->flags |= UV_HANDLE_SHUT; if (req->cb != NULL) req->cb(req, err); @@ -868,7 +871,7 @@ static void uv__write(uv_stream_t* stream) { if (!WRITE_RETRY_ON_ERROR(req->send_handle)) { err = UV__ERR(errno); goto error; - } else if (stream->flags & UV_STREAM_BLOCKING) { + } else if (stream->flags & UV_HANDLE_BLOCKING_WRITES) { /* If this is a blocking stream, try again. */ goto start; } @@ -888,7 +891,7 @@ static void uv__write(uv_stream_t* stream) { n = 0; /* There is more to write. */ - if (stream->flags & UV_STREAM_BLOCKING) { + if (stream->flags & UV_HANDLE_BLOCKING_WRITES) { /* * If we're blocking then we should not be enabling the write * watcher - instead we need to try again. @@ -924,7 +927,7 @@ static void uv__write(uv_stream_t* stream) { assert(n == 0 || n == -1); /* Only non-blocking streams should use the write_watcher. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); + assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES)); /* We're not done. */ uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); @@ -1015,13 +1018,13 @@ uv_handle_type uv__handle_type(int fd) { static void uv__stream_eof(uv_stream_t* stream, const uv_buf_t* buf) { - stream->flags |= UV_STREAM_READ_EOF; + stream->flags |= UV_HANDLE_READ_EOF; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); uv__stream_osx_interrupt_select(stream); stream->read_cb(stream, UV_EOF, buf); - stream->flags &= ~UV_STREAM_READING; + stream->flags &= ~UV_HANDLE_READING; } @@ -1121,6 +1124,7 @@ static int uv__stream_recv_cmsg(uv_stream_t* stream, struct msghdr* msg) { #ifdef __clang__ # pragma clang diagnostic push # pragma clang diagnostic ignored "-Wgnu-folding-constant" +# pragma clang diagnostic ignored "-Wvla-extension" #endif static void uv__read(uv_stream_t* stream) { @@ -1132,7 +1136,7 @@ static void uv__read(uv_stream_t* stream) { int err; int is_ipc; - stream->flags &= ~UV_STREAM_READ_PARTIAL; + stream->flags &= ~UV_HANDLE_READ_PARTIAL; /* Prevent loop starvation when the data comes in as fast as (or faster than) * we can read it. XXX Need to rearm fd if we switch to edge-triggered I/O. @@ -1141,11 +1145,11 @@ static void uv__read(uv_stream_t* stream) { is_ipc = stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) stream)->ipc; - /* XXX: Maybe instead of having UV_STREAM_READING we just test if + /* XXX: Maybe instead of having UV_HANDLE_READING we just test if * tcp->read_cb is NULL or not? */ while (stream->read_cb - && (stream->flags & UV_STREAM_READING) + && (stream->flags & UV_HANDLE_READING) && (count-- > 0)) { assert(stream->alloc_cb != NULL); @@ -1186,7 +1190,7 @@ static void uv__read(uv_stream_t* stream) { /* Error */ if (errno == EAGAIN || errno == EWOULDBLOCK) { /* Wait for the next one. */ - if (stream->flags & UV_STREAM_READING) { + if (stream->flags & UV_HANDLE_READING) { uv__io_start(stream->loop, &stream->io_watcher, POLLIN); uv__stream_osx_interrupt_select(stream); } @@ -1199,8 +1203,8 @@ static void uv__read(uv_stream_t* stream) { } else { /* Error. User should call uv_close(). */ stream->read_cb(stream, UV__ERR(errno), &buf); - if (stream->flags & UV_STREAM_READING) { - stream->flags &= ~UV_STREAM_READING; + if (stream->flags & UV_HANDLE_READING) { + stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); @@ -1250,7 +1254,7 @@ static void uv__read(uv_stream_t* stream) { /* Return if we didn't fill the buffer, there is no more data to read. */ if (nread < buflen) { - stream->flags |= UV_STREAM_READ_PARTIAL; + stream->flags |= UV_HANDLE_READ_PARTIAL; return; } } @@ -1271,9 +1275,9 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { stream->type == UV_TTY || stream->type == UV_NAMED_PIPE); - if (!(stream->flags & UV_STREAM_WRITABLE) || - stream->flags & UV_STREAM_SHUT || - stream->flags & UV_STREAM_SHUTTING || + if (!(stream->flags & UV_HANDLE_WRITABLE) || + stream->flags & UV_HANDLE_SHUT || + stream->flags & UV_HANDLE_SHUTTING || uv__is_closing(stream)) { return UV_ENOTCONN; } @@ -1285,7 +1289,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { req->handle = stream; req->cb = cb; stream->shutdown_req = req; - stream->flags |= UV_STREAM_SHUTTING; + stream->flags |= UV_HANDLE_SHUTTING; uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); @@ -1302,7 +1306,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - assert(!(stream->flags & UV_CLOSING)); + assert(!(stream->flags & UV_HANDLE_CLOSING)); if (stream->connect_req) { uv__stream_connect(stream); @@ -1311,7 +1315,7 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { assert(uv__stream_fd(stream) >= 0); - /* Ignore POLLHUP here. Even it it's set, there may still be data to read. */ + /* Ignore POLLHUP here. Even if it's set, there may still be data to read. */ if (events & (POLLIN | POLLERR | POLLHUP)) uv__read(stream); @@ -1325,9 +1329,9 @@ static void uv__stream_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { * report the EOF yet because there is still data to read. */ if ((events & POLLHUP) && - (stream->flags & UV_STREAM_READING) && - (stream->flags & UV_STREAM_READ_PARTIAL) && - !(stream->flags & UV_STREAM_READ_EOF)) { + (stream->flags & UV_HANDLE_READING) && + (stream->flags & UV_HANDLE_READ_PARTIAL) && + !(stream->flags & UV_HANDLE_READ_EOF)) { uv_buf_t buf = { NULL, 0 }; uv__stream_eof(stream, &buf); } @@ -1417,7 +1421,7 @@ int uv_write2(uv_write_t* req, if (uv__stream_fd(stream) < 0) return UV_EBADF; - if (!(stream->flags & UV_STREAM_WRITABLE)) + if (!(stream->flags & UV_HANDLE_WRITABLE)) return -EPIPE; if (send_handle) { @@ -1487,7 +1491,7 @@ int uv_write2(uv_write_t* req, * if this assert fires then somehow the blocking stream isn't being * sufficiently flushed in uv__write. */ - assert(!(stream->flags & UV_STREAM_BLOCKING)); + assert(!(stream->flags & UV_HANDLE_BLOCKING_WRITES)); uv__io_start(stream->loop, &stream->io_watcher, POLLOUT); uv__stream_osx_interrupt_select(stream); } @@ -1568,16 +1572,16 @@ int uv_read_start(uv_stream_t* stream, assert(stream->type == UV_TCP || stream->type == UV_NAMED_PIPE || stream->type == UV_TTY); - if (stream->flags & UV_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return UV_EINVAL; - if (!(stream->flags & UV_STREAM_READABLE)) + if (!(stream->flags & UV_HANDLE_READABLE)) return -ENOTCONN; - /* The UV_STREAM_READING flag is irrelevant of the state of the tcp - it just + /* The UV_HANDLE_READING flag is irrelevant of the state of the tcp - it just * expresses the desired state of the user. */ - stream->flags |= UV_STREAM_READING; + stream->flags |= UV_HANDLE_READING; /* TODO: try to do the read inline? */ /* TODO: keep track of tcp state. If we've gotten a EOF then we should @@ -1598,10 +1602,10 @@ int uv_read_start(uv_stream_t* stream, int uv_read_stop(uv_stream_t* stream) { - if (!(stream->flags & UV_STREAM_READING)) + if (!(stream->flags & UV_HANDLE_READING)) return 0; - stream->flags &= ~UV_STREAM_READING; + stream->flags &= ~UV_HANDLE_READING; uv__io_stop(stream->loop, &stream->io_watcher, POLLIN); if (!uv__io_active(&stream->io_watcher, POLLOUT)) uv__handle_stop(stream); @@ -1614,12 +1618,12 @@ int uv_read_stop(uv_stream_t* stream) { int uv_is_readable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_READABLE); + return !!(stream->flags & UV_HANDLE_READABLE); } int uv_is_writable(const uv_stream_t* stream) { - return !!(stream->flags & UV_STREAM_WRITABLE); + return !!(stream->flags & UV_HANDLE_WRITABLE); } diff --git a/deps/libuv/src/unix/tcp.c b/deps/libuv/src/unix/tcp.c index 9a46793fd..2982851dc 100644 --- a/deps/libuv/src/unix/tcp.c +++ b/deps/libuv/src/unix/tcp.c @@ -216,7 +216,7 @@ int uv__tcp_connect(uv_connect_t* req, err = maybe_new_socket(handle, addr->sa_family, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); if (err) return err; @@ -263,13 +263,16 @@ int uv__tcp_connect(uv_connect_t* req, int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { int err; + if (uv__fd_exists(handle->loop, sock)) + return UV_EEXIST; + err = uv__nonblock(sock, 1); if (err) return err; return uv__stream_open((uv_stream_t*)handle, sock, - UV_STREAM_READABLE | UV_STREAM_WRITABLE); + UV_HANDLE_READABLE | UV_HANDLE_WRITABLE); } @@ -331,7 +334,7 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) { } if (single_accept) - tcp->flags |= UV_TCP_SINGLE_ACCEPT; + tcp->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; flags = 0; #if defined(__MVS__) @@ -398,9 +401,9 @@ int uv_tcp_nodelay(uv_tcp_t* handle, int on) { } if (on) - handle->flags |= UV_TCP_NODELAY; + handle->flags |= UV_HANDLE_TCP_NODELAY; else - handle->flags &= ~UV_TCP_NODELAY; + handle->flags &= ~UV_HANDLE_TCP_NODELAY; return 0; } @@ -416,9 +419,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { } if (on) - handle->flags |= UV_TCP_KEEPALIVE; + handle->flags |= UV_HANDLE_TCP_KEEPALIVE; else - handle->flags &= ~UV_TCP_KEEPALIVE; + handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; /* TODO Store delay if uv__stream_fd(handle) == -1 but don't want to enlarge * uv_tcp_t with an int that's almost never used... @@ -430,9 +433,9 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int on, unsigned int delay) { int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { if (enable) - handle->flags &= ~UV_TCP_SINGLE_ACCEPT; + handle->flags &= ~UV_HANDLE_TCP_SINGLE_ACCEPT; else - handle->flags |= UV_TCP_SINGLE_ACCEPT; + handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; return 0; } diff --git a/deps/libuv/src/unix/thread.c b/deps/libuv/src/unix/thread.c index ada2ffc88..303bc6ec8 100644 --- a/deps/libuv/src/unix/thread.c +++ b/deps/libuv/src/unix/thread.c @@ -423,87 +423,6 @@ int uv_sem_trywait(uv_sem_t* sem) { return UV_EINVAL; /* Satisfy the compiler. */ } -#elif defined(__MVS__) - -int uv_sem_init(uv_sem_t* sem, unsigned int value) { - uv_sem_t semid; - int err; - union { - int val; - struct semid_ds* buf; - unsigned short* array; - } arg; - - - semid = semget(IPC_PRIVATE, 1, S_IRUSR | S_IWUSR); - if (semid == -1) - return UV__ERR(errno); - - arg.val = value; - if (-1 == semctl(semid, 0, SETVAL, arg)) { - err = errno; - if (-1 == semctl(*sem, 0, IPC_RMID)) - abort(); - return UV__ERR(err); - } - - *sem = semid; - return 0; -} - -void uv_sem_destroy(uv_sem_t* sem) { - if (-1 == semctl(*sem, 0, IPC_RMID)) - abort(); -} - -void uv_sem_post(uv_sem_t* sem) { - struct sembuf buf; - - buf.sem_num = 0; - buf.sem_op = 1; - buf.sem_flg = 0; - - if (-1 == semop(*sem, &buf, 1)) - abort(); -} - -void uv_sem_wait(uv_sem_t* sem) { - struct sembuf buf; - int op_status; - - buf.sem_num = 0; - buf.sem_op = -1; - buf.sem_flg = 0; - - do - op_status = semop(*sem, &buf, 1); - while (op_status == -1 && errno == EINTR); - - if (op_status) - abort(); -} - -int uv_sem_trywait(uv_sem_t* sem) { - struct sembuf buf; - int op_status; - - buf.sem_num = 0; - buf.sem_op = -1; - buf.sem_flg = IPC_NOWAIT; - - do - op_status = semop(*sem, &buf, 1); - while (op_status == -1 && errno == EINTR); - - if (op_status) { - if (errno == EAGAIN) - return UV_EAGAIN; - abort(); - } - - return 0; -} - #else /* !(defined(__APPLE__) && defined(__MACH__)) */ #ifdef __GLIBC__ @@ -517,18 +436,22 @@ int uv_sem_trywait(uv_sem_t* sem) { * a pointer to the actual struct we're using underneath. */ static uv_once_t glibc_version_check_once = UV_ONCE_INIT; -static int glibc_needs_custom_semaphore = 0; +static int platform_needs_custom_semaphore = 0; static void glibc_version_check(void) { const char* version = gnu_get_libc_version(); - glibc_needs_custom_semaphore = + platform_needs_custom_semaphore = version[0] == '2' && version[1] == '.' && atoi(version + 2) < 21; } -#else /* !defined(__GLIBC__) */ +#elif defined(__MVS__) + +#define platform_needs_custom_semaphore 1 -#define glibc_needs_custom_semaphore 0 +#else /* !defined(__GLIBC__) && !defined(__MVS__) */ + +#define platform_needs_custom_semaphore 0 #endif @@ -538,8 +461,9 @@ typedef struct uv_semaphore_s { unsigned int value; } uv_semaphore_t; - +#if defined(__GLIBC__) || platform_needs_custom_semaphore STATIC_ASSERT(sizeof(uv_sem_t) >= sizeof(uv_semaphore_t*)); +#endif static int uv__custom_sem_init(uv_sem_t* sem_, unsigned int value) { int err; @@ -670,7 +594,7 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) { uv_once(&glibc_version_check_once, glibc_version_check); #endif - if (glibc_needs_custom_semaphore) + if (platform_needs_custom_semaphore) return uv__custom_sem_init(sem, value); else return uv__sem_init(sem, value); @@ -678,7 +602,7 @@ int uv_sem_init(uv_sem_t* sem, unsigned int value) { void uv_sem_destroy(uv_sem_t* sem) { - if (glibc_needs_custom_semaphore) + if (platform_needs_custom_semaphore) uv__custom_sem_destroy(sem); else uv__sem_destroy(sem); @@ -686,7 +610,7 @@ void uv_sem_destroy(uv_sem_t* sem) { void uv_sem_post(uv_sem_t* sem) { - if (glibc_needs_custom_semaphore) + if (platform_needs_custom_semaphore) uv__custom_sem_post(sem); else uv__sem_post(sem); @@ -694,7 +618,7 @@ void uv_sem_post(uv_sem_t* sem) { void uv_sem_wait(uv_sem_t* sem) { - if (glibc_needs_custom_semaphore) + if (platform_needs_custom_semaphore) uv__custom_sem_wait(sem); else uv__sem_wait(sem); @@ -702,7 +626,7 @@ void uv_sem_wait(uv_sem_t* sem) { int uv_sem_trywait(uv_sem_t* sem) { - if (glibc_needs_custom_semaphore) + if (platform_needs_custom_semaphore) return uv__custom_sem_trywait(sem); else return uv__sem_trywait(sem); diff --git a/deps/libuv/src/unix/tty.c b/deps/libuv/src/unix/tty.c index f22b3b80d..1b92b5c91 100644 --- a/deps/libuv/src/unix/tty.c +++ b/deps/libuv/src/unix/tty.c @@ -135,7 +135,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { if (r < 0) { /* fallback to using blocking writes */ if (!readable) - flags |= UV_STREAM_BLOCKING; + flags |= UV_HANDLE_BLOCKING_WRITES; goto skip; } @@ -177,7 +177,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ - if (!(flags & UV_STREAM_BLOCKING)) + if (!(flags & UV_HANDLE_BLOCKING_WRITES)) uv__nonblock(fd, 1); #if defined(__APPLE__) @@ -195,9 +195,9 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { #endif if (readable) - flags |= UV_STREAM_READABLE; + flags |= UV_HANDLE_READABLE; else - flags |= UV_STREAM_WRITABLE; + flags |= UV_HANDLE_WRITABLE; uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; diff --git a/deps/libuv/src/unix/udp.c b/deps/libuv/src/unix/udp.c index 74d613b68..e6668a012 100644 --- a/deps/libuv/src/unix/udp.c +++ b/deps/libuv/src/unix/udp.c @@ -92,8 +92,8 @@ static void uv__udp_run_completed(uv_udp_t* handle) { uv_udp_send_t* req; QUEUE* q; - assert(!(handle->flags & UV_UDP_PROCESSING)); - handle->flags |= UV_UDP_PROCESSING; + assert(!(handle->flags & UV_HANDLE_UDP_PROCESSING)); + handle->flags |= UV_HANDLE_UDP_PROCESSING; while (!QUEUE_EMPTY(&handle->write_completed_queue)) { q = QUEUE_HEAD(&handle->write_completed_queue); @@ -128,7 +128,7 @@ static void uv__udp_run_completed(uv_udp_t* handle) { uv__handle_stop(handle); } - handle->flags &= ~UV_UDP_PROCESSING; + handle->flags &= ~UV_HANDLE_UDP_PROCESSING; } @@ -427,7 +427,7 @@ int uv__udp_send(uv_udp_send_t* req, QUEUE_INSERT_TAIL(&handle->write_queue, &req->queue); uv__handle_start(handle); - if (empty_queue && !(handle->flags & UV_UDP_PROCESSING)) { + if (empty_queue && !(handle->flags & UV_HANDLE_UDP_PROCESSING)) { uv__udp_sendmsg(handle); /* `uv__udp_sendmsg` may not be able to do non-blocking write straight @@ -624,6 +624,9 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { if (handle->io_watcher.fd != -1) return UV_EBUSY; + if (uv__fd_exists(handle->loop, sock)) + return UV_EEXIST; + err = uv__nonblock(sock, 1); if (err) return err; diff --git a/deps/libuv/src/uv-common.c b/deps/libuv/src/uv-common.c index 713458956..f0aec4526 100644 --- a/deps/libuv/src/uv-common.c +++ b/deps/libuv/src/uv-common.c @@ -155,6 +155,18 @@ static const char* uv__unknown_err_code(int err) { return copy != NULL ? copy : "Unknown system error"; } +#define UV_ERR_NAME_GEN_R(name, _) \ +case UV_## name: \ + snprintf(buf, buflen, "%s", #name); break; +char* uv_err_name_r(int err, char* buf, size_t buflen) { + switch (err) { + UV_ERRNO_MAP(UV_ERR_NAME_GEN_R) + default: snprintf(buf, buflen, "Unknown system error %d", err); + } + return buf; +} +#undef UV_ERR_NAME_GEN_R + #define UV_ERR_NAME_GEN(name, _) case UV_ ## name: return #name; const char* uv_err_name(int err) { @@ -166,6 +178,19 @@ const char* uv_err_name(int err) { #undef UV_ERR_NAME_GEN +#define UV_STRERROR_GEN_R(name, msg) \ +case UV_ ## name: \ + snprintf(buf, buflen, "%s", msg); break; +char* uv_strerror_r(int err, char* buf, size_t buflen) { + switch (err) { + UV_ERRNO_MAP(UV_STRERROR_GEN_R) + default: snprintf(buf, buflen, "Unknown system error %d", err); + } + return buf; +} +#undef UV_STRERROR_GEN_R + + #define UV_STRERROR_GEN(name, msg) case UV_ ## name: return msg; const char* uv_strerror(int err) { switch (err) { @@ -357,7 +382,7 @@ void uv_walk(uv_loop_t* loop, uv_walk_cb walk_cb, void* arg) { QUEUE_REMOVE(q); QUEUE_INSERT_TAIL(&loop->handle_queue, q); - if (h->flags & UV__HANDLE_INTERNAL) continue; + if (h->flags & UV_HANDLE_INTERNAL) continue; walk_cb(h, arg); } } @@ -386,9 +411,9 @@ static void uv__print_handles(uv_loop_t* loop, int only_active, FILE* stream) { fprintf(stream, "[%c%c%c] %-8s %p\n", - "R-"[!(h->flags & UV__HANDLE_REF)], - "A-"[!(h->flags & UV__HANDLE_ACTIVE)], - "I-"[!(h->flags & UV__HANDLE_INTERNAL)], + "R-"[!(h->flags & UV_HANDLE_REF)], + "A-"[!(h->flags & UV_HANDLE_ACTIVE)], + "I-"[!(h->flags & UV_HANDLE_INTERNAL)], type, (void*)h); } @@ -632,7 +657,7 @@ int uv_loop_close(uv_loop_t* loop) { QUEUE_FOREACH(q, &loop->handle_queue) { h = QUEUE_DATA(q, uv_handle_t, handle_queue); - if (!(h->flags & UV__HANDLE_INTERNAL)) + if (!(h->flags & UV_HANDLE_INTERNAL)) return UV_EBUSY; } diff --git a/deps/libuv/src/uv-common.h b/deps/libuv/src/uv-common.h index c497d014f..3289950d0 100644 --- a/deps/libuv/src/uv-common.h +++ b/deps/libuv/src/uv-common.h @@ -32,13 +32,13 @@ #include #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include #endif #include "uv.h" -#include "tree.h" +#include "uv/tree.h" #include "queue.h" #if EDOM > 0 @@ -59,22 +59,67 @@ extern int snprintf(char*, size_t, const char*, ...); #define STATIC_ASSERT(expr) \ void uv__static_assert(int static_assert_failed[1 - 2 * !(expr)]) -#ifndef _WIN32 +/* Handle flags. Some flags are specific to Windows or UNIX. */ enum { - UV__SIGNAL_ONE_SHOT = 0x80000, /* On signal reception remove sighandler */ - UV__HANDLE_INTERNAL = 0x8000, - UV__HANDLE_ACTIVE = 0x4000, - UV__HANDLE_REF = 0x2000, - UV__HANDLE_CLOSING = 0 /* no-op on unix */ + /* Used by all handles. */ + UV_HANDLE_CLOSING = 0x00000001, + UV_HANDLE_CLOSED = 0x00000002, + UV_HANDLE_ACTIVE = 0x00000004, + UV_HANDLE_REF = 0x00000008, + UV_HANDLE_INTERNAL = 0x00000010, + UV_HANDLE_ENDGAME_QUEUED = 0x00000020, + + /* Used by streams. */ + UV_HANDLE_LISTENING = 0x00000040, + UV_HANDLE_CONNECTION = 0x00000080, + UV_HANDLE_SHUTTING = 0x00000100, + UV_HANDLE_SHUT = 0x00000200, + UV_HANDLE_READ_PARTIAL = 0x00000400, + UV_HANDLE_READ_EOF = 0x00000800, + + /* Used by streams and UDP handles. */ + UV_HANDLE_READING = 0x00001000, + UV_HANDLE_BOUND = 0x00002000, + UV_HANDLE_READABLE = 0x00004000, + UV_HANDLE_WRITABLE = 0x00008000, + UV_HANDLE_READ_PENDING = 0x00010000, + UV_HANDLE_SYNC_BYPASS_IOCP = 0x00020000, + UV_HANDLE_ZERO_READ = 0x00040000, + UV_HANDLE_EMULATE_IOCP = 0x00080000, + UV_HANDLE_BLOCKING_WRITES = 0x00100000, + UV_HANDLE_CANCELLATION_PENDING = 0x00200000, + + /* Used by uv_tcp_t and uv_udp_t handles */ + UV_HANDLE_IPV6 = 0x00400000, + + /* Only used by uv_tcp_t handles. */ + UV_HANDLE_TCP_NODELAY = 0x01000000, + UV_HANDLE_TCP_KEEPALIVE = 0x02000000, + UV_HANDLE_TCP_SINGLE_ACCEPT = 0x04000000, + UV_HANDLE_TCP_ACCEPT_STATE_CHANGING = 0x08000000, + UV_HANDLE_TCP_SOCKET_CLOSED = 0x10000000, + UV_HANDLE_SHARED_TCP_SOCKET = 0x20000000, + + /* Only used by uv_udp_t handles. */ + UV_HANDLE_UDP_PROCESSING = 0x01000000, + + /* Only used by uv_pipe_t handles. */ + UV_HANDLE_NON_OVERLAPPED_PIPE = 0x01000000, + UV_HANDLE_PIPESERVER = 0x02000000, + + /* Only used by uv_tty_t handles. */ + UV_HANDLE_TTY_READABLE = 0x01000000, + UV_HANDLE_TTY_RAW = 0x02000000, + UV_HANDLE_TTY_SAVED_POSITION = 0x04000000, + UV_HANDLE_TTY_SAVED_ATTRIBUTES = 0x08000000, + + /* Only used by uv_signal_t handles. */ + UV_SIGNAL_ONE_SHOT_DISPATCHED = 0x01000000, + UV_SIGNAL_ONE_SHOT = 0x02000000, + + /* Only used by uv_poll_t handles. */ + UV_HANDLE_POLL_SLOW = 0x01000000 }; -#else -# define UV__SIGNAL_ONE_SHOT_DISPATCHED 0x200 -# define UV__SIGNAL_ONE_SHOT 0x100 -# define UV__HANDLE_INTERNAL 0x80 -# define UV__HANDLE_ACTIVE 0x40 -# define UV__HANDLE_REF 0x20 -# define UV__HANDLE_CLOSING 0x01 -#endif int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); @@ -132,6 +177,10 @@ int uv__socket_sockopt(uv_handle_t* handle, int optname, int* value); void uv__fs_scandir_cleanup(uv_fs_t* req); +int uv__next_timeout(const uv_loop_t* loop); +void uv__run_timers(uv_loop_t* loop); +void uv__timer_close(uv_timer_t* handle); + #define uv__has_active_reqs(loop) \ ((loop)->active_reqs.count > 0) @@ -164,49 +213,47 @@ void uv__fs_scandir_cleanup(uv_fs_t* req); while (0) #define uv__is_active(h) \ - (((h)->flags & UV__HANDLE_ACTIVE) != 0) + (((h)->flags & UV_HANDLE_ACTIVE) != 0) #define uv__is_closing(h) \ - (((h)->flags & (UV_CLOSING | UV_CLOSED)) != 0) + (((h)->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)) != 0) #define uv__handle_start(h) \ do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) break; \ - (h)->flags |= UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_add(h); \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \ + (h)->flags |= UV_HANDLE_ACTIVE; \ + if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \ } \ while (0) #define uv__handle_stop(h) \ do { \ - assert(((h)->flags & UV__HANDLE_CLOSING) == 0); \ - if (((h)->flags & UV__HANDLE_ACTIVE) == 0) break; \ - (h)->flags &= ~UV__HANDLE_ACTIVE; \ - if (((h)->flags & UV__HANDLE_REF) != 0) uv__active_handle_rm(h); \ + if (((h)->flags & UV_HANDLE_ACTIVE) == 0) break; \ + (h)->flags &= ~UV_HANDLE_ACTIVE; \ + if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_rm(h); \ } \ while (0) #define uv__handle_ref(h) \ do { \ - if (((h)->flags & UV__HANDLE_REF) != 0) break; \ - (h)->flags |= UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ + if (((h)->flags & UV_HANDLE_REF) != 0) break; \ + (h)->flags |= UV_HANDLE_REF; \ + if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_add(h); \ } \ while (0) #define uv__handle_unref(h) \ do { \ - if (((h)->flags & UV__HANDLE_REF) == 0) break; \ - (h)->flags &= ~UV__HANDLE_REF; \ - if (((h)->flags & UV__HANDLE_CLOSING) != 0) break; \ - if (((h)->flags & UV__HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ + if (((h)->flags & UV_HANDLE_REF) == 0) break; \ + (h)->flags &= ~UV_HANDLE_REF; \ + if (((h)->flags & UV_HANDLE_CLOSING) != 0) break; \ + if (((h)->flags & UV_HANDLE_ACTIVE) != 0) uv__active_handle_rm(h); \ } \ while (0) #define uv__has_ref(h) \ - (((h)->flags & UV__HANDLE_REF) != 0) + (((h)->flags & UV_HANDLE_REF) != 0) #if defined(_WIN32) # define uv__handle_platform_init(h) ((h)->u.fd = -1) @@ -218,7 +265,7 @@ void uv__fs_scandir_cleanup(uv_fs_t* req); do { \ (h)->loop = (loop_); \ (h)->type = (type_); \ - (h)->flags = UV__HANDLE_REF; /* Ref the loop when active. */ \ + (h)->flags = UV_HANDLE_REF; /* Ref the loop when active. */ \ QUEUE_INSERT_TAIL(&(loop_)->handle_queue, &(h)->handle_queue); \ uv__handle_platform_init(h); \ } \ diff --git a/deps/libuv/src/win/async.c b/deps/libuv/src/win/async.c index 0b636ed1e..d787f6604 100644 --- a/deps/libuv/src/win/async.c +++ b/deps/libuv/src/win/async.c @@ -29,7 +29,7 @@ void uv_async_endgame(uv_loop_t* loop, uv_async_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && !handle->async_sent) { assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); @@ -71,9 +71,9 @@ int uv_async_send(uv_async_t* handle) { return -1; } - /* The user should make sure never to call uv_async_send to a closing */ - /* or closed handle. */ - assert(!(handle->flags & UV__HANDLE_CLOSING)); + /* The user should make sure never to call uv_async_send to a closing or + * closed handle. */ + assert(!(handle->flags & UV_HANDLE_CLOSING)); if (!uv__atomic_exchange_set(&handle->async_sent)) { POST_COMPLETION_FOR_REQ(loop, &handle->async_req); @@ -90,7 +90,7 @@ void uv_process_async_wakeup_req(uv_loop_t* loop, uv_async_t* handle, handle->async_sent = 0; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*)handle); } else if (handle->async_cb != NULL) { handle->async_cb(handle); diff --git a/deps/libuv/src/win/atomicops-inl.h b/deps/libuv/src/win/atomicops-inl.h index 6d8126f69..52713cf30 100644 --- a/deps/libuv/src/win/atomicops-inl.h +++ b/deps/libuv/src/win/atomicops-inl.h @@ -29,10 +29,10 @@ /* Atomic set operation on char */ #ifdef _MSC_VER /* MSVC */ -/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less */ -/* efficient than InterlockedExchange, but InterlockedExchange8 does not */ -/* exist, and interlocked operations on larger targets might require the */ -/* target to be aligned. */ +/* _InterlockedOr8 is supported by MSVC on x32 and x64. It is slightly less + * efficient than InterlockedExchange, but InterlockedExchange8 does not exist, + * and interlocked operations on larger targets might require the target to be + * aligned. */ #pragma intrinsic(_InterlockedOr8) static char INLINE uv__atomic_exchange_set(char volatile* target) { diff --git a/deps/libuv/src/win/core.c b/deps/libuv/src/win/core.c index 5fa9b6666..5a76c9003 100644 --- a/deps/libuv/src/win/core.c +++ b/deps/libuv/src/win/core.c @@ -33,6 +33,7 @@ #include "internal.h" #include "queue.h" #include "handle-inl.h" +#include "heap-inl.h" #include "req-inl.h" /* uv_once initialization guards */ @@ -221,6 +222,7 @@ static void uv_init(void) { int uv_loop_init(uv_loop_t* loop) { + struct heap* timer_heap; int err; /* Initialize libuv itself first */ @@ -246,7 +248,11 @@ int uv_loop_init(uv_loop_t* loop) { loop->endgame_handles = NULL; - RB_INIT(&loop->timers); + loop->timer_heap = timer_heap = uv__malloc(sizeof(*timer_heap)); + if (timer_heap == NULL) + goto fail_timers_alloc; + + heap_init(timer_heap); loop->check_handles = NULL; loop->prepare_handles = NULL; @@ -273,7 +279,7 @@ int uv_loop_init(uv_loop_t* loop) { goto fail_async_init; uv__handle_unref(&loop->wq_async); - loop->wq_async.flags |= UV__HANDLE_INTERNAL; + loop->wq_async.flags |= UV_HANDLE_INTERNAL; err = uv__loops_add(loop); if (err) @@ -285,6 +291,10 @@ int uv_loop_init(uv_loop_t* loop) { uv_mutex_destroy(&loop->wq_mutex); fail_mutex_init: + uv__free(timer_heap); + loop->timer_heap = NULL; + +fail_timers_alloc: CloseHandle(loop->iocp); loop->iocp = INVALID_HANDLE_VALUE; @@ -292,6 +302,13 @@ int uv_loop_init(uv_loop_t* loop) { } +void uv_update_time(uv_loop_t* loop) { + uint64_t new_time = uv__hrtime(1000); + assert(new_time >= loop->time); + loop->time = new_time; +} + + void uv__once_init(void) { uv_once(&uv_init_guard_, uv_init); } @@ -320,6 +337,9 @@ void uv__loop_close(uv_loop_t* loop) { uv_mutex_unlock(&loop->wq_mutex); uv_mutex_destroy(&loop->wq_mutex); + uv__free(loop->timer_heap); + loop->timer_heap = NULL; + CloseHandle(loop->iocp); } @@ -359,58 +379,7 @@ int uv_backend_timeout(const uv_loop_t* loop) { } -static void uv_poll(uv_loop_t* loop, DWORD timeout) { - DWORD bytes; - ULONG_PTR key; - OVERLAPPED* overlapped; - uv_req_t* req; - int repeat; - uint64_t timeout_time; - - timeout_time = loop->time + timeout; - - for (repeat = 0; ; repeat++) { - GetQueuedCompletionStatus(loop->iocp, - &bytes, - &key, - &overlapped, - timeout); - - if (overlapped) { - /* Package was dequeued */ - req = uv_overlapped_to_req(overlapped); - uv_insert_pending_req(loop, req); - - /* Some time might have passed waiting for I/O, - * so update the loop time here. - */ - uv_update_time(loop); - } else if (GetLastError() != WAIT_TIMEOUT) { - /* Serious error */ - uv_fatal_error(GetLastError(), "GetQueuedCompletionStatus"); - } else if (timeout > 0) { - /* GetQueuedCompletionStatus can occasionally return a little early. - * Make sure that the desired timeout target time is reached. - */ - uv_update_time(loop); - if (timeout_time > loop->time) { - timeout = (DWORD)(timeout_time - loop->time); - /* The first call to GetQueuedCompletionStatus should return very - * close to the target time and the second should reach it, but - * this is not stated in the documentation. To make sure a busy - * loop cannot happen, the timeout is increased exponentially - * starting on the third round. - */ - timeout += repeat ? (1 << (repeat - 1)) : 0; - continue; - } - } - break; - } -} - - -static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { +static void uv__poll(uv_loop_t* loop, DWORD timeout) { BOOL success; uv_req_t* req; OVERLAPPED_ENTRY overlappeds[128]; @@ -422,12 +391,12 @@ static void uv_poll_ex(uv_loop_t* loop, DWORD timeout) { timeout_time = loop->time + timeout; for (repeat = 0; ; repeat++) { - success = pGetQueuedCompletionStatusEx(loop->iocp, - overlappeds, - ARRAY_SIZE(overlappeds), - &count, - timeout, - FALSE); + success = GetQueuedCompletionStatusEx(loop->iocp, + overlappeds, + ARRAY_SIZE(overlappeds), + &count, + timeout, + FALSE); if (success) { for (i = 0; i < count; i++) { @@ -485,12 +454,6 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { DWORD timeout; int r; int ran_pending; - void (*poll)(uv_loop_t* loop, DWORD timeout); - - if (pGetQueuedCompletionStatusEx) - poll = &uv_poll_ex; - else - poll = &uv_poll; r = uv__loop_alive(loop); if (!r) @@ -498,7 +461,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); - uv_process_timers(loop); + uv__run_timers(loop); ran_pending = uv_process_reqs(loop); uv_idle_invoke(loop); @@ -508,7 +471,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); - (*poll)(loop, timeout); + uv__poll(loop, timeout); uv_check_invoke(loop); uv_process_endgames(loop); @@ -522,7 +485,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { * UV_RUN_NOWAIT makes no guarantees about progress so it's omitted from * the check. */ - uv_process_timers(loop); + uv__run_timers(loop); } r = uv__loop_alive(loop); diff --git a/deps/libuv/src/win/error.c b/deps/libuv/src/win/error.c index 9b03bfef6..24924ba81 100644 --- a/deps/libuv/src/win/error.c +++ b/deps/libuv/src/win/error.c @@ -46,8 +46,8 @@ void uv_fatal_error(const int errorno, const char* syscall) { errmsg = "Unknown error"; } - /* FormatMessage messages include a newline character already, */ - /* so don't add another. */ + /* FormatMessage messages include a newline character already, so don't add + * another. */ if (syscall) { fprintf(stderr, "%s: (%d) %s", syscall, errorno, errmsg); } else { diff --git a/deps/libuv/src/win/fs-event.c b/deps/libuv/src/win/fs-event.c index 14c9af9ad..226e6e7ae 100644 --- a/deps/libuv/src/win/fs-event.c +++ b/deps/libuv/src/win/fs-event.c @@ -419,7 +419,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, * - We are not active, just ignore the callback */ if (!uv__is_active(handle)) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); } return; @@ -543,7 +543,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, } offset = file_info->NextEntryOffset; - } while (offset && !(handle->flags & UV__HANDLE_CLOSING)); + } while (offset && !(handle->flags & UV_HANDLE_CLOSING)); } else { handle->cb(handle, NULL, UV_CHANGE, 0); } @@ -552,7 +552,7 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, handle->cb(handle, NULL, 0, uv_translate_sys_error(err)); } - if (!(handle->flags & UV__HANDLE_CLOSING)) { + if (!(handle->flags & UV_HANDLE_CLOSING)) { uv_fs_event_queue_readdirchanges(loop, handle); } else { uv_want_endgame(loop, (uv_handle_t*)handle); @@ -573,7 +573,7 @@ void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { - if ((handle->flags & UV__HANDLE_CLOSING) && !handle->req_pending) { + if ((handle->flags & UV_HANDLE_CLOSING) && !handle->req_pending) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (handle->buffer) { diff --git a/deps/libuv/src/win/fs.c b/deps/libuv/src/win/fs.c index 30b87ac51..71b6a81a0 100644 --- a/deps/libuv/src/win/fs.c +++ b/deps/libuv/src/win/fs.c @@ -326,12 +326,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, reparse_data->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR); - /* Real symlinks can contain pretty much everything, but the only thing */ - /* we really care about is undoing the implicit conversion to an NT */ - /* namespaced path that CreateSymbolicLink will perform on absolute */ - /* paths. If the path is win32-namespaced then the user must have */ - /* explicitly made it so, and we better just return the unmodified */ - /* reparse data. */ + /* Real symlinks can contain pretty much everything, but the only thing we + * really care about is undoing the implicit conversion to an NT namespaced + * path that CreateSymbolicLink will perform on absolute paths. If the path + * is win32-namespaced then the user must have explicitly made it so, and + * we better just return the unmodified reparse data. */ if (w_target_len >= 4 && w_target[0] == L'\\' && w_target[1] == L'?' && @@ -352,8 +351,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, (w_target[5] == L'N' || w_target[5] == L'n') && (w_target[6] == L'C' || w_target[6] == L'c') && w_target[7] == L'\\') { - /* \??\UNC\\\ - make sure the final path looks like */ - /* \\\\ */ + /* \??\UNC\\\ - make sure the final path looks like + * \\\\ */ w_target += 6; w_target[0] = L'\\'; w_target_len -= 6; @@ -368,11 +367,11 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr, w_target_len = reparse_data->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR); - /* Only treat junctions that look like \??\:\ as symlink. */ - /* Junctions can also be used as mount points, like \??\Volume{}, */ - /* but that's confusing for programs since they wouldn't be able to */ - /* actually understand such a path when returned by uv_readlink(). */ - /* UNC paths are never valid for junctions so we don't care about them. */ + /* Only treat junctions that look like \??\:\ as symlink. Junctions + * can also be used as mount points, like \??\Volume{}, but that's + * confusing for programs since they wouldn't be able to actually + * understand such a path when returned by uv_readlink(). UNC paths are + * never valid for junctions so we don't care about them. */ if (!(w_target_len >= 6 && w_target[0] == L'\\' && w_target[1] == L'?' && @@ -409,8 +408,8 @@ void fs__open(uv_fs_t* req) { int fd, current_umask; int flags = req->fs.info.file_flags; - /* Obtain the active umask. umask() never fails and returns the previous */ - /* umask. */ + /* Obtain the active umask. umask() never fails and returns the previous + * umask. */ current_umask = umask(0); umask(current_umask); @@ -530,8 +529,8 @@ void fs__open(uv_fs_t* req) { DWORD error = GetLastError(); if (error == ERROR_FILE_EXISTS && (flags & UV_FS_O_CREAT) && !(flags & UV_FS_O_EXCL)) { - /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was */ - /* specified, it means the path referred to a directory. */ + /* Special case: when ERROR_FILE_EXISTS happens and UV_FS_O_CREAT was + * specified, it means the path referred to a directory. */ SET_REQ_UV_ERROR(req, UV_EISDIR, error); } else { SET_REQ_WIN32_ERROR(req, GetLastError()); @@ -756,9 +755,9 @@ void fs__unlink(uv_fs_t* req) { } if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { - /* Do not allow deletion of directories, unless it is a symlink. When */ - /* the path refers to a non-symlink directory, report EPERM as mandated */ - /* by POSIX.1. */ + /* Do not allow deletion of directories, unless it is a symlink. When the + * path refers to a non-symlink directory, report EPERM as mandated by + * POSIX.1. */ /* Check if it is a reparse point. If it's not, it's a normal directory. */ if (!(info.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { @@ -767,8 +766,8 @@ void fs__unlink(uv_fs_t* req) { return; } - /* Read the reparse point and check if it is a valid symlink. */ - /* If not, don't unlink. */ + /* Read the reparse point and check if it is a valid symlink. If not, don't + * unlink. */ if (fs__readlink_handle(handle, NULL, NULL) < 0) { DWORD error = GetLastError(); if (error == ERROR_SYMLINK_NOT_SUPPORTED) @@ -1490,6 +1489,7 @@ static void fs__chmod(uv_fs_t* req) { static void fs__fchmod(uv_fs_t* req) { int fd = req->file.fd; + int clear_archive_flag; HANDLE handle; NTSTATUS nt_status; IO_STATUS_BLOCK io_status; @@ -1497,7 +1497,11 @@ static void fs__fchmod(uv_fs_t* req) { VERIFY_FD(fd, req); - handle = uv__get_osfhandle(fd); + handle = ReOpenFile(uv__get_osfhandle(fd), FILE_WRITE_ATTRIBUTES, 0, 0); + if (handle == INVALID_HANDLE_VALUE) { + SET_REQ_WIN32_ERROR(req, GetLastError()); + return; + } nt_status = pNtQueryInformationFile(handle, &io_status, @@ -1507,7 +1511,27 @@ static void fs__fchmod(uv_fs_t* req) { if (!NT_SUCCESS(nt_status)) { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; + goto fchmod_cleanup; + } + + /* Test if the Archive attribute is cleared */ + if ((file_info.FileAttributes & FILE_ATTRIBUTE_ARCHIVE) == 0) { + /* Set Archive flag, otherwise setting or clearing the read-only + flag will not work */ + file_info.FileAttributes |= FILE_ATTRIBUTE_ARCHIVE; + nt_status = pNtSetInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + if (!NT_SUCCESS(nt_status)) { + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); + goto fchmod_cleanup; + } + /* Remeber to clear the flag later on */ + clear_archive_flag = 1; + } else { + clear_archive_flag = 0; } if (req->fs.info.mode & _S_IWRITE) { @@ -1524,10 +1548,28 @@ static void fs__fchmod(uv_fs_t* req) { if (!NT_SUCCESS(nt_status)) { SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); - return; + goto fchmod_cleanup; + } + + if (clear_archive_flag) { + file_info.FileAttributes &= ~FILE_ATTRIBUTE_ARCHIVE; + if (file_info.FileAttributes == 0) { + file_info.FileAttributes = FILE_ATTRIBUTE_NORMAL; + } + nt_status = pNtSetInformationFile(handle, + &io_status, + &file_info, + sizeof file_info, + FileBasicInformation); + if (!NT_SUCCESS(nt_status)) { + SET_REQ_WIN32_ERROR(req, pRtlNtStatusToDosError(nt_status)); + goto fchmod_cleanup; + } } SET_REQ_SUCCESS(req); +fchmod_cleanup: + CloseHandle(handle); } @@ -1787,17 +1829,13 @@ static void fs__symlink(uv_fs_t* req) { fs__create_junction(req, pathw, new_pathw); return; } - if (!pCreateSymbolicLinkW) { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - return; - } if (req->fs.info.file_flags & UV_FS_SYMLINK_DIR) flags = SYMBOLIC_LINK_FLAG_DIRECTORY | uv__file_symlink_usermode_flag; else flags = uv__file_symlink_usermode_flag; - if (pCreateSymbolicLinkW(new_pathw, pathw, flags)) { + if (CreateSymbolicLinkW(new_pathw, pathw, flags)) { SET_REQ_RESULT(req, 0); return; } @@ -1854,7 +1892,7 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { WCHAR* w_realpath_ptr = NULL; WCHAR* w_realpath_buf; - w_realpath_len = pGetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); + w_realpath_len = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME_NAME_DOS); if (w_realpath_len == 0) { return -1; } @@ -1866,10 +1904,8 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { } w_realpath_ptr = w_realpath_buf; - if (pGetFinalPathNameByHandleW(handle, - w_realpath_ptr, - w_realpath_len, - VOLUME_NAME_DOS) == 0) { + if (GetFinalPathNameByHandleW( + handle, w_realpath_ptr, w_realpath_len, VOLUME_NAME_DOS) == 0) { uv__free(w_realpath_buf); SetLastError(ERROR_INVALID_HANDLE); return -1; @@ -1901,11 +1937,6 @@ static size_t fs__realpath_handle(HANDLE handle, char** realpath_ptr) { static void fs__realpath(uv_fs_t* req) { HANDLE handle; - if (!pGetFinalPathNameByHandleW) { - SET_REQ_UV_ERROR(req, UV_ENOSYS, ERROR_NOT_SUPPORTED); - return; - } - handle = CreateFileW(req->file.pathw, 0, 0, @@ -1940,6 +1971,10 @@ static void fs__fchown(uv_fs_t* req) { } +static void fs__lchown(uv_fs_t* req) { + req->result = 0; +} + static void uv__fs_work(struct uv__work* w) { uv_fs_t* req; @@ -1977,6 +2012,7 @@ static void uv__fs_work(struct uv__work* w) { XX(REALPATH, realpath) XX(CHOWN, chown) XX(FCHOWN, fchown); + XX(LCHOWN, lchown); default: assert(!"bad uv_fs_type"); } @@ -2262,6 +2298,19 @@ int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_uid_t uid, } +int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, + uv_gid_t gid, uv_fs_cb cb) { + int err; + + INIT(UV_FS_LCHOWN); + err = fs__capture_path(req, path, NULL, cb != NULL); + if (err) { + return uv_translate_sys_error(err); + } + POST; +} + + int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb) { int err; diff --git a/deps/libuv/src/win/getaddrinfo.c b/deps/libuv/src/win/getaddrinfo.c index 282d919cf..063b4937c 100644 --- a/deps/libuv/src/win/getaddrinfo.c +++ b/deps/libuv/src/win/getaddrinfo.c @@ -71,8 +71,8 @@ int uv__getaddrinfo_translate_error(int sys_err) { #endif -/* adjust size value to be multiple of 4. Use to keep pointer aligned */ -/* Do we need different versions of this for different architectures? */ +/* Adjust size value to be multiple of 4. Use to keep pointer aligned. + * Do we need different versions of this for different architectures? */ #define ALIGNED_SIZE(X) ((((X) + 3) >> 2) << 2) #ifndef NDIS_IF_MAX_STRING_SIZE @@ -124,8 +124,7 @@ static void uv__getaddrinfo_done(struct uv__work* w, int status) { } if (req->retcode == 0) { - /* convert addrinfoW to addrinfo */ - /* first calculate required length */ + /* Convert addrinfoW to addrinfo. First calculate required length. */ addrinfow_ptr = req->addrinfow; while (addrinfow_ptr != NULL) { addrinfo_len += addrinfo_struct_len + @@ -313,8 +312,8 @@ int uv_getaddrinfo(uv_loop_t* loop, /* save alloc_ptr now so we can free if error */ req->alloc = (void*)alloc_ptr; - /* convert node string to UTF16 into allocated memory and save pointer in */ - /* the request. */ + /* Convert node string to UTF16 into allocated memory and save pointer in the + * request. */ if (node != NULL) { req->node = (WCHAR*)alloc_ptr; if (MultiByteToWideChar(CP_UTF8, @@ -331,8 +330,8 @@ int uv_getaddrinfo(uv_loop_t* loop, req->node = NULL; } - /* convert service string to UTF16 into allocated memory and save pointer */ - /* in the req. */ + /* Convert service string to UTF16 into allocated memory and save pointer in + * the req. */ if (service != NULL) { req->service = (WCHAR*)alloc_ptr; if (MultiByteToWideChar(CP_UTF8, diff --git a/deps/libuv/src/win/handle-inl.h b/deps/libuv/src/win/handle-inl.h index 8d0334cc5..82c657d57 100644 --- a/deps/libuv/src/win/handle-inl.h +++ b/deps/libuv/src/win/handle-inl.h @@ -32,7 +32,7 @@ #define DECREASE_ACTIVE_COUNT(loop, handle) \ do { \ if (--(handle)->activecnt == 0 && \ - !((handle)->flags & UV__HANDLE_CLOSING)) { \ + !((handle)->flags & UV_HANDLE_CLOSING)) { \ uv__handle_stop((handle)); \ } \ assert((handle)->activecnt >= 0); \ @@ -53,7 +53,7 @@ assert(handle->reqs_pending > 0); \ handle->reqs_pending--; \ \ - if (handle->flags & UV__HANDLE_CLOSING && \ + if (handle->flags & UV_HANDLE_CLOSING && \ handle->reqs_pending == 0) { \ uv_want_endgame(loop, (uv_handle_t*)handle); \ } \ @@ -62,14 +62,14 @@ #define uv__handle_closing(handle) \ do { \ - assert(!((handle)->flags & UV__HANDLE_CLOSING)); \ + assert(!((handle)->flags & UV_HANDLE_CLOSING)); \ \ - if (!(((handle)->flags & UV__HANDLE_ACTIVE) && \ - ((handle)->flags & UV__HANDLE_REF))) \ + if (!(((handle)->flags & UV_HANDLE_ACTIVE) && \ + ((handle)->flags & UV_HANDLE_REF))) \ uv__active_handle_add((uv_handle_t*) (handle)); \ \ - (handle)->flags |= UV__HANDLE_CLOSING; \ - (handle)->flags &= ~UV__HANDLE_ACTIVE; \ + (handle)->flags |= UV_HANDLE_CLOSING; \ + (handle)->flags &= ~UV_HANDLE_ACTIVE; \ } while (0) @@ -126,7 +126,8 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { break; case UV_TIMER: - uv_timer_endgame(loop, (uv_timer_t*) handle); + uv__timer_close((uv_timer_t*) handle); + uv__handle_close(handle); break; case UV_PREPARE: @@ -164,10 +165,10 @@ INLINE static void uv_process_endgames(uv_loop_t* loop) { INLINE static HANDLE uv__get_osfhandle(int fd) { - /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. */ - /* But it also correctly checks the FD and returns INVALID_HANDLE_VALUE */ - /* for invalid FDs in release builds (or if you let the assert continue). */ - /* So this wrapper function disables asserts when calling _get_osfhandle. */ + /* _get_osfhandle() raises an assert in debug builds if the FD is invalid. + * But it also correctly checks the FD and returns INVALID_HANDLE_VALUE for + * invalid FDs in release builds (or if you let the assert continue). So this + * wrapper function disables asserts when calling _get_osfhandle. */ HANDLE handle; UV_BEGIN_DISABLE_CRT_ASSERT(); diff --git a/deps/libuv/src/win/handle.c b/deps/libuv/src/win/handle.c index 39150702d..738d7ff32 100644 --- a/deps/libuv/src/win/handle.c +++ b/deps/libuv/src/win/handle.c @@ -59,15 +59,15 @@ uv_handle_type uv_guess_handle(uv_file file) { int uv_is_active(const uv_handle_t* handle) { - return (handle->flags & UV__HANDLE_ACTIVE) && - !(handle->flags & UV__HANDLE_CLOSING); + return (handle->flags & UV_HANDLE_ACTIVE) && + !(handle->flags & UV_HANDLE_CLOSING); } void uv_close(uv_handle_t* handle, uv_close_cb cb) { uv_loop_t* loop = handle->loop; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { assert(0); return; } @@ -150,7 +150,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb cb) { int uv_is_closing(const uv_handle_t* handle) { - return !!(handle->flags & (UV__HANDLE_CLOSING | UV_HANDLE_CLOSED)); + return !!(handle->flags & (UV_HANDLE_CLOSING | UV_HANDLE_CLOSED)); } diff --git a/deps/libuv/src/win/internal.h b/deps/libuv/src/win/internal.h index cce4e204d..b37b4c0c9 100644 --- a/deps/libuv/src/win/internal.h +++ b/deps/libuv/src/win/internal.h @@ -25,7 +25,7 @@ #include "uv.h" #include "../uv-common.h" -#include "tree.h" +#include "uv/tree.h" #include "winapi.h" #include "winsock.h" @@ -57,78 +57,15 @@ extern UV_THREAD_LOCAL int uv__crt_assert_enabled; #define UV_END_DISABLE_CRT_ASSERT() #endif -/* - * Handles - * (also see handle-inl.h) - */ - -/* Used by all handles. */ -#define UV_HANDLE_CLOSED 0x00000002 -#define UV_HANDLE_ENDGAME_QUEUED 0x00000008 - -/* uv-common.h: #define UV__HANDLE_CLOSING 0x00000001 */ -/* uv-common.h: #define UV__HANDLE_ACTIVE 0x00000040 */ -/* uv-common.h: #define UV__HANDLE_REF 0x00000020 */ -/* uv-common.h: #define UV_HANDLE_INTERNAL 0x00000080 */ - -/* Used by streams and UDP handles. */ -#define UV_HANDLE_READING 0x00000100 -#define UV_HANDLE_BOUND 0x00000200 -#define UV_HANDLE_LISTENING 0x00000800 -#define UV_HANDLE_CONNECTION 0x00001000 -#define UV_HANDLE_READABLE 0x00008000 -#define UV_HANDLE_WRITABLE 0x00010000 -#define UV_HANDLE_READ_PENDING 0x00020000 -#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00040000 -#define UV_HANDLE_ZERO_READ 0x00080000 -#define UV_HANDLE_EMULATE_IOCP 0x00100000 -#define UV_HANDLE_BLOCKING_WRITES 0x00200000 -#define UV_HANDLE_CANCELLATION_PENDING 0x00400000 - -/* Used by uv_tcp_t and uv_udp_t handles */ -#define UV_HANDLE_IPV6 0x01000000 - -/* Only used by uv_tcp_t handles. */ -#define UV_HANDLE_TCP_NODELAY 0x02000000 -#define UV_HANDLE_TCP_KEEPALIVE 0x04000000 -#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 -#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000 -#define UV_HANDLE_TCP_SOCKET_CLOSED 0x20000000 -#define UV_HANDLE_SHARED_TCP_SOCKET 0x40000000 - -/* Only used by uv_pipe_t handles. */ -#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x01000000 -#define UV_HANDLE_PIPESERVER 0x02000000 -#define UV_HANDLE_PIPE_READ_CANCELABLE 0x04000000 - -/* Only used by uv_tty_t handles. */ -#define UV_HANDLE_TTY_READABLE 0x01000000 -#define UV_HANDLE_TTY_RAW 0x02000000 -#define UV_HANDLE_TTY_SAVED_POSITION 0x04000000 -#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x08000000 - -/* Only used by uv_poll_t handles. */ -#define UV_HANDLE_POLL_SLOW 0x02000000 - - -/* - * Requests: see req-inl.h - */ - - -/* - * Streams: see stream-inl.h - */ - - /* * TCP */ typedef struct { WSAPROTOCOL_INFOW socket_info; - int delayed_error; -} uv__ipc_socket_info_ex; + uint32_t delayed_error; + uint32_t flags; /* Either zero or UV_HANDLE_CONNECTION. */ +} uv__ipc_socket_xfer_info_t; int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb); int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client); @@ -150,11 +87,10 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp); void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection); - -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info); +int uv__tcp_xfer_export(uv_tcp_t* handle, + int pid, + uv__ipc_socket_xfer_info_t* xfer_info); +int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info); /* @@ -178,14 +114,14 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb); int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client); int uv_pipe_read_start(uv_pipe_t* handle, uv_alloc_cb alloc_cb, uv_read_cb read_cb); -int uv_pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); -int uv_pipe_write2(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, - const uv_buf_t bufs[], unsigned int nbufs, uv_stream_t* send_handle, - uv_write_cb cb); -void uv__pipe_pause_read(uv_pipe_t* handle); -void uv__pipe_unpause_read(uv_pipe_t* handle); -void uv__pipe_stop_read(uv_pipe_t* handle); +void uv__pipe_read_stop(uv_pipe_t* handle); +int uv__pipe_write(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t bufs[], + size_t nbufs, + uv_stream_t* send_handle, + uv_write_cb cb); void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, uv_req_t* req); @@ -247,15 +183,6 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle); void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle); -/* - * Timers - */ -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle); - -DWORD uv__next_timeout(const uv_loop_t* loop); -void uv_process_timers(uv_loop_t* loop); - - /* * Loop watchers */ @@ -332,7 +259,6 @@ void uv__fs_poll_endgame(uv_loop_t* loop, uv_fs_poll_t* handle); void uv__util_init(void); uint64_t uv__hrtime(double scale); -int uv_current_pid(void); __declspec(noreturn) void uv_fatal_error(const int errorno, const char* syscall); int uv__getpwuid_r(uv_passwd_t* pwd); int uv__convert_utf16_to_utf8(const WCHAR* utf16, int utf16len, char** utf8); diff --git a/deps/libuv/src/win/loop-watcher.c b/deps/libuv/src/win/loop-watcher.c index 20e4509f8..ad7fbea16 100644 --- a/deps/libuv/src/win/loop-watcher.c +++ b/deps/libuv/src/win/loop-watcher.c @@ -27,7 +27,7 @@ void uv_loop_watcher_endgame(uv_loop_t* loop, uv_handle_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { assert(!(handle->flags & UV_HANDLE_CLOSED)); handle->flags |= UV_HANDLE_CLOSED; uv__handle_close(handle); diff --git a/deps/libuv/src/win/pipe.c b/deps/libuv/src/win/pipe.c index 0ecfbf1f0..42380f659 100644 --- a/deps/libuv/src/win/pipe.c +++ b/deps/libuv/src/win/pipe.c @@ -21,9 +21,9 @@ #include #include -#include #include #include +#include #include "uv.h" #include "internal.h" @@ -34,26 +34,14 @@ #include #include -typedef struct uv__ipc_queue_item_s uv__ipc_queue_item_t; - -struct uv__ipc_queue_item_s { - /* - * NOTE: It is important for socket_info_ex to be the first field, - * because we will we assigning it to the pending_ipc_info.socket_info - */ - uv__ipc_socket_info_ex socket_info_ex; - QUEUE member; - int tcp_connection; -}; - /* A zero-size buffer for use by uv_pipe_read */ static char uv_zero_[] = ""; /* Null uv_buf_t */ static const uv_buf_t uv_null_buf_ = { 0, NULL }; -/* The timeout that the pipe will wait for the remote end to write data */ -/* when the local ends wants to shut it down. */ +/* The timeout that the pipe will wait for the remote end to write data when + * the local ends wants to shut it down. */ static const int64_t eof_timeout = 50; /* ms */ static const int default_pending_pipe_instances = 4; @@ -62,22 +50,27 @@ static const int default_pending_pipe_instances = 4; static char pipe_prefix[] = "\\\\?\\pipe"; static const int pipe_prefix_len = sizeof(pipe_prefix) - 1; -/* IPC protocol flags. */ -#define UV_IPC_RAW_DATA 0x0001 -#define UV_IPC_TCP_SERVER 0x0002 -#define UV_IPC_TCP_CONNECTION 0x0004 +/* IPC incoming xfer queue item. */ +typedef struct { + uv__ipc_socket_xfer_info_t xfer_info; + QUEUE member; +} uv__ipc_xfer_queue_item_t; + +/* IPC frame types. */ +enum { UV__IPC_DATA_FRAME = 0, UV__IPC_XFER_FRAME = 1 }; /* IPC frame header. */ typedef struct { - int flags; - uint64_t raw_data_length; -} uv_ipc_frame_header_t; + uint32_t type; + uint32_t payload_length; +} uv__ipc_frame_header_t; -/* IPC frame, which contains an imported TCP socket stream. */ +/* Coalesced write request. */ typedef struct { - uv_ipc_frame_header_t header; - uv__ipc_socket_info_ex socket_info_ex; -} uv_ipc_frame_uv_stream; + uv_write_t req; /* Internal heap-allocated write request. */ + uv_write_t* user_req; /* Pointer to user-specified uv_write_t. */ +} uv__coalesced_write_t; + static void eof_timer_init(uv_pipe_t* pipe); static void eof_timer_start(uv_pipe_t* pipe); @@ -98,15 +91,12 @@ int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { handle->reqs_pending = 0; handle->handle = INVALID_HANDLE_VALUE; handle->name = NULL; - handle->pipe.conn.ipc_pid = 0; - handle->pipe.conn.remaining_ipc_rawdata_bytes = 0; - QUEUE_INIT(&handle->pipe.conn.pending_ipc_info.queue); - handle->pipe.conn.pending_ipc_info.queue_len = 0; + handle->pipe.conn.ipc_remote_pid = 0; + handle->pipe.conn.ipc_data_frame.payload_remaining = 0; + QUEUE_INIT(&handle->pipe.conn.ipc_xfer_queue); + handle->pipe.conn.ipc_xfer_queue_length = 0; handle->ipc = ipc; handle->pipe.conn.non_overlapped_writes_tail = NULL; - handle->pipe.conn.readfile_thread = NULL; - - UV_REQ_INIT(&handle->pipe.conn.ipc_header_write_req, UV_UNKNOWN_REQ); return 0; } @@ -117,10 +107,9 @@ static void uv_pipe_connection_init(uv_pipe_t* handle) { handle->read_req.data = handle; handle->pipe.conn.eof_timer = NULL; assert(!(handle->flags & UV_HANDLE_PIPESERVER)); - if (pCancelSynchronousIo && - handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - uv_mutex_init(&handle->pipe.conn.readfile_mutex); - handle->flags |= UV_HANDLE_PIPE_READ_CANCELABLE; + if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + handle->pipe.conn.readfile_thread_handle = NULL; + InitializeCriticalSection(&handle->pipe.conn.readfile_thread_lock); } } @@ -347,12 +336,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { NTSTATUS nt_status; IO_STATUS_BLOCK io_status; FILE_PIPE_LOCAL_INFORMATION pipe_info; - uv__ipc_queue_item_t* item; - - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - handle->flags &= ~UV_HANDLE_PIPE_READ_CANCELABLE; - uv_mutex_destroy(&handle->pipe.conn.readfile_mutex); - } + uv__ipc_xfer_queue_item_t* xfer_queue_item; if ((handle->flags & UV_HANDLE_CONNECTION) && handle->stream.conn.shutdown_req != NULL && @@ -362,7 +346,7 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { /* Clear the shutdown_req field so we don't go here again. */ handle->stream.conn.shutdown_req = NULL; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { UNREGISTER_HANDLE_REQ(loop, handle, req); /* Already closing. Cancel the shutdown. */ @@ -423,33 +407,33 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { } } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); if (handle->flags & UV_HANDLE_CONNECTION) { /* Free pending sockets */ - while (!QUEUE_EMPTY(&handle->pipe.conn.pending_ipc_info.queue)) { + while (!QUEUE_EMPTY(&handle->pipe.conn.ipc_xfer_queue)) { QUEUE* q; SOCKET socket; - q = QUEUE_HEAD(&handle->pipe.conn.pending_ipc_info.queue); + q = QUEUE_HEAD(&handle->pipe.conn.ipc_xfer_queue); QUEUE_REMOVE(q); - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); + xfer_queue_item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); /* Materialize socket and close it */ socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, - &item->socket_info_ex.socket_info, + &xfer_queue_item->xfer_info.socket_info, 0, WSA_FLAG_OVERLAPPED); - uv__free(item); + uv__free(xfer_queue_item); if (socket != INVALID_SOCKET) closesocket(socket); } - handle->pipe.conn.pending_ipc_info.queue_len = 0; + handle->pipe.conn.ipc_xfer_queue_length = 0; if (handle->flags & UV_HANDLE_EMULATE_IOCP) { if (handle->read_req.wait_handle != INVALID_HANDLE_VALUE) { @@ -461,6 +445,9 @@ void uv_pipe_endgame(uv_loop_t* loop, uv_pipe_t* handle) { handle->read_req.event_handle = NULL; } } + + if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) + DeleteCriticalSection(&handle->pipe.conn.readfile_thread_lock); } if (handle->flags & UV_HANDLE_PIPESERVER) { @@ -595,8 +582,8 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { loop = handle->loop; assert(loop); - /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. */ - /* We wait for the pipe to become available with WaitNamedPipe. */ + /* We're here because CreateFile on a pipe returned ERROR_PIPE_BUSY. We wait + * for the pipe to become available with WaitNamedPipe. */ while (WaitNamedPipeW(handle->name, 30000)) { /* The pipe is now available, try to connect. */ pipeHandle = open_named_pipe(handle->name, &duplex_flags); @@ -706,48 +693,68 @@ void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, } -void uv__pipe_pause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - /* Pause the ReadFile task briefly, to work - around the Windows kernel bug that causes - any access to a NamedPipe to deadlock if - any process has called ReadFile */ - HANDLE h; - uv_mutex_lock(&handle->pipe.conn.readfile_mutex); - h = handle->pipe.conn.readfile_thread; - while (h) { - /* spinlock: we expect this to finish quickly, - or we are probably about to deadlock anyways - (in the kernel), so it doesn't matter */ - pCancelSynchronousIo(h); - SwitchToThread(); /* yield thread control briefly */ - h = handle->pipe.conn.readfile_thread; - } - } -} +void uv__pipe_interrupt_read(uv_pipe_t* handle) { + BOOL r; + + if (!(handle->flags & UV_HANDLE_READ_PENDING)) + return; /* No pending reads. */ + if (handle->flags & UV_HANDLE_CANCELLATION_PENDING) + return; /* Already cancelled. */ + if (handle->handle == INVALID_HANDLE_VALUE) + return; /* Pipe handle closed. */ + if (!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)) { + /* Cancel asynchronous read. */ + r = CancelIoEx(handle->handle, &handle->read_req.u.io.overlapped); + assert(r || GetLastError() == ERROR_NOT_FOUND); + + } else { + /* Cancel synchronous read (which is happening in the thread pool). */ + HANDLE thread; + volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle; + + EnterCriticalSection(&handle->pipe.conn.readfile_thread_lock); + + thread = *thread_ptr; + if (thread == NULL) { + /* The thread pool thread has not yet reached the point of blocking, we + * can pre-empt it by setting thread_handle to INVALID_HANDLE_VALUE. */ + *thread_ptr = INVALID_HANDLE_VALUE; + + } else { + /* Spin until the thread has acknowledged (by setting the thread to + * INVALID_HANDLE_VALUE) that it is past the point of blocking. */ + while (thread != INVALID_HANDLE_VALUE) { + r = CancelSynchronousIo(thread); + assert(r || GetLastError() == ERROR_NOT_FOUND); + SwitchToThread(); /* Yield thread. */ + thread = *thread_ptr; + } + } -void uv__pipe_unpause_read(uv_pipe_t* handle) { - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_unlock(&handle->pipe.conn.readfile_mutex); + LeaveCriticalSection(&handle->pipe.conn.readfile_thread_lock); } + + /* Set flag to indicate that read has been cancelled. */ + handle->flags |= UV_HANDLE_CANCELLATION_PENDING; } -void uv__pipe_stop_read(uv_pipe_t* handle) { +void uv__pipe_read_stop(uv_pipe_t* handle) { handle->flags &= ~UV_HANDLE_READING; - uv__pipe_pause_read((uv_pipe_t*)handle); - uv__pipe_unpause_read((uv_pipe_t*)handle); + DECREASE_ACTIVE_COUNT(handle->loop, handle); + + uv__pipe_interrupt_read(handle); } -/* Cleans up uv_pipe_t (server or connection) and all resources associated */ -/* with it. */ +/* Cleans up uv_pipe_t (server or connection) and all resources associated with + * it. */ void uv_pipe_cleanup(uv_loop_t* loop, uv_pipe_t* handle) { int i; HANDLE pipeHandle; - uv__pipe_stop_read(handle); + uv__pipe_interrupt_read(handle); if (handle->name) { uv__free(handle->name); @@ -857,23 +864,21 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { uv_pipe_t* pipe_client; uv_pipe_accept_t* req; QUEUE* q; - uv__ipc_queue_item_t* item; + uv__ipc_xfer_queue_item_t* item; int err; if (server->ipc) { - if (QUEUE_EMPTY(&server->pipe.conn.pending_ipc_info.queue)) { + if (QUEUE_EMPTY(&server->pipe.conn.ipc_xfer_queue)) { /* No valid pending sockets. */ return WSAEWOULDBLOCK; } - q = QUEUE_HEAD(&server->pipe.conn.pending_ipc_info.queue); + q = QUEUE_HEAD(&server->pipe.conn.ipc_xfer_queue); QUEUE_REMOVE(q); - server->pipe.conn.pending_ipc_info.queue_len--; - item = QUEUE_DATA(q, uv__ipc_queue_item_t, member); + server->pipe.conn.ipc_xfer_queue_length--; + item = QUEUE_DATA(q, uv__ipc_xfer_queue_item_t, member); - err = uv_tcp_import((uv_tcp_t*)client, - &item->socket_info_ex, - item->tcp_connection); + err = uv__tcp_xfer_import((uv_tcp_t*) client, &item->xfer_info); if (err != 0) return err; @@ -882,8 +887,8 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { } else { pipe_client = (uv_pipe_t*)client; - /* Find a connection instance that has been connected, but not yet */ - /* accepted. */ + /* Find a connection instance that has been connected, but not yet + * accepted. */ req = server->pipe.serv.pending_accepts; if (!req) { @@ -901,7 +906,7 @@ int uv_pipe_accept(uv_pipe_t* server, uv_stream_t* client) { req->next_pending = NULL; req->pipeHandle = INVALID_HANDLE_VALUE; - if (!(server->flags & UV__HANDLE_CLOSING)) { + if (!(server->flags & UV_HANDLE_CLOSING)) { uv_pipe_queue_accept(loop, server, req, FALSE); } } @@ -946,74 +951,75 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { } -static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* parameter) { - int result; - DWORD bytes; - uv_read_t* req = (uv_read_t*) parameter; +static DWORD WINAPI uv_pipe_zero_readfile_thread_proc(void* arg) { + uv_read_t* req = (uv_read_t*) arg; uv_pipe_t* handle = (uv_pipe_t*) req->data; uv_loop_t* loop = handle->loop; - HANDLE hThread = NULL; + volatile HANDLE* thread_ptr = &handle->pipe.conn.readfile_thread_handle; + CRITICAL_SECTION* lock = &handle->pipe.conn.readfile_thread_lock; + HANDLE thread; + DWORD bytes; DWORD err; - uv_mutex_t *m = &handle->pipe.conn.readfile_mutex; - assert(req != NULL); assert(req->type == UV_READ); assert(handle->type == UV_NAMED_PIPE); - if (handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - uv_mutex_lock(m); /* mutex controls *setting* of readfile_thread */ - if (DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), - GetCurrentProcess(), &hThread, - 0, FALSE, DUPLICATE_SAME_ACCESS)) { - handle->pipe.conn.readfile_thread = hThread; - } else { - hThread = NULL; - } - uv_mutex_unlock(m); + err = 0; + + /* Create a handle to the current thread. */ + if (!DuplicateHandle(GetCurrentProcess(), + GetCurrentThread(), + GetCurrentProcess(), + &thread, + 0, + FALSE, + DUPLICATE_SAME_ACCESS)) { + err = GetLastError(); + goto out1; } -restart_readfile: - if (handle->flags & UV_HANDLE_READING) { - result = ReadFile(handle->handle, - &uv_zero_, - 0, - &bytes, - NULL); - if (!result) { - err = GetLastError(); - if (err == ERROR_OPERATION_ABORTED && - handle->flags & UV_HANDLE_PIPE_READ_CANCELABLE) { - if (handle->flags & UV_HANDLE_READING) { - /* just a brief break to do something else */ - handle->pipe.conn.readfile_thread = NULL; - /* resume after it is finished */ - uv_mutex_lock(m); - handle->pipe.conn.readfile_thread = hThread; - uv_mutex_unlock(m); - goto restart_readfile; - } else { - result = 1; /* successfully stopped reading */ - } - } - } + + /* The lock needs to be held when thread handle is modified. */ + EnterCriticalSection(lock); + if (*thread_ptr == INVALID_HANDLE_VALUE) { + /* uv__pipe_interrupt_read() cancelled reading before we got here. */ + err = ERROR_OPERATION_ABORTED; } else { - result = 1; /* successfully aborted read before it even started */ - } - if (hThread) { - assert(hThread == handle->pipe.conn.readfile_thread); - /* mutex does not control clearing readfile_thread */ - handle->pipe.conn.readfile_thread = NULL; - uv_mutex_lock(m); - /* only when we hold the mutex lock is it safe to - open or close the handle */ - CloseHandle(hThread); - uv_mutex_unlock(m); + /* Let main thread know which worker thread is doing the blocking read. */ + assert(*thread_ptr == NULL); + *thread_ptr = thread; } + LeaveCriticalSection(lock); - if (!result) { - SET_REQ_ERROR(req, err); - } + if (err) + goto out2; + + /* Block the thread until data is available on the pipe, or the read is + * cancelled. */ + if (!ReadFile(handle->handle, &uv_zero_, 0, &bytes, NULL)) + err = GetLastError(); + + /* Let the main thread know the worker is past the point of blocking. */ + assert(thread == *thread_ptr); + *thread_ptr = INVALID_HANDLE_VALUE; + /* Briefly acquire the mutex. Since the main thread holds the lock while it + * is spinning trying to cancel this thread's I/O, we will block here until + * it stops doing that. */ + EnterCriticalSection(lock); + LeaveCriticalSection(lock); + +out2: + /* Close the handle to the current thread. */ + CloseHandle(thread); + +out1: + /* Set request status and post a completion record to the IOCP. */ + if (err) + SET_REQ_ERROR(req, err); + else + SET_REQ_SUCCESS(req); POST_COMPLETION_FOR_REQ(loop, req); + return 0; } @@ -1095,6 +1101,7 @@ static void uv_pipe_queue_read(uv_loop_t* loop, uv_pipe_t* handle) { req = &handle->read_req; if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + handle->pipe.conn.readfile_thread_handle = NULL; /* Reset cancellation. */ if (!QueueUserWorkItem(&uv_pipe_zero_readfile_thread_proc, req, WT_EXECUTELONGFUNCTION)) { @@ -1162,8 +1169,8 @@ int uv_pipe_read_start(uv_pipe_t* handle, handle->read_cb = read_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) uv_pipe_queue_read(loop, handle); @@ -1219,154 +1226,111 @@ static void uv_queue_non_overlapped_write(uv_pipe_t* handle) { } -static int uv_pipe_write_impl(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_stream_t* send_handle, - uv_write_cb cb) { - int err; - int result; - uv_tcp_t* tcp_send_handle; - uv_write_t* ipc_header_req = NULL; - uv_ipc_frame_uv_stream ipc_frame; +static int uv__build_coalesced_write_req(uv_write_t* user_req, + const uv_buf_t bufs[], + size_t nbufs, + uv_write_t** req_out, + uv_buf_t* write_buf_out) { + /* Pack into a single heap-allocated buffer: + * (a) a uv_write_t structure where libuv stores the actual state. + * (b) a pointer to the original uv_write_t. + * (c) data from all `bufs` entries. + */ + char* heap_buffer; + size_t heap_buffer_length, heap_buffer_offset; + uv__coalesced_write_t* coalesced_write_req; /* (a) + (b) */ + char* data_start; /* (c) */ + size_t data_length; + unsigned int i; + + /* Compute combined size of all combined buffers from `bufs`. */ + data_length = 0; + for (i = 0; i < nbufs; i++) + data_length += bufs[i].len; + + /* The total combined size of data buffers should not exceed UINT32_MAX, + * because WriteFile() won't accept buffers larger than that. */ + if (data_length > UINT32_MAX) + return WSAENOBUFS; /* Maps to UV_ENOBUFS. */ + + /* Compute heap buffer size. */ + heap_buffer_length = sizeof *coalesced_write_req + /* (a) + (b) */ + data_length; /* (c) */ + + /* Allocate buffer. */ + heap_buffer = uv__malloc(heap_buffer_length); + if (heap_buffer == NULL) + return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ + + /* Copy uv_write_t information to the buffer. */ + coalesced_write_req = (uv__coalesced_write_t*) heap_buffer; + coalesced_write_req->req = *user_req; /* copy (a) */ + coalesced_write_req->req.coalesced = 1; + coalesced_write_req->user_req = user_req; /* copy (b) */ + heap_buffer_offset = sizeof *coalesced_write_req; /* offset (a) + (b) */ + + /* Copy data buffers to the heap buffer. */ + data_start = &heap_buffer[heap_buffer_offset]; + for (i = 0; i < nbufs; i++) { + memcpy(&heap_buffer[heap_buffer_offset], + bufs[i].base, + bufs[i].len); /* copy (c) */ + heap_buffer_offset += bufs[i].len; /* offset (c) */ + } + assert(heap_buffer_offset == heap_buffer_length); + + /* Set out arguments and return. */ + *req_out = &coalesced_write_req->req; + *write_buf_out = uv_buf_init(data_start, (unsigned int) data_length); + return 0; +} - if (nbufs != 1 && (nbufs != 0 || !send_handle)) { - return ERROR_NOT_SUPPORTED; - } - /* Only TCP handles are supported for sharing. */ - if (send_handle && ((send_handle->type != UV_TCP) || - (!(send_handle->flags & UV_HANDLE_BOUND) && - !(send_handle->flags & UV_HANDLE_CONNECTION)))) { - return ERROR_NOT_SUPPORTED; - } +static int uv__pipe_write_data(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t bufs[], + size_t nbufs, + uv_stream_t* send_handle, + uv_write_cb cb, + int copy_always) { + int err; + int result; + uv_buf_t write_buf; assert(handle->handle != INVALID_HANDLE_VALUE); UV_REQ_INIT(req, UV_WRITE); req->handle = (uv_stream_t*) handle; + req->send_handle = send_handle; req->cb = cb; - req->ipc_header = 0; + /* Private fields. */ + req->coalesced = 0; req->event_handle = NULL; req->wait_handle = INVALID_HANDLE_VALUE; memset(&req->u.io.overlapped, 0, sizeof(req->u.io.overlapped)); - - if (handle->ipc) { - assert(!(handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - ipc_frame.header.flags = 0; - - /* Use the IPC framing protocol. */ - if (send_handle) { - tcp_send_handle = (uv_tcp_t*)send_handle; - - if (handle->pipe.conn.ipc_pid == 0) { - handle->pipe.conn.ipc_pid = uv_current_pid(); - } - - err = uv_tcp_duplicate_socket(tcp_send_handle, handle->pipe.conn.ipc_pid, - &ipc_frame.socket_info_ex.socket_info); - if (err) { - return err; - } - - ipc_frame.socket_info_ex.delayed_error = tcp_send_handle->delayed_error; - - ipc_frame.header.flags |= UV_IPC_TCP_SERVER; - - if (tcp_send_handle->flags & UV_HANDLE_CONNECTION) { - ipc_frame.header.flags |= UV_IPC_TCP_CONNECTION; - } - } - - if (nbufs == 1) { - ipc_frame.header.flags |= UV_IPC_RAW_DATA; - ipc_frame.header.raw_data_length = bufs[0].len; - } - - /* - * Use the provided req if we're only doing a single write. - * If we're doing multiple writes, use ipc_header_write_req to do - * the first write, and then use the provided req for the second write. - */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - ipc_header_req = req; - } else { - /* - * Try to use the preallocated write req if it's available. - * Otherwise allocate a new one. - */ - if (handle->pipe.conn.ipc_header_write_req.type != UV_WRITE) { - ipc_header_req = (uv_write_t*)&handle->pipe.conn.ipc_header_write_req; - } else { - ipc_header_req = (uv_write_t*)uv__malloc(sizeof(uv_write_t)); - if (!ipc_header_req) { - uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - } - } - - UV_REQ_INIT(ipc_header_req, UV_WRITE); - ipc_header_req->handle = (uv_stream_t*) handle; - ipc_header_req->cb = NULL; - ipc_header_req->ipc_header = 1; - } - - /* Write the header or the whole frame. */ - memset(&ipc_header_req->u.io.overlapped, 0, - sizeof(ipc_header_req->u.io.overlapped)); - - /* Using overlapped IO, but wait for completion before returning. - This write is blocking because ipc_frame is on stack. */ - ipc_header_req->u.io.overlapped.hEvent = CreateEvent(NULL, 1, 0, NULL); - if (!ipc_header_req->u.io.overlapped.hEvent) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - - result = WriteFile(handle->handle, - &ipc_frame, - ipc_frame.header.flags & UV_IPC_TCP_SERVER ? - sizeof(ipc_frame) : sizeof(ipc_frame.header), - NULL, - &ipc_header_req->u.io.overlapped); - if (!result && GetLastError() != ERROR_IO_PENDING) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); + req->write_buffer = uv_null_buf_; + + if (nbufs == 0) { + /* Write empty buffer. */ + write_buf = uv_null_buf_; + } else if (nbufs == 1 && !copy_always) { + /* Write directly from bufs[0]. */ + write_buf = bufs[0]; + } else { + /* Coalesce all `bufs` into one big buffer. This also creates a new + * write-request structure that replaces the old one. */ + err = uv__build_coalesced_write_req(req, bufs, nbufs, &req, &write_buf); + if (err != 0) return err; - } - - if (!result) { - /* Request not completed immediately. Wait for it.*/ - if (WaitForSingleObject(ipc_header_req->u.io.overlapped.hEvent, INFINITE) != - WAIT_OBJECT_0) { - err = GetLastError(); - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - return err; - } - } - ipc_header_req->u.io.queued_bytes = 0; - CloseHandle(ipc_header_req->u.io.overlapped.hEvent); - ipc_header_req->u.io.overlapped.hEvent = NULL; - - REGISTER_HANDLE_REQ(loop, handle, ipc_header_req); - handle->reqs_pending++; - handle->stream.conn.write_reqs_pending++; - - /* If we don't have any raw data to write - we're done. */ - if (!(ipc_frame.header.flags & UV_IPC_RAW_DATA)) { - return 0; - } } if ((handle->flags & (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) == (UV_HANDLE_BLOCKING_WRITES | UV_HANDLE_NON_OVERLAPPED_PIPE)) { DWORD bytes; - result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, - &bytes, - NULL); + result = + WriteFile(handle->handle, write_buf.base, write_buf.len, &bytes, NULL); if (!result) { err = GetLastError(); @@ -1382,14 +1346,14 @@ static int uv_pipe_write_impl(uv_loop_t* loop, POST_COMPLETION_FOR_REQ(loop, req); return 0; } else if (handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { - req->write_buffer = bufs[0]; + req->write_buffer = write_buf; uv_insert_non_overlapped_write_req(handle, req); if (handle->stream.conn.write_reqs_pending == 0) { uv_queue_non_overlapped_write(handle); } /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; } else if (handle->flags & UV_HANDLE_BLOCKING_WRITES) { /* Using overlapped IO, but wait for completion before returning */ @@ -1399,8 +1363,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, + write_buf.base, + write_buf.len, NULL, &req->u.io.overlapped); @@ -1415,13 +1379,13 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->u.io.queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; if (WaitForSingleObject(req->u.io.overlapped.hEvent, INFINITE) != WAIT_OBJECT_0) { err = GetLastError(); CloseHandle(req->u.io.overlapped.hEvent); - return uv_translate_sys_error(err); + return err; } } CloseHandle(req->u.io.overlapped.hEvent); @@ -1432,8 +1396,8 @@ static int uv_pipe_write_impl(uv_loop_t* loop, return 0; } else { result = WriteFile(handle->handle, - bufs[0].base, - bufs[0].len, + write_buf.base, + write_buf.len, NULL, &req->u.io.overlapped); @@ -1446,7 +1410,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop, req->u.io.queued_bytes = 0; } else { /* Request queued by the kernel. */ - req->u.io.queued_bytes = bufs[0].len; + req->u.io.queued_bytes = write_buf.len; handle->write_queue_size += req->u.io.queued_bytes; } @@ -1471,35 +1435,140 @@ static int uv_pipe_write_impl(uv_loop_t* loop, } -int uv_pipe_write(uv_loop_t* loop, - uv_write_t* req, - uv_pipe_t* handle, - const uv_buf_t bufs[], - unsigned int nbufs, - uv_write_cb cb) { - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, NULL, cb); +static DWORD uv__pipe_get_ipc_remote_pid(uv_pipe_t* handle) { + DWORD* pid = &handle->pipe.conn.ipc_remote_pid; + + /* If the both ends of the IPC pipe are owned by the same process, + * the remote end pid may not yet be set. If so, do it here. + * TODO: this is weird; it'd probably better to use a handshake. */ + if (*pid == 0) + *pid = GetCurrentProcessId(); + + return *pid; +} + + +int uv__pipe_write_ipc(uv_loop_t* loop, + uv_write_t* req, + uv_pipe_t* handle, + const uv_buf_t data_bufs[], + size_t data_buf_count, + uv_stream_t* send_handle, + uv_write_cb cb) { + uv_buf_t stack_bufs[6]; + uv_buf_t* bufs; + size_t buf_count, buf_index; + uv__ipc_frame_header_t xfer_frame_header; + uv__ipc_socket_xfer_info_t xfer_info; + uv__ipc_frame_header_t data_frame_header; + size_t data_length; + size_t i; + int err; + + /* Compute the combined size of data buffers. */ + data_length = 0; + for (i = 0; i < data_buf_count; i++) + data_length += data_bufs[i].len; + if (data_length > UINT32_MAX) + return WSAENOBUFS; /* Maps to UV_ENOBUFS. */ + + /* Prepare xfer frame payload. */ + if (send_handle) { + uv_tcp_t* send_tcp_handle = (uv_tcp_t*) send_handle; + + /* Verify that `send_handle` it is indeed a tcp handle. */ + if (send_tcp_handle->type != UV_TCP) + return ERROR_NOT_SUPPORTED; + + /* Export the tcp handle. */ + err = uv__tcp_xfer_export( + send_tcp_handle, uv__pipe_get_ipc_remote_pid(handle), &xfer_info); + if (err != 0) + return err; + } + + /* Compute the number of uv_buf_t's required. */ + buf_count = 0; + if (send_handle != NULL) { + buf_count += 2; /* One for the frame header, one for the payload. */ + } + if (data_buf_count > 0) { + buf_count += 1 + data_buf_count; /* One extra for the frame header. */ + } + + /* Use the on-stack buffer array if it is big enough; otherwise allocate + * space for it on the heap. */ + if (buf_count < ARRAY_SIZE(stack_bufs)) { + /* Use on-stack buffer array. */ + bufs = stack_bufs; + } else { + /* Use heap-allocated buffer array. */ + bufs = uv__calloc(buf_count, sizeof(uv_buf_t)); + if (bufs == NULL) + return ERROR_NOT_ENOUGH_MEMORY; /* Maps to UV_ENOMEM. */ + } + buf_index = 0; + + if (send_handle != NULL) { + /* Add xfer frame header. */ + xfer_frame_header.type = UV__IPC_XFER_FRAME; + xfer_frame_header.payload_length = sizeof xfer_info; + bufs[buf_index++] = + uv_buf_init((char*) &xfer_frame_header, sizeof xfer_frame_header); + + /* Add xfer frame payload. */ + bufs[buf_index++] = uv_buf_init((char*) &xfer_info, sizeof xfer_info); + } + + if (data_length > 0) { + /* Add data frame header. */ + data_frame_header.type = UV__IPC_DATA_FRAME; + data_frame_header.payload_length = (uint32_t) data_length; + bufs[buf_index++] = + uv_buf_init((char*) &data_frame_header, sizeof data_frame_header); + + /* Add data buffers. */ + for (i = 0; i < data_buf_count; i++) + bufs[buf_index++] = data_bufs[i]; + } + + /* Write buffers. We set the `always_copy` flag, so it is not a problem that + * some of the written data lives on the stack. */ + err = uv__pipe_write_data( + loop, req, handle, bufs, buf_count, send_handle, cb, 1); + + /* If we had to heap-allocate the bufs array, free it now. */ + if (bufs != stack_bufs) { + uv__free(bufs); + } + + return err; } -int uv_pipe_write2(uv_loop_t* loop, +int uv__pipe_write(uv_loop_t* loop, uv_write_t* req, uv_pipe_t* handle, const uv_buf_t bufs[], - unsigned int nbufs, + size_t nbufs, uv_stream_t* send_handle, uv_write_cb cb) { - if (!handle->ipc) { - return WSAEINVAL; + if (handle->ipc) { + /* IPC pipe write: use framing protocol. */ + return uv__pipe_write_ipc(loop, req, handle, bufs, nbufs, send_handle, cb); + } else { + /* Non-IPC pipe write: put data on the wire directly. */ + assert(send_handle == NULL); + return uv__pipe_write_data( + loop, req, handle, bufs, nbufs, NULL, cb, 0); } - - return uv_pipe_write_impl(loop, req, handle, bufs, nbufs, send_handle, cb); } static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ + /* If there is an eof timer running, we don't need it any more, so discard + * it. */ eof_timer_destroy(handle); handle->flags &= ~UV_HANDLE_READABLE; @@ -1511,8 +1580,8 @@ static void uv_pipe_read_eof(uv_loop_t* loop, uv_pipe_t* handle, static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { - /* If there is an eof timer running, we don't need it any more, */ - /* so discard it. */ + /* If there is an eof timer running, we don't need it any more, so discard + * it. */ eof_timer_destroy(handle); uv_read_stop((uv_stream_t*) handle); @@ -1523,10 +1592,7 @@ static void uv_pipe_read_error(uv_loop_t* loop, uv_pipe_t* handle, int error, static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, int error, uv_buf_t buf) { - if (error == ERROR_OPERATION_ABORTED) { - /* do nothing (equivalent to EINTR) */ - } - else if (error == ERROR_BROKEN_PIPE) { + if (error == ERROR_BROKEN_PIPE) { uv_pipe_read_eof(loop, handle, buf); } else { uv_pipe_read_error(loop, handle, error, buf); @@ -1534,152 +1600,198 @@ static void uv_pipe_read_error_or_eof(uv_loop_t* loop, uv_pipe_t* handle, } -void uv__pipe_insert_pending_socket(uv_pipe_t* handle, - uv__ipc_socket_info_ex* info, - int tcp_connection) { - uv__ipc_queue_item_t* item; +static void uv__pipe_queue_ipc_xfer_info( + uv_pipe_t* handle, uv__ipc_socket_xfer_info_t* xfer_info) { + uv__ipc_xfer_queue_item_t* item; - item = (uv__ipc_queue_item_t*) uv__malloc(sizeof(*item)); + item = (uv__ipc_xfer_queue_item_t*) uv__malloc(sizeof(*item)); if (item == NULL) uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc"); - memcpy(&item->socket_info_ex, info, sizeof(item->socket_info_ex)); - item->tcp_connection = tcp_connection; - QUEUE_INSERT_TAIL(&handle->pipe.conn.pending_ipc_info.queue, &item->member); - handle->pipe.conn.pending_ipc_info.queue_len++; + memcpy(&item->xfer_info, xfer_info, sizeof(item->xfer_info)); + QUEUE_INSERT_TAIL(&handle->pipe.conn.ipc_xfer_queue, &item->member); + handle->pipe.conn.ipc_xfer_queue_length++; } -void uv_process_pipe_read_req(uv_loop_t* loop, uv_pipe_t* handle, - uv_req_t* req) { - DWORD bytes, avail; +/* Read an exact number of bytes from a pipe. If an error or end-of-file is + * encountered before the requested number of bytes are read, an error is + * returned. */ +static int uv__pipe_read_exactly(HANDLE h, void* buffer, DWORD count) { + DWORD bytes_read, bytes_read_now; + + bytes_read = 0; + while (bytes_read < count) { + if (!ReadFile(h, + (char*) buffer + bytes_read, + count - bytes_read, + &bytes_read_now, + NULL)) { + return GetLastError(); + } + + bytes_read += bytes_read_now; + } + + assert(bytes_read == count); + return 0; +} + + +static DWORD uv__pipe_read_data(uv_loop_t* loop, + uv_pipe_t* handle, + DWORD suggested_bytes, + DWORD max_bytes) { + DWORD bytes_read; uv_buf_t buf; - uv_ipc_frame_uv_stream ipc_frame; + /* Ask the user for a buffer to read data into. */ + buf = uv_buf_init(NULL, 0); + handle->alloc_cb((uv_handle_t*) handle, suggested_bytes, &buf); + if (buf.base == NULL || buf.len == 0) { + handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); + return 0; /* Break out of read loop. */ + } + + /* Ensure we read at most the smaller of: + * (a) the length of the user-allocated buffer. + * (b) the maximum data length as specified by the `max_bytes` argument. + */ + if (max_bytes > buf.len) + max_bytes = buf.len; + + /* Read into the user buffer. */ + if (!ReadFile(handle->handle, buf.base, max_bytes, &bytes_read, NULL)) { + uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); + return 0; /* Break out of read loop. */ + } + + /* Call the read callback. */ + handle->read_cb((uv_stream_t*) handle, bytes_read, &buf); + + return bytes_read; +} + + +static DWORD uv__pipe_read_ipc(uv_loop_t* loop, uv_pipe_t* handle) { + uint32_t* data_remaining = &handle->pipe.conn.ipc_data_frame.payload_remaining; + int err; + + if (*data_remaining > 0) { + /* Read data frame payload. */ + DWORD bytes_read = + uv__pipe_read_data(loop, handle, *data_remaining, *data_remaining); + *data_remaining -= bytes_read; + return bytes_read; + + } else { + /* Start of a new IPC frame. */ + uv__ipc_frame_header_t frame_header; + uv__ipc_socket_xfer_info_t xfer_info; + + /* Read the IPC frame header. */ + err = uv__pipe_read_exactly( + handle->handle, &frame_header, sizeof frame_header); + if (err) + goto error; + + if (frame_header.type == UV__IPC_DATA_FRAME) { + /* Data frame: capture payload length. Actual data will be read in + * subsequent call to uv__pipe_read_ipc(). */ + *data_remaining = frame_header.payload_length; + + /* Return number of bytes read. */ + return sizeof frame_header; + + } else if (frame_header.type == UV__IPC_XFER_FRAME) { + /* Xfer frame: read the payload. */ + assert(frame_header.payload_length == sizeof xfer_info); + err = + uv__pipe_read_exactly(handle->handle, &xfer_info, sizeof xfer_info); + if (err) + goto error; + + /* Store the pending socket info. */ + uv__pipe_queue_ipc_xfer_info(handle, &xfer_info); + + /* Return number of bytes read. */ + return sizeof frame_header + sizeof xfer_info; + } + + /* Invalid frame. */ + err = WSAECONNABORTED; /* Maps to UV_ECONNABORTED. */ + } + +error: + uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); + return 0; /* Break out of read loop. */ +} + + +void uv_process_pipe_read_req(uv_loop_t* loop, + uv_pipe_t* handle, + uv_req_t* req) { assert(handle->type == UV_NAMED_PIPE); - handle->flags &= ~UV_HANDLE_READ_PENDING; + handle->flags &= ~(UV_HANDLE_READ_PENDING | UV_HANDLE_CANCELLATION_PENDING); + DECREASE_PENDING_REQ_COUNT(handle); eof_timer_stop(handle); - if (!REQ_SUCCESS(req)) { - /* An error occurred doing the 0-read. */ - if (handle->flags & UV_HANDLE_READING) { - uv_pipe_read_error_or_eof(loop, - handle, - GET_REQ_ERROR(req), - uv_null_buf_); - } - } else { - /* Do non-blocking reads until the buffer is empty */ - while (handle->flags & UV_HANDLE_READING) { - if (!PeekNamedPipe(handle->handle, - NULL, - 0, - NULL, - &avail, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); - break; - } + /* At this point, we're done with bookkeeping. If the user has stopped + * reading the pipe in the meantime, there is nothing left to do, since there + * is no callback that we can call. */ + if (!(handle->flags & UV_HANDLE_READING)) + return; - if (avail == 0) { - /* There is nothing to read after all. */ - break; - } + if (!REQ_SUCCESS(req)) { + /* An error occurred doing the zero-read. */ + DWORD err = GET_REQ_ERROR(req); - if (handle->ipc) { - /* Use the IPC framing protocol to read the incoming data. */ - if (handle->pipe.conn.remaining_ipc_rawdata_bytes == 0) { - /* We're reading a new frame. First, read the header. */ - assert(avail >= sizeof(ipc_frame.header)); - - if (!ReadFile(handle->handle, - &ipc_frame.header, - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame.header)); - assert(ipc_frame.header.flags <= (UV_IPC_TCP_SERVER | UV_IPC_RAW_DATA | - UV_IPC_TCP_CONNECTION)); - - if (ipc_frame.header.flags & UV_IPC_TCP_SERVER) { - assert(avail - sizeof(ipc_frame.header) >= - sizeof(ipc_frame.socket_info_ex)); - - /* Read the TCP socket info. */ - if (!ReadFile(handle->handle, - &ipc_frame.socket_info_ex, - sizeof(ipc_frame) - sizeof(ipc_frame.header), - &bytes, - NULL)) { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), - uv_null_buf_); - break; - } - - assert(bytes == sizeof(ipc_frame) - sizeof(ipc_frame.header)); - - /* Store the pending socket info. */ - uv__pipe_insert_pending_socket( - handle, - &ipc_frame.socket_info_ex, - ipc_frame.header.flags & UV_IPC_TCP_CONNECTION); - } - - if (ipc_frame.header.flags & UV_IPC_RAW_DATA) { - handle->pipe.conn.remaining_ipc_rawdata_bytes = - ipc_frame.header.raw_data_length; - continue; - } - } else { - avail = min(avail, (DWORD)handle->pipe.conn.remaining_ipc_rawdata_bytes); - } - } + /* If the read was cancelled by uv__pipe_interrupt_read(), the request may + * indicate an ERROR_OPERATION_ABORTED error. This error isn't relevant to + * the user; we'll start a new zero-read at the end of this function. */ + if (err != ERROR_OPERATION_ABORTED) + uv_pipe_read_error_or_eof(loop, handle, err, uv_null_buf_); - buf = uv_buf_init(NULL, 0); - handle->alloc_cb((uv_handle_t*) handle, avail, &buf); - if (buf.base == NULL || buf.len == 0) { - handle->read_cb((uv_stream_t*) handle, UV_ENOBUFS, &buf); + } else { + /* The zero-read completed without error, indicating there is data + * available in the kernel buffer. */ + DWORD avail; + + /* Get the number of bytes available. */ + avail = 0; + if (!PeekNamedPipe(handle->handle, NULL, 0, NULL, &avail, NULL)) + uv_pipe_read_error_or_eof(loop, handle, GetLastError(), uv_null_buf_); + + /* Read until we've either read all the bytes available, or the 'reading' + * flag is cleared. */ + while (avail > 0 && handle->flags & UV_HANDLE_READING) { + /* Depending on the type of pipe, read either IPC frames or raw data. */ + DWORD bytes_read = + handle->ipc ? uv__pipe_read_ipc(loop, handle) + : uv__pipe_read_data(loop, handle, avail, (DWORD) -1); + + /* If no bytes were read, treat this as an indication that an error + * occurred, and break out of the read loop. */ + if (bytes_read == 0) break; - } - assert(buf.base != NULL); - - if (ReadFile(handle->handle, - buf.base, - min(buf.len, avail), - &bytes, - NULL)) { - /* Successful read */ - if (handle->ipc) { - assert(handle->pipe.conn.remaining_ipc_rawdata_bytes >= bytes); - handle->pipe.conn.remaining_ipc_rawdata_bytes = - handle->pipe.conn.remaining_ipc_rawdata_bytes - bytes; - } - handle->read_cb((uv_stream_t*)handle, bytes, &buf); - /* Read again only if bytes == buf.len */ - if (bytes <= buf.len) { - break; - } - } else { - uv_pipe_read_error_or_eof(loop, handle, GetLastError(), buf); + /* It is possible that more bytes were read than we thought were + * available. To prevent `avail` from underflowing, break out of the loop + * if this is the case. */ + if (bytes_read > avail) break; - } - } - /* Post another 0-read if still reading and not closing. */ - if ((handle->flags & UV_HANDLE_READING) && - !(handle->flags & UV_HANDLE_READ_PENDING)) { - uv_pipe_queue_read(loop, handle); + /* Recompute the number of bytes available. */ + avail -= bytes_read; } } - DECREASE_PENDING_REQ_COUNT(handle); + /* Start another zero-read request if necessary. */ + if ((handle->flags & UV_HANDLE_READING) && + !(handle->flags & UV_HANDLE_READ_PENDING)) { + uv_pipe_queue_read(loop, handle); + } } @@ -1705,17 +1817,19 @@ void uv_process_pipe_write_req(uv_loop_t* loop, uv_pipe_t* handle, } } - if (req->ipc_header) { - if (req == &handle->pipe.conn.ipc_header_write_req) { - req->type = UV_UNKNOWN_REQ; - } else { - uv__free(req); - } - } else { - if (req->cb) { - err = GET_REQ_ERROR(req); - req->cb(req, uv_translate_sys_error(err)); - } + err = GET_REQ_ERROR(req); + + /* If this was a coalesced write, extract pointer to the user_provided + * uv_write_t structure so we can pass the expected pointer to the callback, + * then free the heap-allocated write req. */ + if (req->coalesced) { + uv__coalesced_write_t* coalesced_write = + container_of(req, uv__coalesced_write_t, req); + req = coalesced_write->user_req; + uv__free(coalesced_write); + } + if (req->cb) { + req->cb(req, uv_translate_sys_error(err)); } handle->stream.conn.write_reqs_pending--; @@ -1741,7 +1855,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, assert(handle->type == UV_NAMED_PIPE); - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* The req->pipeHandle should be freed already in uv_pipe_cleanup(). */ assert(req->pipeHandle == INVALID_HANDLE_VALUE); DECREASE_PENDING_REQ_COUNT(handle); @@ -1761,7 +1875,7 @@ void uv_process_pipe_accept_req(uv_loop_t* loop, uv_pipe_t* handle, CloseHandle(req->pipeHandle); req->pipeHandle = INVALID_HANDLE_VALUE; } - if (!(handle->flags & UV__HANDLE_CLOSING)) { + if (!(handle->flags & UV_HANDLE_CLOSING)) { uv_pipe_queue_accept(loop, handle, req, FALSE); } } @@ -1799,19 +1913,19 @@ void uv_process_pipe_shutdown_req(uv_loop_t* loop, uv_pipe_t* handle, UNREGISTER_HANDLE_REQ(loop, handle, req); if (handle->flags & UV_HANDLE_READABLE) { - /* Initialize and optionally start the eof timer. Only do this if the */ - /* pipe is readable and we haven't seen EOF come in ourselves. */ + /* Initialize and optionally start the eof timer. Only do this if the pipe + * is readable and we haven't seen EOF come in ourselves. */ eof_timer_init(handle); - /* If reading start the timer right now. */ - /* Otherwise uv_pipe_queue_read will start it. */ + /* If reading start the timer right now. Otherwise uv_pipe_queue_read will + * start it. */ if (handle->flags & UV_HANDLE_READ_PENDING) { eof_timer_start(handle); } } else { - /* This pipe is not readable. We can just close it to let the other end */ - /* know that we're done writing. */ + /* This pipe is not readable. We can just close it to let the other end + * know that we're done writing. */ close_pipe(handle); } @@ -1862,17 +1976,16 @@ static void eof_timer_cb(uv_timer_t* timer) { assert(pipe->type == UV_NAMED_PIPE); - /* This should always be true, since we start the timer only */ - /* in uv_pipe_queue_read after successfully calling ReadFile, */ - /* or in uv_process_pipe_shutdown_req if a read is pending, */ - /* and we always immediately stop the timer in */ - /* uv_process_pipe_read_req. */ + /* This should always be true, since we start the timer only in + * uv_pipe_queue_read after successfully calling ReadFile, or in + * uv_process_pipe_shutdown_req if a read is pending, and we always + * immediately stop the timer in uv_process_pipe_read_req. */ assert(pipe->flags & UV_HANDLE_READ_PENDING); - /* If there are many packets coming off the iocp then the timer callback */ - /* may be called before the read request is coming off the queue. */ - /* Therefore we check here if the read request has completed but will */ - /* be processed later. */ + /* If there are many packets coming off the iocp then the timer callback may + * be called before the read request is coming off the queue. Therefore we + * check here if the read request has completed but will be processed later. + */ if ((pipe->flags & UV_HANDLE_READ_PENDING) && HasOverlappedIoCompleted(&pipe->read_req.u.io.overlapped)) { return; @@ -1881,12 +1994,12 @@ static void eof_timer_cb(uv_timer_t* timer) { /* Force both ends off the pipe. */ close_pipe(pipe); - /* Stop reading, so the pending read that is going to fail will */ - /* not be reported to the user. */ + /* 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); - /* Report the eof and update flags. This will get reported even if the */ - /* user stopped reading in the meantime. TODO: is that okay? */ + /* Report the eof and update flags. This will get reported even if the user + * stopped reading in the meantime. TODO: is that okay? */ uv_pipe_read_eof(loop, pipe, uv_null_buf_); } @@ -1973,8 +2086,8 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) { if (pipe->ipc) { assert(!(pipe->flags & UV_HANDLE_NON_OVERLAPPED_PIPE)); - pipe->pipe.conn.ipc_pid = uv_os_getppid(); - assert(pipe->pipe.conn.ipc_pid != -1); + pipe->pipe.conn.ipc_remote_pid = uv_os_getppid(); + assert(pipe->pipe.conn.ipc_remote_pid != -1); } return 0; } @@ -1999,7 +2112,15 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) return UV_EINVAL; } - uv__pipe_pause_read((uv_pipe_t*)handle); /* cast away const warning */ + /* NtQueryInformationFile will block if another thread is performing a + * blocking operation on the queried handle. If the pipe handle is + * synchronous, there may be a worker thread currently calling ReadFile() on + * the pipe handle, which could cause a deadlock. To avoid this, interrupt + * the read. */ + if (handle->flags & UV_HANDLE_CONNECTION && + handle->flags & UV_HANDLE_NON_OVERLAPPED_PIPE) { + uv__pipe_interrupt_read((uv_pipe_t*) handle); /* cast away const warning */ + } nt_status = pNtQueryInformationFile(handle->handle, &io_status, @@ -2090,7 +2211,6 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) uv__free(name_info); cleanup: - uv__pipe_unpause_read((uv_pipe_t*)handle); /* cast away const warning */ return err; } @@ -2098,7 +2218,7 @@ static int uv__pipe_getname(const uv_pipe_t* handle, char* buffer, size_t* size) int uv_pipe_pending_count(uv_pipe_t* handle) { if (!handle->ipc) return 0; - return handle->pipe.conn.pending_ipc_info.queue_len; + return handle->pipe.conn.ipc_xfer_queue_length; } @@ -2131,7 +2251,7 @@ int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) { uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) { if (!handle->ipc) return UV_UNKNOWN_HANDLE; - if (handle->pipe.conn.pending_ipc_info.queue_len == 0) + if (handle->pipe.conn.ipc_xfer_queue_length == 0) return UV_UNKNOWN_HANDLE; else return UV_TCP; diff --git a/deps/libuv/src/win/poll.c b/deps/libuv/src/win/poll.c index a648ba711..77eb071c8 100644 --- a/deps/libuv/src/win/poll.c +++ b/deps/libuv/src/win/poll.c @@ -91,16 +91,16 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { handle->mask_events_1 = handle->events; handle->mask_events_2 = 0; } else { - /* Just wait until there's an unsubmitted req. */ - /* This will happen almost immediately as one of the 2 outstanding */ - /* requests is about to return. When this happens, */ - /* uv__fast_poll_process_poll_req will be called, and the pending */ - /* events, if needed, will be processed in a subsequent request. */ + /* Just wait until there's an unsubmitted req. This will happen almost + * immediately as one of the 2 outstanding requests is about to return. + * When this happens, uv__fast_poll_process_poll_req will be called, and + * the pending events, if needed, will be processed in a subsequent + * request. */ return; } - /* Setting Exclusive to TRUE makes the other poll request return if there */ - /* is any. */ + /* Setting Exclusive to TRUE makes the other poll request return if there is + * any. */ afd_poll_info->Exclusive = TRUE; afd_poll_info->NumberOfHandles = 1; afd_poll_info->Timeout.QuadPart = INT64_MAX; @@ -218,7 +218,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, if ((handle->events & ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { uv__fast_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && + } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { uv_want_endgame(loop, (uv_handle_t*) handle); @@ -228,7 +228,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, static int uv__fast_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); assert((events & ~(UV_READABLE | UV_WRITABLE | UV_DISCONNECT)) == 0); handle->events = events; @@ -257,8 +257,8 @@ static int uv__fast_poll_close(uv_loop_t* loop, uv_poll_t* handle) { uv_want_endgame(loop, (uv_handle_t*) handle); return 0; } else { - /* Cancel outstanding poll requests by executing another, unique poll */ - /* request that forces the outstanding ones to return. */ + /* Cancel outstanding poll requests by executing another, unique poll + * request that forces the outstanding ones to return. */ return uv__fast_poll_cancel_poll_req(loop, handle); } } @@ -316,9 +316,8 @@ static SOCKET uv__fast_poll_get_peer_socket(uv_loop_t* loop, return INVALID_SOCKET; } - /* If we didn't (try) to create a peer socket yet, try to make one. Don't */ - /* try again if the peer socket creation failed earlier for the same */ - /* protocol. */ + /* If we didn't (try) to create a peer socket yet, try to make one. Don't try + * again if the peer socket creation failed earlier for the same protocol. */ peer_socket = loop->poll_peer_sockets[index]; if (peer_socket == 0) { peer_socket = uv__fast_poll_create_peer_socket(loop->iocp, protocol_info); @@ -357,8 +356,8 @@ static DWORD WINAPI uv__slow_poll_thread_proc(void* arg) { efds.fd_count = 0; } - /* Make the select() time out after 3 minutes. If select() hangs because */ - /* the user closed the socket, we will at least not hang indefinitely. */ + /* Make the select() time out after 3 minutes. If select() hangs because the + * user closed the socket, we will at least not hang indefinitely. */ timeout.tv_sec = 3 * 60; timeout.tv_usec = 0; @@ -462,7 +461,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, if ((handle->events & ~(handle->submitted_events_1 | handle->submitted_events_2)) != 0) { uv__slow_poll_submit_poll_req(loop, handle); - } else if ((handle->flags & UV__HANDLE_CLOSING) && + } else if ((handle->flags & UV_HANDLE_CLOSING) && handle->submitted_events_1 == 0 && handle->submitted_events_2 == 0) { uv_want_endgame(loop, (uv_handle_t*) handle); @@ -472,7 +471,7 @@ static void uv__slow_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, static int uv__slow_poll_set(uv_loop_t* loop, uv_poll_t* handle, int events) { assert(handle->type == UV_POLL); - assert(!(handle->flags & UV__HANDLE_CLOSING)); + assert(!(handle->flags & UV_HANDLE_CLOSING)); assert((events & ~(UV_READABLE | UV_WRITABLE)) == 0); handle->events = events; @@ -522,10 +521,10 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) return uv_translate_sys_error(WSAGetLastError()); - /* Try to obtain a base handle for the socket. This increases this chances */ - /* that we find an AFD handle and are able to use the fast poll mechanism. */ - /* This will always fail on windows XP/2k3, since they don't support the */ - /* SIO_BASE_HANDLE ioctl. */ +/* Try to obtain a base handle for the socket. This increases this chances that + * we find an AFD handle and are able to use the fast poll mechanism. This will + * always fail on windows XP/2k3, since they don't support the. SIO_BASE_HANDLE + * ioctl. */ #ifndef NDEBUG base_socket = INVALID_SOCKET; #endif @@ -557,9 +556,9 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, return uv_translate_sys_error(WSAGetLastError()); } - /* Get the peer socket that is needed to enable fast poll. If the returned */ - /* value is NULL, the protocol is not implemented by MSAFD and we'll have */ - /* to use slow mode. */ + /* Get the peer socket that is needed to enable fast poll. If the returned + * value is NULL, the protocol is not implemented by MSAFD and we'll have to + * use slow mode. */ peer_socket = uv__fast_poll_get_peer_socket(loop, &protocol_info); if (peer_socket != INVALID_SOCKET) { @@ -634,7 +633,7 @@ int uv_poll_close(uv_loop_t* loop, uv_poll_t* handle) { void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); assert(handle->submitted_events_1 == 0); diff --git a/deps/libuv/src/win/process-stdio.c b/deps/libuv/src/win/process-stdio.c index 032e30935..355d61880 100644 --- a/deps/libuv/src/win/process-stdio.c +++ b/deps/libuv/src/win/process-stdio.c @@ -103,12 +103,12 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, DWORD client_access = 0; HANDLE child_pipe = INVALID_HANDLE_VALUE; int err; + int overlap; if (flags & UV_READABLE_PIPE) { - /* The server needs inbound access too, otherwise CreateNamedPipe() */ - /* won't give us the FILE_READ_ATTRIBUTES permission. We need that to */ - /* probe the state of the write buffer when we're trying to shutdown */ - /* the pipe. */ + /* The server needs inbound access too, otherwise CreateNamedPipe() won't + * give us the FILE_READ_ATTRIBUTES permission. We need that to probe the + * state of the write buffer when we're trying to shutdown the pipe. */ server_access |= PIPE_ACCESS_OUTBOUND | PIPE_ACCESS_INBOUND; client_access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES; } @@ -131,12 +131,13 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, sa.lpSecurityDescriptor = NULL; sa.bInheritHandle = TRUE; + overlap = server_pipe->ipc || (flags & UV_OVERLAPPED_PIPE); child_pipe = CreateFileA(pipe_name, client_access, 0, &sa, OPEN_EXISTING, - server_pipe->ipc ? FILE_FLAG_OVERLAPPED : 0, + overlap ? FILE_FLAG_OVERLAPPED : 0, NULL); if (child_pipe == INVALID_HANDLE_VALUE) { err = GetLastError(); @@ -159,8 +160,8 @@ static int uv__create_stdio_pipe_pair(uv_loop_t* loop, } #endif - /* Do a blocking ConnectNamedPipe. This should not block because we have */ - /* both ends of the pipe created. */ + /* Do a blocking ConnectNamedPipe. This should not block because we have both + * ends of the pipe created. */ if (!ConnectNamedPipe(server_pipe->handle, NULL)) { if (GetLastError() != ERROR_PIPE_CONNECTED) { err = GetLastError(); @@ -194,11 +195,11 @@ static int uv__duplicate_handle(uv_loop_t* loop, HANDLE handle, HANDLE* dup) { HANDLE current_process; - /* _get_osfhandle will sometimes return -2 in case of an error. This seems */ - /* to happen when fd <= 2 and the process' corresponding stdio handle is */ - /* set to NULL. Unfortunately DuplicateHandle will happily duplicate */ - /* (HANDLE) -2, so this situation goes unnoticed until someone tries to */ - /* use the duplicate. Therefore we filter out known-invalid handles here. */ + /* _get_osfhandle will sometimes return -2 in case of an error. This seems to + * happen when fd <= 2 and the process' corresponding stdio handle is set to + * NULL. Unfortunately DuplicateHandle will happily duplicate (HANDLE) -2, so + * this situation goes unnoticed until someone tries to use the duplicate. + * Therefore we filter out known-invalid handles here. */ if (handle == INVALID_HANDLE_VALUE || handle == NULL || handle == (HANDLE) -2) { @@ -284,8 +285,8 @@ int uv__stdio_create(uv_loop_t* loop, return ERROR_OUTOFMEMORY; } - /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can */ - /* clean up on failure. */ + /* Prepopulate the buffer with INVALID_HANDLE_VALUE handles so we can clean + * up on failure. */ CHILD_STDIO_COUNT(buffer) = count; for (i = 0; i < count; i++) { CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; @@ -303,12 +304,12 @@ int uv__stdio_create(uv_loop_t* loop, switch (fdopt.flags & (UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM)) { case UV_IGNORE: - /* Starting a process with no stdin/stout/stderr can confuse it. */ - /* So no matter what the user specified, we make sure the first */ - /* three FDs are always open in their typical modes, e.g. stdin */ - /* be readable and stdout/err should be writable. For FDs > 2, don't */ - /* do anything - all handles in the stdio buffer are initialized with */ - /* INVALID_HANDLE_VALUE, which should be okay. */ + /* Starting a process with no stdin/stout/stderr can confuse it. So no + * matter what the user specified, we make sure the first three FDs are + * always open in their typical modes, e. g. stdin be readable and + * stdout/err should be writable. For FDs > 2, don't do anything - all + * handles in the stdio buffer are initialized with. + * INVALID_HANDLE_VALUE, which should be okay. */ if (i <= 2) { DWORD access = (i == 0) ? FILE_GENERIC_READ : FILE_GENERIC_WRITE | FILE_READ_ATTRIBUTES; @@ -323,14 +324,14 @@ int uv__stdio_create(uv_loop_t* loop, break; case UV_CREATE_PIPE: { - /* Create a pair of two connected pipe ends; one end is turned into */ - /* an uv_pipe_t for use by the parent. The other one is given to */ - /* the child. */ + /* Create a pair of two connected pipe ends; one end is turned into an + * uv_pipe_t for use by the parent. The other one is given to the + * child. */ uv_pipe_t* parent_pipe = (uv_pipe_t*) fdopt.data.stream; HANDLE child_pipe = INVALID_HANDLE_VALUE; - /* Create a new, connected pipe pair. stdio[i].stream should point */ - /* to an uninitialized, but not connected pipe handle. */ + /* Create a new, connected pipe pair. stdio[i]. stream should point to + * an uninitialized, but not connected pipe handle. */ assert(fdopt.data.stream->type == UV_NAMED_PIPE); assert(!(fdopt.data.stream->flags & UV_HANDLE_CONNECTION)); assert(!(fdopt.data.stream->flags & UV_HANDLE_PIPESERVER)); @@ -354,8 +355,8 @@ int uv__stdio_create(uv_loop_t* loop, /* Make an inheritable duplicate of the handle. */ err = uv__duplicate_fd(loop, fdopt.data.fd, &child_handle); if (err) { - /* If fdopt.data.fd is not valid and fd fd <= 2, then ignore the */ - /* error. */ + /* If fdopt. data. fd is not valid and fd <= 2, then ignore the + * error. */ if (fdopt.data.fd <= 2 && err == ERROR_INVALID_HANDLE) { CHILD_STDIO_CRT_FLAGS(buffer, i) = 0; CHILD_STDIO_HANDLE(buffer, i) = INVALID_HANDLE_VALUE; @@ -418,8 +419,8 @@ int uv__stdio_create(uv_loop_t* loop, if (stream_handle == NULL || stream_handle == INVALID_HANDLE_VALUE) { - /* The handle is already closed, or not yet created, or the */ - /* stream type is not supported. */ + /* The handle is already closed, or not yet created, or the stream + * type is not supported. */ err = ERROR_NOT_SUPPORTED; goto error; } diff --git a/deps/libuv/src/win/process.c b/deps/libuv/src/win/process.c index 752352221..b47f203e9 100644 --- a/deps/libuv/src/win/process.c +++ b/deps/libuv/src/win/process.c @@ -360,8 +360,8 @@ static WCHAR* search_path(const WCHAR *file, return NULL; } - /* Find the start of the filename so we can split the directory from the */ - /* name. */ + /* Find the start of the filename so we can split the directory from the + * name. */ for (file_name_start = (WCHAR*)file + file_len; file_name_start > file && file_name_start[-1] != L'\\' @@ -556,8 +556,8 @@ int make_program_args(char** args, int verbatim_arguments, WCHAR** dst_ptr) { arg_count++; } - /* Adjust for potential quotes. Also assume the worst-case scenario */ - /* that every character needs escaping, so we need twice as much space. */ + /* Adjust for potential quotes. Also assume the worst-case scenario that + * every character needs escaping, so we need twice as much space. */ dst_len = dst_len * 2 + arg_count * 2; /* Allocate buffer for the final command line. */ @@ -831,8 +831,13 @@ int make_program_env(char* env_block[], WCHAR** dst_ptr) { */ static WCHAR* find_path(WCHAR *env) { for (; env != NULL && *env != 0; env += wcslen(env) + 1) { - if (wcsncmp(env, L"PATH=", 5) == 0) + if ((env[0] == L'P' || env[0] == L'p') && + (env[1] == L'A' || env[1] == L'a') && + (env[2] == L'T' || env[2] == L't') && + (env[3] == L'H' || env[3] == L'h') && + (env[4] == L'=')) { return &env[5]; + } } return NULL; @@ -865,9 +870,9 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { assert(handle->exit_cb_pending); handle->exit_cb_pending = 0; - /* If we're closing, don't call the exit callback. Just schedule a close */ - /* callback now. */ - if (handle->flags & UV__HANDLE_CLOSING) { + /* If we're closing, don't call the exit callback. Just schedule a close + * callback now. */ + if (handle->flags & UV_HANDLE_CLOSING) { uv_want_endgame(loop, (uv_handle_t*) handle); return; } @@ -878,14 +883,14 @@ void uv_process_proc_exit(uv_loop_t* loop, uv_process_t* handle) { handle->wait_handle = INVALID_HANDLE_VALUE; } - /* Set the handle to inactive: no callbacks will be made after the exit */ - /* callback.*/ + /* Set the handle to inactive: no callbacks will be made after the exit + * callback. */ uv__handle_stop(handle); if (GetExitCodeProcess(handle->process_handle, &status)) { exit_code = status; } else { - /* Unable to to obtain the exit code. This should never happen. */ + /* Unable to obtain the exit code. This should never happen. */ exit_code = uv_translate_sys_error(GetLastError()); } @@ -900,8 +905,8 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { uv__handle_closing(handle); if (handle->wait_handle != INVALID_HANDLE_VALUE) { - /* This blocks until either the wait was cancelled, or the callback has */ - /* completed. */ + /* This blocks until either the wait was cancelled, or the callback has + * completed. */ BOOL r = UnregisterWaitEx(handle->wait_handle, INVALID_HANDLE_VALUE); if (!r) { /* This should never happen, and if it happens, we can't recover... */ @@ -919,7 +924,7 @@ void uv_process_close(uv_loop_t* loop, uv_process_t* handle) { void uv_process_endgame(uv_loop_t* loop, uv_process_t* handle) { assert(!handle->exit_cb_pending); - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); /* Clean-up the process handle. */ @@ -1104,14 +1109,13 @@ int uv_spawn(uv_loop_t* loop, goto done; } - /* Spawn succeeded */ - /* Beyond this point, failure is reported asynchronously. */ + /* Spawn succeeded. Beyond this point, failure is reported asynchronously. */ process->process_handle = info.hProcess; process->pid = info.dwProcessId; - /* If the process isn't spawned as detached, assign to the global job */ - /* object so windows will kill it when the parent process dies. */ + /* If the process isn't spawned as detached, assign to the global job object + * so windows will kill it when the parent process dies. */ if (!(options->flags & UV_PROCESS_DETACHED)) { uv_once(&uv_global_job_handle_init_guard_, uv__init_global_job_handle); @@ -1138,7 +1142,8 @@ int uv_spawn(uv_loop_t* loop, if (fdopt->flags & UV_CREATE_PIPE && fdopt->data.stream->type == UV_NAMED_PIPE && ((uv_pipe_t*) fdopt->data.stream)->ipc) { - ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_pid = info.dwProcessId; + ((uv_pipe_t*) fdopt->data.stream)->pipe.conn.ipc_remote_pid = + info.dwProcessId; } } @@ -1154,8 +1159,8 @@ int uv_spawn(uv_loop_t* loop, assert(!err); - /* Make the handle active. It will remain active until the exit callback */ - /* is made or the handle is closed, whichever happens first. */ + /* Make the handle active. It will remain active until the exit callback is + * made or the handle is closed, whichever happens first. */ uv__handle_start(process); /* Cleanup, whether we succeeded or failed. */ @@ -1186,16 +1191,16 @@ static int uv__kill(HANDLE process_handle, int signum) { case SIGTERM: case SIGKILL: case SIGINT: { - /* Unconditionally terminate the process. On Windows, killed processes */ - /* normally return 1. */ + /* Unconditionally terminate the process. On Windows, killed processes + * normally return 1. */ DWORD status; int err; if (TerminateProcess(process_handle, 1)) return 0; - /* If the process already exited before TerminateProcess was called, */ - /* TerminateProcess will fail with ERROR_ACCESS_DENIED. */ + /* If the process already exited before TerminateProcess was called,. + * TerminateProcess will fail with ERROR_ACCESS_DENIED. */ err = GetLastError(); if (err == ERROR_ACCESS_DENIED && GetExitCodeProcess(process_handle, &status) && diff --git a/deps/libuv/src/win/signal.c b/deps/libuv/src/win/signal.c index a174da1f7..3d0b8a35b 100644 --- a/deps/libuv/src/win/signal.c +++ b/deps/libuv/src/win/signal.c @@ -47,13 +47,13 @@ void uv_signals_init(void) { static int uv__signal_compare(uv_signal_t* w1, uv_signal_t* w2) { - /* Compare signums first so all watchers with the same signnum end up */ - /* adjacent. */ + /* Compare signums first so all watchers with the same signnum end up + * adjacent. */ if (w1->signum < w2->signum) return -1; if (w1->signum > w2->signum) return 1; - /* Sort by loop pointer, so we can easily look up the first item after */ - /* { .signum = x, .loop = NULL } */ + /* Sort by loop pointer, so we can easily look up the first item after + * { .signum = x, .loop = NULL }. */ if ((uintptr_t) w1->loop < (uintptr_t) w2->loop) return -1; if ((uintptr_t) w1->loop > (uintptr_t) w2->loop) return 1; @@ -90,7 +90,7 @@ int uv__signal_dispatch(int signum) { unsigned long previous = InterlockedExchange( (volatile LONG*) &handle->pending_signum, signum); - if (handle->flags & UV__SIGNAL_ONE_SHOT_DISPATCHED) + if (handle->flags & UV_SIGNAL_ONE_SHOT_DISPATCHED) continue; if (!previous) { @@ -98,8 +98,8 @@ int uv__signal_dispatch(int signum) { } dispatched = 1; - if (handle->flags & UV__SIGNAL_ONE_SHOT) - handle->flags |= UV__SIGNAL_ONE_SHOT_DISPATCHED; + if (handle->flags & UV_SIGNAL_ONE_SHOT) + handle->flags |= UV_SIGNAL_ONE_SHOT_DISPATCHED; } LeaveCriticalSection(&uv__signal_lock); @@ -118,10 +118,10 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { case CTRL_CLOSE_EVENT: if (uv__signal_dispatch(SIGHUP)) { - /* Windows will terminate the process after the control handler */ - /* returns. After that it will just terminate our process. Therefore */ - /* block the signal handler so the main loop has some time to pick */ - /* up the signal and do something for a few seconds. */ + /* Windows will terminate the process after the control handler + * returns. After that it will just terminate our process. Therefore + * block the signal handler so the main loop has some time to pick up + * the signal and do something for a few seconds. */ Sleep(INFINITE); return TRUE; } @@ -129,8 +129,8 @@ static BOOL WINAPI uv__signal_control_handler(DWORD type) { case CTRL_LOGOFF_EVENT: case CTRL_SHUTDOWN_EVENT: - /* These signals are only sent to services. Services have their own */ - /* notification mechanism, so there's no point in handling these. */ + /* These signals are only sent to services. Services have their own + * notification mechanism, so there's no point in handling these. */ default: /* We don't handle these. */ @@ -193,10 +193,10 @@ int uv__signal_start(uv_signal_t* handle, if (signum != SIGWINCH && (signum <= 0 || signum >= NSIG)) return UV_EINVAL; - /* Short circuit: if the signal watcher is already watching {signum} don't */ - /* go through the process of deregistering and registering the handler. */ - /* Additionally, this avoids pending signals getting lost in the (small) */ - /* time frame that handle->signum == 0. */ + /* Short circuit: if the signal watcher is already watching {signum} don't go + * through the process of deregistering and registering the handler. + * Additionally, this avoids pending signals getting lost in the (small) time + * frame that handle->signum == 0. */ if (signum == handle->signum) { handle->signal_cb = signal_cb; return 0; @@ -213,7 +213,7 @@ int uv__signal_start(uv_signal_t* handle, handle->signum = signum; if (oneshot) - handle->flags |= UV__SIGNAL_ONE_SHOT; + handle->flags |= UV_SIGNAL_ONE_SHOT; RB_INSERT(uv_signal_tree_s, &uv__signal_tree, handle); @@ -237,16 +237,16 @@ void uv_process_signal_req(uv_loop_t* loop, uv_signal_t* handle, (volatile LONG*) &handle->pending_signum, 0); assert(dispatched_signum != 0); - /* Check if the pending signal equals the signum that we are watching for. */ - /* These can get out of sync when the handler is stopped and restarted */ - /* while the signal_req is pending. */ + /* Check if the pending signal equals the signum that we are watching for. + * These can get out of sync when the handler is stopped and restarted while + * the signal_req is pending. */ if (dispatched_signum == handle->signum) handle->signal_cb(handle, dispatched_signum); - if (handle->flags & UV__SIGNAL_ONE_SHOT) + if (handle->flags & UV_SIGNAL_ONE_SHOT) uv_signal_stop(handle); - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* When it is closing, it must be stopped at this point. */ assert(handle->signum == 0); uv_want_endgame(loop, (uv_handle_t*) handle); @@ -265,7 +265,7 @@ void uv_signal_close(uv_loop_t* loop, uv_signal_t* handle) { void uv_signal_endgame(uv_loop_t* loop, uv_signal_t* handle) { - assert(handle->flags & UV__HANDLE_CLOSING); + assert(handle->flags & UV_HANDLE_CLOSING); assert(!(handle->flags & UV_HANDLE_CLOSED)); assert(handle->signum == 0); diff --git a/deps/libuv/src/win/stream.c b/deps/libuv/src/win/stream.c index 13cbfdcb9..7656627e9 100644 --- a/deps/libuv/src/win/stream.c +++ b/deps/libuv/src/win/stream.c @@ -105,12 +105,10 @@ int uv_read_stop(uv_stream_t* handle) { err = 0; if (handle->type == UV_TTY) { err = uv_tty_read_stop((uv_tty_t*) handle); + } else if (handle->type == UV_NAMED_PIPE) { + uv__pipe_read_stop((uv_pipe_t*) handle); } else { - if (handle->type == UV_NAMED_PIPE) { - uv__pipe_stop_read((uv_pipe_t*) handle); - } else { - handle->flags &= ~UV_HANDLE_READING; - } + handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(handle->loop, handle); } @@ -136,7 +134,8 @@ int uv_write(uv_write_t* req, err = uv_tcp_write(loop, req, (uv_tcp_t*) handle, bufs, nbufs, cb); break; case UV_NAMED_PIPE: - err = uv_pipe_write(loop, req, (uv_pipe_t*) handle, bufs, nbufs, cb); + err = uv__pipe_write( + loop, req, (uv_pipe_t*) handle, bufs, nbufs, NULL, cb); break; case UV_TTY: err = uv_tty_write(loop, req, (uv_tty_t*) handle, bufs, nbufs, cb); @@ -158,25 +157,18 @@ int uv_write2(uv_write_t* req, uv_loop_t* loop = handle->loop; int err; - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; + if (send_handle == NULL) { + return uv_write(req, handle, bufs, nbufs, cb); } - err = ERROR_INVALID_PARAMETER; - switch (handle->type) { - case UV_NAMED_PIPE: - err = uv_pipe_write2(loop, - req, - (uv_pipe_t*) handle, - bufs, - nbufs, - send_handle, - cb); - break; - default: - assert(0); + if (handle->type != UV_NAMED_PIPE || !((uv_pipe_t*) handle)->ipc) { + return UV_EINVAL; + } else if (!(handle->flags & UV_HANDLE_WRITABLE)) { + return UV_EPIPE; } + err = uv__pipe_write( + loop, req, (uv_pipe_t*) handle, bufs, nbufs, send_handle, cb); return uv_translate_sys_error(err); } @@ -184,7 +176,7 @@ int uv_write2(uv_write_t* req, int uv_try_write(uv_stream_t* stream, const uv_buf_t bufs[], unsigned int nbufs) { - if (stream->flags & UV__HANDLE_CLOSING) + if (stream->flags & UV_HANDLE_CLOSING) return UV_EBADF; if (!(stream->flags & UV_HANDLE_WRITABLE)) return UV_EPIPE; diff --git a/deps/libuv/src/win/tcp.c b/deps/libuv/src/win/tcp.c index 39c1ff056..a97ab2a51 100644 --- a/deps/libuv/src/win/tcp.c +++ b/deps/libuv/src/win/tcp.c @@ -99,8 +99,8 @@ static int uv_tcp_set_socket(uv_loop_t* loop, if (!SetHandleInformation((HANDLE) socket, HANDLE_FLAG_INHERIT, 0)) return GetLastError(); - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ + /* Associate it with the I/O completion port. Use uv_handle_t pointer as + * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, @@ -118,15 +118,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; } - if (pSetFileCompletionNotificationModes && - !(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { - if (pSetFileCompletionNotificationModes((HANDLE) socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { + if (!(handle->flags & UV_HANDLE_EMULATE_IOCP) && !non_ifs_lsp) { + UCHAR sfcnm_flags = + FILE_SKIP_SET_EVENT_ON_HANDLE | FILE_SKIP_COMPLETION_PORT_ON_SUCCESS; + if (!SetFileCompletionNotificationModes((HANDLE) socket, sfcnm_flags)) return GetLastError(); - } + handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; } if (handle->flags & UV_HANDLE_TCP_NODELAY) { @@ -220,7 +217,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { UNREGISTER_HANDLE_REQ(loop, handle, handle->stream.conn.shutdown_req); err = 0; - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { err = ERROR_OPERATION_ABORTED; } else if (shutdown(handle->socket, SD_SEND) == SOCKET_ERROR) { err = WSAGetLastError(); @@ -236,7 +233,7 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { return; } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); @@ -326,9 +323,9 @@ static int uv_tcp_try_bind(uv_tcp_t* handle, on = (flags & UV_TCP_IPV6ONLY) != 0; - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ + /* TODO: how to handle errors? This may fail if there is no ipv4 stack + * available, or when run on XP/2003 which have no support for dualstack + * sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, @@ -626,9 +623,9 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { uv_tcp_queue_accept(handle, req); } - /* Initialize other unused requests too, because uv_tcp_endgame */ - /* doesn't know how how many requests were initialized, so it will */ - /* try to clean up {uv_simultaneous_server_accepts} requests. */ + /* Initialize other unused requests too, because uv_tcp_endgame doesn't + * know how many requests were initialized, so it will try to clean up + * {uv_simultaneous_server_accepts} requests. */ for (i = simultaneous_accepts; i < uv_simultaneous_server_accepts; i++) { req = &handle->tcp.serv.accept_reqs[i]; UV_REQ_INIT(req, UV_ACCEPT); @@ -683,7 +680,7 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { req->next_pending = NULL; req->accept_socket = INVALID_SOCKET; - if (!(server->flags & UV__HANDLE_CLOSING)) { + if (!(server->flags & UV_HANDLE_CLOSING)) { /* Check if we're in a middle of changing the number of pending accepts. */ if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { uv_tcp_queue_accept(server, req); @@ -721,8 +718,8 @@ int uv_tcp_read_start(uv_tcp_t* handle, uv_alloc_cb alloc_cb, handle->alloc_cb = alloc_cb; INCREASE_ACTIVE_COUNT(loop, handle); - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) { if (handle->flags & UV_HANDLE_EMULATE_IOCP && !handle->read_req.event_handle) { @@ -965,8 +962,7 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, err = GET_REQ_SOCK_ERROR(req); if (err == WSAECONNABORTED) { - /* - * Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. + /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with Unix. */ err = WSAECONNRESET; } @@ -1046,8 +1042,8 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, DECREASE_ACTIVE_COUNT(loop, handle); if (err == WSAECONNABORTED) { - /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with */ - /* Unix. */ + /* Turn WSAECONNABORTED into UV_ECONNRESET to be consistent with + * Unix. */ err = WSAECONNRESET; } @@ -1119,10 +1115,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, assert(handle->type == UV_TCP); - /* If handle->accepted_socket is not a valid socket, then */ - /* uv_queue_accept must have failed. This is a serious error. We stop */ - /* accepting connections and report this error to the connection */ - /* callback. */ + /* If handle->accepted_socket is not a valid socket, then uv_queue_accept + * must have failed. This is a serious error. We stop accepting connections + * and report this error to the connection callback. */ if (req->accept_socket == INVALID_SOCKET) { if (handle->flags & UV_HANDLE_LISTENING) { handle->flags &= ~UV_HANDLE_LISTENING; @@ -1147,9 +1142,9 @@ void uv_process_tcp_accept_req(uv_loop_t* loop, uv_tcp_t* handle, handle->stream.serv.connection_cb((uv_stream_t*)handle, 0); } } else { - /* Error related to accepted socket is ignored because the server */ - /* socket may still be healthy. If the server socket is broken */ - /* uv_queue_accept will detect it. */ + /* Error related to accepted socket is ignored because the server socket + * may still be healthy. If the server socket is broken uv_queue_accept + * will detect it. */ closesocket(req->accept_socket); req->accept_socket = INVALID_SOCKET; if (handle->flags & UV_HANDLE_LISTENING) { @@ -1171,7 +1166,7 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, err = 0; if (REQ_SUCCESS(req)) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { /* use UV_ECANCELED for consistency with Unix */ err = ERROR_OPERATION_ABORTED; } else if (setsockopt(handle->socket, @@ -1194,13 +1189,46 @@ void uv_process_tcp_connect_req(uv_loop_t* loop, uv_tcp_t* handle, } -int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, - int tcp_connection) { +int uv__tcp_xfer_export(uv_tcp_t* handle, + int target_pid, + uv__ipc_socket_xfer_info_t* xfer_info) { + if (!(handle->flags & UV_HANDLE_CONNECTION)) { + /* We're about to share the socket with another process. Because this is a + * listening socket, we assume that the other process will be accepting + * connections on it. Thus, before sharing the socket with another process, + * we call listen here in the parent process. */ + if (!(handle->flags & UV_HANDLE_LISTENING)) { + if (!(handle->flags & UV_HANDLE_BOUND)) { + return ERROR_NOT_SUPPORTED; + } + if (handle->delayed_error == 0 && + listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { + handle->delayed_error = WSAGetLastError(); + } + } + } + + if (WSADuplicateSocketW( + handle->socket, target_pid, &xfer_info->socket_info)) { + return WSAGetLastError(); + } + xfer_info->delayed_error = handle->delayed_error; + xfer_info->flags = handle->flags & UV_HANDLE_CONNECTION; + + /* Mark the local copy of the handle as 'shared' so we behave in a way that's + * friendly to the process(es) that we share the socket with. */ + handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; + + return 0; +} + + +int uv__tcp_xfer_import(uv_tcp_t* tcp, uv__ipc_socket_xfer_info_t* xfer_info) { int err; SOCKET socket = WSASocketW(FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, FROM_PROTOCOL_INFO, - &socket_info_ex->socket_info, + &xfer_info->socket_info, 0, WSA_FLAG_OVERLAPPED); @@ -1208,26 +1236,21 @@ int uv_tcp_import(uv_tcp_t* tcp, uv__ipc_socket_info_ex* socket_info_ex, return WSAGetLastError(); } - err = uv_tcp_set_socket(tcp->loop, - tcp, - socket, - socket_info_ex->socket_info.iAddressFamily, - 1); + err = uv_tcp_set_socket( + tcp->loop, tcp, socket, xfer_info->socket_info.iAddressFamily, 1); if (err) { closesocket(socket); return err; } - if (tcp_connection) { + tcp->delayed_error = xfer_info->delayed_error; + tcp->flags |= UV_HANDLE_BOUND | UV_HANDLE_SHARED_TCP_SOCKET; + + if (xfer_info->flags & UV_HANDLE_CONNECTION) { uv_connection_init((uv_stream_t*)tcp); tcp->flags |= UV_HANDLE_READABLE | UV_HANDLE_WRITABLE; } - tcp->flags |= UV_HANDLE_BOUND; - tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - tcp->delayed_error = socket_info_ex->delayed_error; - tcp->loop->active_tcp_streams++; return 0; } @@ -1273,39 +1296,6 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { } -int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, - LPWSAPROTOCOL_INFOW protocol_info) { - if (!(handle->flags & UV_HANDLE_CONNECTION)) { - /* - * We're about to share the socket with another process. Because - * this is a listening socket, we assume that the other process will - * be accepting connections on it. So, before sharing the socket - * with another process, we call listen here in the parent process. - */ - - if (!(handle->flags & UV_HANDLE_LISTENING)) { - if (!(handle->flags & UV_HANDLE_BOUND)) { - return ERROR_INVALID_PARAMETER; - } - - if (!(handle->delayed_error)) { - if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { - handle->delayed_error = WSAGetLastError(); - } - } - } - } - - if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) { - return WSAGetLastError(); - } - - handle->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - - return 0; -} - - int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { if (handle->flags & UV_HANDLE_CONNECTION) { return UV_EINVAL; @@ -1346,8 +1336,8 @@ static int uv_tcp_try_cancel_io(uv_tcp_t* tcp) { non_ifs_lsp = (tcp->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : uv_tcp_non_ifs_lsp_ipv4; - /* If there are non-ifs LSPs then try to obtain a base handle for the */ - /* socket. This will always fail on Windows XP/3k. */ + /* If there are non-ifs LSPs then try to obtain a base handle for the socket. + * This will always fail on Windows XP/3k. */ if (non_ifs_lsp) { DWORD bytes; if (WSAIoctl(socket, @@ -1379,38 +1369,37 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { int close_socket = 1; if (tcp->flags & UV_HANDLE_READ_PENDING) { - /* In order for winsock to do a graceful close there must not be any */ - /* any pending reads, or the socket must be shut down for writing */ + /* In order for winsock to do a graceful close there must not be any any + * pending reads, or the socket must be shut down for writing */ if (!(tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET)) { /* Just do shutdown on non-shared sockets, which ensures graceful close. */ shutdown(tcp->socket, SD_SEND); } else if (uv_tcp_try_cancel_io(tcp) == 0) { - /* In case of a shared socket, we try to cancel all outstanding I/O, */ - /* If that works, don't close the socket yet - wait for the read req to */ - /* return and close the socket in uv_tcp_endgame. */ + /* In case of a shared socket, we try to cancel all outstanding I/O,. If + * that works, don't close the socket yet - wait for the read req to + * return and close the socket in uv_tcp_endgame. */ close_socket = 0; } else { - /* When cancelling isn't possible - which could happen when an LSP is */ - /* present on an old Windows version, we will have to close the socket */ - /* with a read pending. That is not nice because trailing sent bytes */ - /* may not make it to the other side. */ + /* When cancelling isn't possible - which could happen when an LSP is + * present on an old Windows version, we will have to close the socket + * with a read pending. That is not nice because trailing sent bytes may + * not make it to the other side. */ } } else if ((tcp->flags & UV_HANDLE_SHARED_TCP_SOCKET) && tcp->tcp.serv.accept_reqs != NULL) { - /* Under normal circumstances closesocket() will ensure that all pending */ - /* accept reqs are canceled. However, when the socket is shared the */ - /* presence of another reference to the socket in another process will */ - /* keep the accept reqs going, so we have to ensure that these are */ - /* canceled. */ + /* Under normal circumstances closesocket() will ensure that all pending + * accept reqs are canceled. However, when the socket is shared the + * presence of another reference to the socket in another process will keep + * the accept reqs going, so we have to ensure that these are canceled. */ if (uv_tcp_try_cancel_io(tcp) != 0) { - /* When cancellation is not possible, there is another option: we can */ - /* close the incoming sockets, which will also cancel the accept */ - /* operations. However this is not cool because we might inadvertently */ - /* close a socket that just accepted a new connection, which will */ - /* cause the connection to be aborted. */ + /* When cancellation is not possible, there is another option: we can + * close the incoming sockets, which will also cancel the accept + * operations. However this is not cool because we might inadvertently + * close a socket that just accepted a new connection, which will cause + * the connection to be aborted. */ unsigned int i; for (i = 0; i < uv_simultaneous_server_accepts; i++) { uv_tcp_accept_t* req = &tcp->tcp.serv.accept_reqs[i]; diff --git a/deps/libuv/src/win/thread.c b/deps/libuv/src/win/thread.c index 9eaad77cd..6e41dcd8a 100644 --- a/deps/libuv/src/win/thread.c +++ b/deps/libuv/src/win/thread.c @@ -26,26 +26,6 @@ #include "uv.h" #include "internal.h" - -#define HAVE_CONDVAR_API() (pInitializeConditionVariable != NULL) - -static int uv_cond_fallback_init(uv_cond_t* cond); -static void uv_cond_fallback_destroy(uv_cond_t* cond); -static void uv_cond_fallback_signal(uv_cond_t* cond); -static void uv_cond_fallback_broadcast(uv_cond_t* cond); -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - -static int uv_cond_condvar_init(uv_cond_t* cond); -static void uv_cond_condvar_destroy(uv_cond_t* cond); -static void uv_cond_condvar_signal(uv_cond_t* cond); -static void uv_cond_condvar_broadcast(uv_cond_t* cond); -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex); -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout); - - static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { DWORD result; HANDLE existing_event, created_event; @@ -69,8 +49,8 @@ static void uv__once_inner(uv_once_t* guard, void (*callback)(void)) { guard->ran = 1; } else { - /* We lost the race. Destroy the event we created and wait for the */ - /* existing one to become signaled. */ + /* We lost the race. Destroy the event we created and wait for the existing + * one to become signaled. */ CloseHandle(created_event); result = WaitForSingleObject(existing_event, INFINITE); assert(result == WAIT_OBJECT_0); @@ -377,220 +357,35 @@ int uv_sem_trywait(uv_sem_t* sem) { } -/* This condition variable implementation is based on the SetEvent solution - * (section 3.2) at http://www.cs.wustl.edu/~schmidt/win32-cv-1.html - * We could not use the SignalObjectAndWait solution (section 3.4) because - * it want the 2nd argument (type uv_mutex_t) of uv_cond_wait() and - * uv_cond_timedwait() to be HANDLEs, but we use CRITICAL_SECTIONs. - */ - -static int uv_cond_fallback_init(uv_cond_t* cond) { - int err; - - /* Initialize the count to 0. */ - cond->fallback.waiters_count = 0; - - InitializeCriticalSection(&cond->fallback.waiters_count_lock); - - /* Create an auto-reset event. */ - cond->fallback.signal_event = CreateEvent(NULL, /* no security */ - FALSE, /* auto-reset event */ - FALSE, /* non-signaled initially */ - NULL); /* unnamed */ - if (!cond->fallback.signal_event) { - err = GetLastError(); - goto error2; - } - - /* Create a manual-reset event. */ - cond->fallback.broadcast_event = CreateEvent(NULL, /* no security */ - TRUE, /* manual-reset */ - FALSE, /* non-signaled */ - NULL); /* unnamed */ - if (!cond->fallback.broadcast_event) { - err = GetLastError(); - goto error; - } - - return 0; - -error: - CloseHandle(cond->fallback.signal_event); -error2: - DeleteCriticalSection(&cond->fallback.waiters_count_lock); - return uv_translate_sys_error(err); -} - - -static int uv_cond_condvar_init(uv_cond_t* cond) { - pInitializeConditionVariable(&cond->cond_var); - return 0; -} - - int uv_cond_init(uv_cond_t* cond) { - uv__once_init(); - - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_init(cond); - else - return uv_cond_fallback_init(cond); -} - - -static void uv_cond_fallback_destroy(uv_cond_t* cond) { - if (!CloseHandle(cond->fallback.broadcast_event)) - abort(); - if (!CloseHandle(cond->fallback.signal_event)) - abort(); - DeleteCriticalSection(&cond->fallback.waiters_count_lock); -} - - -static void uv_cond_condvar_destroy(uv_cond_t* cond) { - /* nothing to do */ + InitializeConditionVariable(&cond->cond_var); + return 0; } void uv_cond_destroy(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_destroy(cond); - else - uv_cond_fallback_destroy(cond); -} - - -static void uv_cond_fallback_signal(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.signal_event); -} - - -static void uv_cond_condvar_signal(uv_cond_t* cond) { - pWakeConditionVariable(&cond->cond_var); + /* nothing to do */ + (void) &cond; } void uv_cond_signal(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_signal(cond); - else - uv_cond_fallback_signal(cond); -} - - -static void uv_cond_fallback_broadcast(uv_cond_t* cond) { - int have_waiters; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - have_waiters = cond->fallback.waiters_count > 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - if (have_waiters) - SetEvent(cond->fallback.broadcast_event); -} - - -static void uv_cond_condvar_broadcast(uv_cond_t* cond) { - pWakeAllConditionVariable(&cond->cond_var); + WakeConditionVariable(&cond->cond_var); } void uv_cond_broadcast(uv_cond_t* cond) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_broadcast(cond); - else - uv_cond_fallback_broadcast(cond); -} - - -static int uv_cond_wait_helper(uv_cond_t* cond, uv_mutex_t* mutex, - DWORD dwMilliseconds) { - DWORD result; - int last_waiter; - HANDLE handles[2] = { - cond->fallback.signal_event, - cond->fallback.broadcast_event - }; - - /* Avoid race conditions. */ - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count++; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* It's ok to release the here since Win32 manual-reset events */ - /* maintain state when used with . This avoids the "lost wakeup" */ - /* bug. */ - uv_mutex_unlock(mutex); - - /* Wait for either event to become signaled due to being */ - /* called or being called. */ - result = WaitForMultipleObjects(2, handles, FALSE, dwMilliseconds); - - EnterCriticalSection(&cond->fallback.waiters_count_lock); - cond->fallback.waiters_count--; - last_waiter = result == WAIT_OBJECT_0 + 1 - && cond->fallback.waiters_count == 0; - LeaveCriticalSection(&cond->fallback.waiters_count_lock); - - /* Some thread called . */ - if (last_waiter) { - /* We're the last waiter to be notified or to stop waiting, so reset the */ - /* the manual-reset event. */ - ResetEvent(cond->fallback.broadcast_event); - } - - /* Reacquire the . */ - uv_mutex_lock(mutex); - - if (result == WAIT_OBJECT_0 || result == WAIT_OBJECT_0 + 1) - return 0; - - if (result == WAIT_TIMEOUT) - return UV_ETIMEDOUT; - - abort(); - return -1; /* Satisfy the compiler. */ -} - - -static void uv_cond_fallback_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (uv_cond_wait_helper(cond, mutex, INFINITE)) - abort(); -} - - -static void uv_cond_condvar_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (!pSleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) - abort(); + WakeAllConditionVariable(&cond->cond_var); } void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { - if (HAVE_CONDVAR_API()) - uv_cond_condvar_wait(cond, mutex); - else - uv_cond_fallback_wait(cond, mutex); -} - - -static int uv_cond_fallback_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - return uv_cond_wait_helper(cond, mutex, (DWORD)(timeout / 1e6)); + if (!SleepConditionVariableCS(&cond->cond_var, mutex, INFINITE)) + abort(); } - -static int uv_cond_condvar_timedwait(uv_cond_t* cond, - uv_mutex_t* mutex, uint64_t timeout) { - if (pSleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) +int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { + if (SleepConditionVariableCS(&cond->cond_var, mutex, (DWORD)(timeout / 1e6))) return 0; if (GetLastError() != ERROR_TIMEOUT) abort(); @@ -598,15 +393,6 @@ static int uv_cond_condvar_timedwait(uv_cond_t* cond, } -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, - uint64_t timeout) { - if (HAVE_CONDVAR_API()) - return uv_cond_condvar_timedwait(cond, mutex, timeout); - else - return uv_cond_fallback_timedwait(cond, mutex, timeout); -} - - int uv_barrier_init(uv_barrier_t* barrier, unsigned int count) { int err; diff --git a/deps/libuv/src/win/timer.c b/deps/libuv/src/win/timer.c deleted file mode 100644 index 7e006fedf..000000000 --- a/deps/libuv/src/win/timer.c +++ /dev/null @@ -1,195 +0,0 @@ -/* 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 - -#include "uv.h" -#include "internal.h" -#include "tree.h" -#include "handle-inl.h" - - -/* The number of milliseconds in one second. */ -#define UV__MILLISEC 1000 - - -void uv_update_time(uv_loop_t* loop) { - uint64_t new_time = uv__hrtime(UV__MILLISEC); - assert(new_time >= loop->time); - loop->time = new_time; -} - - -static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { - if (a->due < b->due) - return -1; - if (a->due > b->due) - return 1; - /* - * compare start_id when both has the same due. start_id is - * allocated with loop->timer_counter in uv_timer_start(). - */ - if (a->start_id < b->start_id) - return -1; - if (a->start_id > b->start_id) - return 1; - return 0; -} - - -RB_GENERATE_STATIC(uv_timer_tree_s, uv_timer_s, tree_entry, uv_timer_compare) - - -int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_TIMER); - handle->timer_cb = NULL; - handle->repeat = 0; - - return 0; -} - - -void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING) { - assert(!(handle->flags & UV_HANDLE_CLOSED)); - uv__handle_close(handle); - } -} - - -static uint64_t get_clamped_due_time(uint64_t loop_time, uint64_t timeout) { - uint64_t clamped_timeout; - - clamped_timeout = loop_time + timeout; - if (clamped_timeout < timeout) - clamped_timeout = (uint64_t) -1; - - return clamped_timeout; -} - - -int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, - uint64_t repeat) { - uv_loop_t* loop = handle->loop; - uv_timer_t* old; - - if (timer_cb == NULL) - return UV_EINVAL; - - if (uv__is_active(handle)) - uv_timer_stop(handle); - - handle->timer_cb = timer_cb; - handle->due = get_clamped_due_time(loop->time, timeout); - handle->repeat = repeat; - uv__handle_start(handle); - - /* start_id is the second index to be compared in uv__timer_cmp() */ - handle->start_id = handle->loop->timer_counter++; - - old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle); - assert(old == NULL); - - return 0; -} - - -int uv_timer_stop(uv_timer_t* handle) { - uv_loop_t* loop = handle->loop; - - if (!uv__is_active(handle)) - return 0; - - RB_REMOVE(uv_timer_tree_s, &loop->timers, handle); - uv__handle_stop(handle); - - return 0; -} - - -int uv_timer_again(uv_timer_t* handle) { - /* If timer_cb is NULL that means that the timer was never started. */ - if (!handle->timer_cb) { - return UV_EINVAL; - } - - if (handle->repeat) { - uv_timer_stop(handle); - uv_timer_start(handle, handle->timer_cb, handle->repeat, handle->repeat); - } - - return 0; -} - - -void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { - assert(handle->type == UV_TIMER); - handle->repeat = repeat; -} - - -uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { - assert(handle->type == UV_TIMER); - return handle->repeat; -} - - -DWORD uv__next_timeout(const uv_loop_t* loop) { - uv_timer_t* timer; - int64_t delta; - - /* Check if there are any running timers - * Need to cast away const first, since RB_MIN doesn't know what we are - * going to do with this return value, it can't be marked const - */ - timer = RB_MIN(uv_timer_tree_s, &((uv_loop_t*)loop)->timers); - if (timer) { - delta = timer->due - loop->time; - if (delta >= UINT_MAX - 1) { - /* A timeout value of UINT_MAX means infinite, so that's no good. */ - return UINT_MAX - 1; - } else if (delta < 0) { - /* Negative timeout values are not allowed */ - return 0; - } else { - return (DWORD)delta; - } - } else { - /* No timers */ - return INFINITE; - } -} - - -void uv_process_timers(uv_loop_t* loop) { - uv_timer_t* timer; - - /* Call timer callbacks */ - for (timer = RB_MIN(uv_timer_tree_s, &loop->timers); - timer != NULL && timer->due <= loop->time; - timer = RB_MIN(uv_timer_tree_s, &loop->timers)) { - - uv_timer_stop(timer); - uv_timer_again(timer); - timer->timer_cb((uv_timer_t*) timer); - } -} diff --git a/deps/libuv/src/win/tty.c b/deps/libuv/src/win/tty.c index ecf7bc9b5..d62aafb7d 100644 --- a/deps/libuv/src/win/tty.c +++ b/deps/libuv/src/win/tty.c @@ -25,7 +25,7 @@ #include #if defined(_MSC_VER) && _MSC_VER < 1600 -# include "stdint-msvc2008.h" +# include "uv/stdint-msvc2008.h" #else # include #endif @@ -205,8 +205,8 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { return uv_translate_sys_error(GetLastError()); } - /* Obtain the the tty_output_lock because the virtual window state is */ - /* shared between all uv_tty_t handles. */ + /* Obtain the tty_output_lock because the virtual window state is shared + * between all uv_tty_t handles. */ uv_sem_wait(&uv_tty_output_lock); if (uv__vterm_state == UV_UNCHECKED) @@ -484,8 +484,8 @@ static DWORD CALLBACK uv_tty_line_read_thread(void* data) { bytes = MAX_INPUT_BUFFER_LENGTH; } - /* At last, unicode! */ - /* One utf-16 codeunit never takes more than 3 utf-8 codeunits to encode */ + /* At last, unicode! One utf-16 codeunit never takes more than 3 utf-8 + * codeunits to encode. */ chars = bytes / 3; status = InterlockedExchange(&uv__read_console_status, IN_PROGRESS); @@ -620,10 +620,10 @@ static const char* get_vt100_fn_key(DWORD code, char shift, char ctrl, } switch (code) { - /* These mappings are the same as Cygwin's. Unmodified and alt-modified */ - /* keypad keys comply with linux console, modifiers comply with xterm */ - /* modifier usage. F1..f12 and shift-f1..f10 comply with linux console, */ - /* f6..f12 with and without modifiers comply with rxvt. */ + /* These mappings are the same as Cygwin's. Unmodified and alt-modified + * keypad keys comply with linux console, modifiers comply with xterm + * modifier usage. F1. f12 and shift-f1. f10 comply with linux console, f6. + * f12 with and without modifiers comply with rxvt. */ VK_CASE(VK_INSERT, "[2~", "[2;2~", "[2;5~", "[2;6~") VK_CASE(VK_END, "[4~", "[4;2~", "[4;5~", "[4;6~") VK_CASE(VK_DOWN, "[B", "[1;2B", "[1;5B", "[1;6B") @@ -706,8 +706,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, goto out; } - /* Windows sends a lot of events that we're not interested in, so buf */ - /* will be allocated on demand, when there's actually something to emit. */ + /* Windows sends a lot of events that we're not interested in, so buf will be + * allocated on demand, when there's actually something to emit. */ buf = uv_null_buf_; buf_used = 0; @@ -733,16 +733,16 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, continue; } - /* Ignore keyup events, unless the left alt key was held and a valid */ - /* unicode character was emitted. */ + /* Ignore keyup events, unless the left alt key was held and a valid + * unicode character was emitted. */ if (!KEV.bKeyDown && !(((KEV.dwControlKeyState & LEFT_ALT_PRESSED) || KEV.wVirtualKeyCode==VK_MENU) && KEV.uChar.UnicodeChar != 0)) { continue; } - /* Ignore keypresses to numpad number keys if the left alt is held */ - /* because the user is composing a character, or windows simulating */ - /* this. */ + /* Ignore keypresses to numpad number keys if the left alt is held + * because the user is composing a character, or windows simulating this. + */ if ((KEV.dwControlKeyState & LEFT_ALT_PRESSED) && !(KEV.dwControlKeyState & ENHANCED_KEY) && (KEV.wVirtualKeyCode == VK_INSERT || @@ -779,8 +779,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, continue; } - /* Prefix with \u033 if alt was held, but alt was not used as part */ - /* a compose sequence. */ + /* Prefix with \u033 if alt was held, but alt was not used as part a + * compose sequence. */ if ((KEV.dwControlKeyState & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) && !(KEV.dwControlKeyState & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED)) && KEV.bKeyDown) { @@ -818,8 +818,8 @@ void uv_process_tty_read_raw_req(uv_loop_t* loop, uv_tty_t* handle, /* Whatever happened, the last character wasn't a high surrogate. */ handle->tty.rd.last_utf16_high_surrogate = 0; - /* If the utf16 character(s) couldn't be converted something must */ - /* be wrong. */ + /* If the utf16 character(s) couldn't be converted something must be + * wrong. */ if (!char_len) { handle->flags &= ~UV_HANDLE_READING; DECREASE_ACTIVE_COUNT(loop, handle); @@ -950,8 +950,7 @@ void uv_process_tty_read_line_req(uv_loop_t* loop, uv_tty_t* handle, } else { if (!(handle->flags & UV_HANDLE_CANCELLATION_PENDING)) { - /* Read successful */ - /* TODO: read unicode, convert to utf-8 */ + /* Read successful. TODO: read unicode, convert to utf-8 */ DWORD bytes = req->u.io.overlapped.InternalHigh; handle->read_cb((uv_stream_t*) handle, bytes, &buf); } else { @@ -975,9 +974,9 @@ void uv_process_tty_read_req(uv_loop_t* loop, uv_tty_t* handle, assert(handle->type == UV_TTY); assert(handle->flags & UV_HANDLE_TTY_READABLE); - /* If the read_line_buffer member is zero, it must have been an raw read. */ - /* Otherwise it was a line-buffered read. */ - /* FIXME: This is quite obscure. Use a flag or something. */ + /* If the read_line_buffer member is zero, it must have been an raw read. + * Otherwise it was a line-buffered read. FIXME: This is quite obscure. Use a + * flag or something. */ if (handle->tty.rd.read_line_buffer.len == 0) { uv_process_tty_read_raw_req(loop, handle, req); } else { @@ -999,14 +998,14 @@ int uv_tty_read_start(uv_tty_t* handle, uv_alloc_cb alloc_cb, handle->read_cb = read_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* read request pending. */ + /* If reading was stopped and then started again, there could still be a read + * request pending. */ if (handle->flags & UV_HANDLE_READ_PENDING) { return 0; } - /* Maybe the user stopped reading half-way while processing key events. */ - /* Short-circuit if this could be the case. */ + /* Maybe the user stopped reading half-way while processing key events. + * Short-circuit if this could be the case. */ if (handle->tty.rd.last_key_len > 0) { SET_REQ_SUCCESS(&handle->read_req); uv_insert_pending_req(handle->loop, (uv_req_t*) &handle->read_req); @@ -1033,8 +1032,8 @@ int uv_tty_read_stop(uv_tty_t* handle) { return 0; if (handle->flags & UV_HANDLE_TTY_RAW) { - /* Cancel raw read */ - /* Write some bullshit event to force the console wait to return. */ + /* Cancel raw read. Write some bullshit event to force the console wait to + * return. */ memset(&record, 0, sizeof record); if (!WriteConsoleInputW(handle->handle, &record, 1, &written)) { return GetLastError(); @@ -1116,8 +1115,8 @@ static void uv_tty_update_virtual_window(CONSOLE_SCREEN_BUFFER_INFO* info) { uv_tty_virtual_offset = info->dwCursorPosition.Y; } else if (uv_tty_virtual_offset < info->dwCursorPosition.Y - uv_tty_virtual_height + 1) { - /* If suddenly find the cursor outside of the virtual window, it must */ - /* have somehow scrolled. Update the virtual window offset. */ + /* If suddenly find the cursor outside of the virtual window, it must have + * somehow scrolled. Update the virtual window offset. */ uv_tty_virtual_offset = info->dwCursorPosition.Y - uv_tty_virtual_height + 1; } @@ -1304,8 +1303,8 @@ static int uv_tty_clear(uv_tty_t* handle, int dir, char entire_screen, x2 = 0; x2r = 1; } else { - /* Clear to end of row. We pretend the console is 65536 characters wide, */ - /* uv_tty_make_real_coord will clip it to the actual console width. */ + /* Clear to end of row. We pretend the console is 65536 characters wide, + * uv_tty_make_real_coord will clip it to the actual console width. */ x2 = 0xffff; x2r = 0; } @@ -1613,8 +1612,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, const uv_buf_t bufs[], unsigned int nbufs, DWORD* error) { - /* We can only write 8k characters at a time. Windows can't handle */ - /* much more characters in a single console write anyway. */ + /* We can only write 8k characters at a time. Windows can't handle much more + * characters in a single console write anyway. */ WCHAR utf16_buf[MAX_CONSOLE_CHAR]; WCHAR* utf16_buffer; DWORD utf16_buf_used = 0; @@ -1650,9 +1649,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, unsigned char previous_eol = handle->tty.wr.previous_eol; unsigned char ansi_parser_state = handle->tty.wr.ansi_parser_state; - /* Store the error here. If we encounter an error, stop trying to do i/o */ - /* but keep parsing the buffer so we leave the parser in a consistent */ - /* state. */ + /* Store the error here. If we encounter an error, stop trying to do i/o but + * keep parsing the buffer so we leave the parser in a consistent state. */ *error = ERROR_SUCCESS; utf16_buffer = utf16_buf; @@ -1700,9 +1698,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, for (j = 0; j < buf.len; j++) { unsigned char c = buf.base[j]; - /* Run the character through the utf8 decoder We happily accept non */ - /* shortest form encodings and invalid code points - there's no real */ - /* harm that can be done. */ + /* Run the character through the utf8 decoder We happily accept non + * shortest form encodings and invalid code points - there's no real harm + * that can be done. */ if (utf8_bytes_left == 0) { /* Read utf-8 start byte */ DWORD first_zero_bit; @@ -1742,8 +1740,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, /* Start byte where continuation was expected. */ utf8_bytes_left = 0; utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; - /* Patch buf offset so this character will be parsed again as a */ - /* start byte. */ + /* Patch buf offset so this character will be parsed again as a start + * byte. */ j--; } @@ -1776,8 +1774,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, case '_': case 'P': case ']': - /* Not supported, but we'll have to parse until we see a stop */ - /* code, e.g. ESC \ or BEL. */ + /* Not supported, but we'll have to parse until we see a stop code, + * e. g. ESC \ or BEL. */ ansi_parser_state = ANSI_ST_CONTROL; continue; @@ -1859,8 +1857,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } else { - /* If ANSI_IN_ARG is not set, add another argument and */ - /* default it to 0. */ + /* If ANSI_IN_ARG is not set, add another argument and default it + * to 0. */ + /* Check for too many arguments */ if (handle->tty.wr.ansi_csi_argc >= ARRAY_SIZE(handle->tty.wr.ansi_csi_argv)) { ansi_parser_state |= ANSI_IGNORE; @@ -1874,9 +1873,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } else if (utf8_codepoint == '?' && !(ansi_parser_state & ANSI_IN_ARG) && handle->tty.wr.ansi_csi_argc == 0) { - /* Ignores '?' if it is the first character after CSI[ */ - /* This is an extension character from the VT100 codeset */ - /* that is supported and used by most ANSI terminals today. */ + /* Ignores '?' if it is the first character after CSI[. This is an + * extension character from the VT100 codeset that is supported and + * used by most ANSI terminals today. */ continue; } else if (utf8_codepoint >= '@' && utf8_codepoint <= '~' && @@ -2006,8 +2005,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, continue; } else { - /* We don't support commands that use private mode characters or */ - /* intermediaries. Ignore the rest of the sequence. */ + /* We don't support commands that use private mode characters or + * intermediaries. Ignore the rest of the sequence. */ ansi_parser_state |= ANSI_IGNORE; continue; } @@ -2020,8 +2019,8 @@ static int uv_tty_write_bufs(uv_tty_t* handle, } } else if (ansi_parser_state & ANSI_ST_CONTROL) { - /* Unsupported control code */ - /* Ignore everything until we see BEL or ESC \ */ + /* Unsupported control code. + * Ignore everything until we see `BEL` or `ESC \`. */ if (ansi_parser_state & ANSI_IN_STRING) { if (!(ansi_parser_state & ANSI_BACKSLASH_SEEN)) { if (utf8_codepoint == '"') { @@ -2055,9 +2054,9 @@ static int uv_tty_write_bufs(uv_tty_t* handle, abort(); } - /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the */ - /* windows console doesn't really support UTF-16, so just emit the */ - /* replacement character. */ + /* We wouldn't mind emitting utf-16 surrogate pairs. Too bad, the windows + * console doesn't really support UTF-16, so just emit the replacement + * character. */ if (utf8_codepoint > 0xffff) { utf8_codepoint = UNICODE_REPLACEMENT_CHARACTER; } @@ -2071,10 +2070,10 @@ static int uv_tty_write_bufs(uv_tty_t* handle, utf16_buf[utf16_buf_used++] = L'\r'; utf16_buf[utf16_buf_used++] = L'\n'; } else if (utf8_codepoint == 0x0d && previous_eol == 0x0a) { - /* \n was followed by \r; do not print the \r, since */ - /* the source was either \r\n\r (so the second \r is */ - /* redundant) or was \n\r (so the \n was processed */ - /* by the last case and an \r automatically inserted). */ + /* \n was followed by \r; do not print the \r, since the source was + * either \r\n\r (so the second \r is redundant) or was \n\r (so the + * \n was processed by the last case and an \r automatically + * inserted). */ } else { /* \r without \n; print \r as-is. */ ENSURE_BUFFER_SPACE(1); @@ -2209,7 +2208,7 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { /* TTY shutdown is really just a no-op */ if (handle->stream.conn.shutdown_req->cb) { - if (handle->flags & UV__HANDLE_CLOSING) { + if (handle->flags & UV_HANDLE_CLOSING) { handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, UV_ECANCELED); } else { handle->stream.conn.shutdown_req->cb(handle->stream.conn.shutdown_req, 0); @@ -2222,10 +2221,10 @@ void uv_tty_endgame(uv_loop_t* loop, uv_tty_t* handle) { return; } - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { - /* The wait handle used for raw reading should be unregistered when the */ - /* wait callback runs. */ + /* The wait handle used for raw reading should be unregistered when the + * wait callback runs. */ assert(!(handle->flags & UV_HANDLE_TTY_READABLE) || handle->tty.rd.read_raw_wait == NULL); diff --git a/deps/libuv/src/win/udp.c b/deps/libuv/src/win/udp.c index cd1d0e07b..402aeea66 100644 --- a/deps/libuv/src/win/udp.c +++ b/deps/libuv/src/win/udp.c @@ -74,8 +74,8 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, return GetLastError(); } - /* Associate it with the I/O completion port. */ - /* Use uv_handle_t pointer as completion key. */ + /* Associate it with the I/O completion port. Use uv_handle_t pointer as + * completion key. */ if (CreateIoCompletionPort((HANDLE)socket, loop->iocp, (ULONG_PTR)socket, @@ -83,31 +83,28 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, return GetLastError(); } - if (pSetFileCompletionNotificationModes) { - /* All known Windows that support SetFileCompletionNotificationModes */ - /* have a bug that makes it impossible to use this function in */ - /* conjunction with datagram sockets. We can work around that but only */ - /* if the user is using the default UDP driver (AFD) and has no other */ - /* LSPs stacked on top. Here we check whether that is the case. */ - opt_len = (int) sizeof info; - if (getsockopt(socket, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &info, - &opt_len) == SOCKET_ERROR) { - return GetLastError(); - } + /* All known Windows that support SetFileCompletionNotificationModes have a + * bug that makes it impossible to use this function in conjunction with + * datagram sockets. We can work around that but only if the user is using + * the default UDP driver (AFD) and has no other. LSPs stacked on top. Here + * we check whether that is the case. */ + opt_len = (int) sizeof info; + if (getsockopt( + socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, &opt_len) == + SOCKET_ERROR) { + return GetLastError(); + } - if (info.ProtocolChain.ChainLen == 1) { - if (pSetFileCompletionNotificationModes((HANDLE)socket, - FILE_SKIP_SET_EVENT_ON_HANDLE | - FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { - handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; - handle->func_wsarecv = uv_wsarecv_workaround; - handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; - } else if (GetLastError() != ERROR_INVALID_FUNCTION) { - return GetLastError(); - } + if (info.ProtocolChain.ChainLen == 1) { + if (SetFileCompletionNotificationModes( + (HANDLE) socket, + FILE_SKIP_SET_EVENT_ON_HANDLE | + FILE_SKIP_COMPLETION_PORT_ON_SUCCESS)) { + handle->flags |= UV_HANDLE_SYNC_BYPASS_IOCP; + handle->func_wsarecv = uv_wsarecv_workaround; + handle->func_wsarecvfrom = uv_wsarecvfrom_workaround; + } else if (GetLastError() != ERROR_INVALID_FUNCTION) { + return GetLastError(); } } @@ -191,7 +188,7 @@ void uv_udp_close(uv_loop_t* loop, uv_udp_t* handle) { void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { - if (handle->flags & UV__HANDLE_CLOSING && + if (handle->flags & UV_HANDLE_CLOSING && handle->reqs_pending == 0) { assert(!(handle->flags & UV_HANDLE_CLOSED)); uv__handle_close(handle); @@ -245,12 +242,12 @@ static int uv_udp_maybe_bind(uv_udp_t* handle, handle->flags |= UV_HANDLE_IPV6; if (addr->sa_family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { - /* On windows IPV6ONLY is on by default. */ - /* If the user doesn't specify it libuv turns it off. */ + /* On windows IPV6ONLY is on by default. If the user doesn't specify it + * libuv turns it off. */ - /* TODO: how to handle errors? This may fail if there is no ipv4 stack */ - /* available, or when run on XP/2003 which have no support for dualstack */ - /* sockets. For now we're silently ignoring the error. */ + /* TODO: how to handle errors? This may fail if there is no ipv4 stack + * available, or when run on XP/2003 which have no support for dualstack + * sockets. For now we're silently ignoring the error. */ setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, @@ -386,8 +383,8 @@ int uv__udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, handle->recv_cb = recv_cb; handle->alloc_cb = alloc_cb; - /* If reading was stopped and then started again, there could still be a */ - /* recv request pending. */ + /* If reading was stopped and then started again, there could still be a recv + * request pending. */ if (!(handle->flags & UV_HANDLE_READ_PENDING)) uv_udp_queue_recv(loop, handle); @@ -467,19 +464,19 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, if (!REQ_SUCCESS(req)) { DWORD err = GET_REQ_SOCK_ERROR(req); if (err == WSAEMSGSIZE) { - /* Not a real error, it just indicates that the received packet */ - /* was bigger than the receive buffer. */ + /* Not a real error, it just indicates that the received packet was + * bigger than the receive buffer. */ } else if (err == WSAECONNRESET || err == WSAENETRESET) { - /* A previous sendto operation failed; ignore this error. If */ - /* zero-reading we need to call WSARecv/WSARecvFrom _without_ the */ - /* MSG_PEEK flag to clear out the error queue. For nonzero reads, */ - /* immediately queue a new receive. */ + /* A previous sendto operation failed; ignore this error. If zero-reading + * we need to call WSARecv/WSARecvFrom _without_ the. MSG_PEEK flag to + * clear out the error queue. For nonzero reads, immediately queue a new + * receive. */ if (!(handle->flags & UV_HANDLE_ZERO_READ)) { goto done; } } else { - /* A real error occurred. Report the error to the user only if we're */ - /* currently reading. */ + /* A real error occurred. Report the error to the user only if we're + * currently reading. */ if (handle->flags & UV_HANDLE_READING) { uv_udp_recv_stop(handle); buf = (handle->flags & UV_HANDLE_ZERO_READ) ? @@ -503,8 +500,8 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, struct sockaddr_storage from; int from_len; - /* Do a nonblocking receive */ - /* TODO: try to read multiple datagrams at once. FIONREAD maybe? */ + /* Do a nonblocking receive. + * TODO: try to read multiple datagrams at once. FIONREAD maybe? */ buf = uv_buf_init(NULL, 0); handle->alloc_cb((uv_handle_t*) handle, 65536, &buf); if (buf.base == NULL || buf.len == 0) { @@ -741,7 +738,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) return UV_EINVAL; } - if (!(handle->flags & UV_HANDLE_BOUND)) + if (handle->socket == INVALID_SOCKET) return UV_EBADF; if (addr_st.ss_family == AF_INET) { @@ -772,7 +769,7 @@ int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) int uv_udp_set_broadcast(uv_udp_t* handle, int value) { BOOL optval = (BOOL) value; - if (!(handle->flags & UV_HANDLE_BOUND)) + if (handle->socket == INVALID_SOCKET) return UV_EBADF; if (setsockopt(handle->socket, @@ -818,7 +815,7 @@ int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { return UV_EINVAL; \ } \ \ - if (!(handle->flags & UV_HANDLE_BOUND)) \ + if (handle->socket == INVALID_SOCKET) \ return UV_EBADF; \ \ if (!(handle->flags & UV_HANDLE_IPV6)) { \ diff --git a/deps/libuv/src/win/util.c b/deps/libuv/src/win/util.c index 6b2bc2d72..3e86ff150 100644 --- a/deps/libuv/src/win/util.c +++ b/deps/libuv/src/win/util.c @@ -37,7 +37,7 @@ #include #include #include - +#include /* * Max title length; the only thing MSDN tells us about the maximum length @@ -74,10 +74,6 @@ static char *process_title; static CRITICAL_SECTION process_title_lock; -/* Cached copy of the process id, written once. */ -static DWORD current_pid = 0; - - /* Interval (in seconds) of the high-resolution clock. */ static double hrtime_interval_ = 0; @@ -149,8 +145,8 @@ int uv_exepath(char* buffer, size_t* size_ptr) { uv__free(utf16_buffer); - /* utf8_len *does* include the terminating null at this point, but the */ - /* returned size shouldn't. */ + /* utf8_len *does* include the terminating null at this point, but the + * returned size shouldn't. */ *size_ptr = utf8_len - 1; return 0; @@ -173,16 +169,16 @@ int uv_cwd(char* buffer, size_t* size) { if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); } else if (utf16_len > MAX_PATH) { - /* This should be impossible; however the CRT has a code path to deal */ - /* with this scenario, so I added a check anyway. */ + /* This should be impossible; however the CRT has a code path to deal with + * this scenario, so I added a check anyway. */ return UV_EIO; } /* utf16_len contains the length, *not* including the terminating null. */ utf16_buffer[utf16_len] = L'\0'; - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (utf16_buffer[utf16_len - 1] == L'\\' && !(utf16_len == 3 && utf16_buffer[1] == L':')) { utf16_len--; @@ -239,9 +235,9 @@ int uv_chdir(const char* dir) { utf16_buffer, MAX_PATH) == 0) { DWORD error = GetLastError(); - /* The maximum length of the current working directory is 260 chars, */ - /* including terminating null. If it doesn't fit, the path name must be */ - /* too long. */ + /* The maximum length of the current working directory is 260 chars, + * including terminating null. If it doesn't fit, the path name must be too + * long. */ if (error == ERROR_INSUFFICIENT_BUFFER) { return UV_ENAMETOOLONG; } else { @@ -253,9 +249,9 @@ int uv_chdir(const char* dir) { return uv_translate_sys_error(GetLastError()); } - /* Windows stores the drive-local path in an "hidden" environment variable, */ - /* which has the form "=C:=C:\Windows". SetCurrentDirectory does not */ - /* update this, so we'll have to do it. */ + /* Windows stores the drive-local path in an "hidden" environment variable, + * which has the form "=C:=C:\Windows". SetCurrentDirectory does not update + * this, so we'll have to do it. */ utf16_len = GetCurrentDirectoryW(MAX_PATH, utf16_buffer); if (utf16_len == 0) { return uv_translate_sys_error(GetLastError()); @@ -263,8 +259,8 @@ int uv_chdir(const char* dir) { return UV_EIO; } - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed. */ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (utf16_buffer[utf16_len - 1] == L'\\' && !(utf16_len == 3 && utf16_buffer[1] == L':')) { utf16_len--; @@ -272,8 +268,8 @@ int uv_chdir(const char* dir) { } if (utf16_len < 2 || utf16_buffer[1] != L':') { - /* Doesn't look like a drive letter could be there - probably an UNC */ - /* path. TODO: Need to handle win32 namespaces like \\?\C:\ ? */ + /* Doesn't look like a drive letter could be there - probably an UNC path. + * TODO: Need to handle win32 namespaces like \\?\C:\ ? */ drive_letter = 0; } else if (utf16_buffer[0] >= L'A' && utf16_buffer[0] <= L'Z') { drive_letter = utf16_buffer[0]; @@ -359,14 +355,6 @@ uv_pid_t uv_os_getppid(void) { } -int uv_current_pid(void) { - if (current_pid == 0) { - current_pid = GetCurrentProcessId(); - } - return current_pid; -} - - char** uv_setup_args(int argc, char** argv) { return argv; } @@ -615,7 +603,7 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION* sppi; DWORD sppi_size; SYSTEM_INFO system_info; - DWORD cpu_count, r, i; + DWORD cpu_count, i; NTSTATUS status; ULONG result_size; int err; @@ -670,34 +658,33 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos_ptr, int* cpu_count_ptr) { assert(len > 0 && len < ARRAY_SIZE(key_name)); - r = RegOpenKeyExW(HKEY_LOCAL_MACHINE, - key_name, - 0, - KEY_QUERY_VALUE, - &processor_key); - if (r != ERROR_SUCCESS) { - err = GetLastError(); + err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, + key_name, + 0, + KEY_QUERY_VALUE, + &processor_key); + if (err != ERROR_SUCCESS) { goto error; } - if (RegQueryValueExW(processor_key, - L"~MHz", - NULL, - NULL, - (BYTE*) &cpu_speed, - &cpu_speed_size) != ERROR_SUCCESS) { - err = GetLastError(); + err = RegQueryValueExW(processor_key, + L"~MHz", + NULL, + NULL, + (BYTE*)&cpu_speed, + &cpu_speed_size); + if (err != ERROR_SUCCESS) { RegCloseKey(processor_key); goto error; } - if (RegQueryValueExW(processor_key, - L"ProcessorNameString", - NULL, - NULL, - (BYTE*) &cpu_brand, - &cpu_brand_size) != ERROR_SUCCESS) { - err = GetLastError(); + err = RegQueryValueExW(processor_key, + L"ProcessorNameString", + NULL, + NULL, + (BYTE*)&cpu_brand, + &cpu_brand_size); + if (err != ERROR_SUCCESS) { RegCloseKey(processor_key); goto error; } @@ -843,17 +830,17 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, } - /* Fetch the size of the adapters reported by windows, and then get the */ - /* list itself. */ + /* Fetch the size of the adapters reported by windows, and then get the list + * itself. */ win_address_buf_size = 0; win_address_buf = NULL; for (;;) { ULONG r; - /* If win_address_buf is 0, then GetAdaptersAddresses will fail with */ - /* ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in */ - /* win_address_buf_size. */ + /* If win_address_buf is 0, then GetAdaptersAddresses will fail with. + * ERROR_BUFFER_OVERFLOW, and the required buffer size will be stored in + * win_address_buf_size. */ r = GetAdaptersAddresses(AF_UNSPEC, flags, NULL, @@ -867,8 +854,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, switch (r) { case ERROR_BUFFER_OVERFLOW: - /* This happens when win_address_buf is NULL or too small to hold */ - /* all adapters. */ + /* This happens when win_address_buf is NULL or too small to hold all + * adapters. */ win_address_buf = uv__malloc(win_address_buf_size); if (win_address_buf == NULL) return UV_ENOMEM; @@ -902,15 +889,15 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return UV_ENOBUFS; default: - /* Other (unspecified) errors can happen, but we don't have any */ - /* special meaning for them. */ + /* Other (unspecified) errors can happen, but we don't have any special + * meaning for them. */ assert(r != ERROR_SUCCESS); return uv_translate_sys_error(r); } } - /* Count the number of enabled interfaces and compute how much space is */ - /* needed to store their info. */ + /* Count the number of enabled interfaces and compute how much space is + * needed to store their info. */ count = 0; uv_address_buf_size = 0; @@ -920,9 +907,9 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, IP_ADAPTER_UNICAST_ADDRESS* unicast_address; int name_size; - /* Interfaces that are not 'up' should not be reported. Also skip */ - /* interfaces that have no associated unicast address, as to avoid */ - /* allocating space for the name for this interface. */ + /* Interfaces that are not 'up' should not be reported. Also skip + * interfaces that have no associated unicast address, as to avoid + * allocating space for the name for this interface. */ if (adapter->OperStatus != IfOperStatusUp || adapter->FirstUnicastAddress == NULL) continue; @@ -942,8 +929,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, } uv_address_buf_size += name_size; - /* Count the number of addresses associated with this interface, and */ - /* compute the size. */ + /* Count the number of addresses associated with this interface, and + * compute the size. */ for (unicast_address = (IP_ADAPTER_UNICAST_ADDRESS*) adapter->FirstUnicastAddress; unicast_address != NULL; @@ -960,8 +947,8 @@ int uv_interface_addresses(uv_interface_address_t** addresses_ptr, return UV_ENOMEM; } - /* Compute the start of the uv_interface_address_t array, and the place in */ - /* the buffer where the interface names will be stored. */ + /* Compute the start of the uv_interface_address_t array, and the place in + * the buffer where the interface names will be stored. */ uv_address = uv_address_buf; name_buf = (char*) (uv_address_buf + count); @@ -1200,8 +1187,8 @@ int uv_os_tmpdir(char* buffer, size_t* size) { return UV_EIO; } - /* The returned directory should not have a trailing slash, unless it */ - /* points at a drive root, like c:\. Remove it if needed.*/ + /* The returned directory should not have a trailing slash, unless it points + * at a drive root, like c:\. Remove it if needed. */ if (path[len - 1] == L'\\' && !(len == 3 && path[1] == L':')) { len--; diff --git a/deps/libuv/src/win/winapi.c b/deps/libuv/src/win/winapi.c index 4ccdf0a5f..0fd598eac 100644 --- a/deps/libuv/src/win/winapi.c +++ b/deps/libuv/src/win/winapi.c @@ -34,21 +34,6 @@ sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; sNtQueryDirectoryFile pNtQueryDirectoryFile; sNtQuerySystemInformation pNtQuerySystemInformation; - -/* Kernel32 function pointers */ -sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -sCreateSymbolicLinkW pCreateSymbolicLinkW; -sCancelIoEx pCancelIoEx; -sInitializeConditionVariable pInitializeConditionVariable; -sSleepConditionVariableCS pSleepConditionVariableCS; -sSleepConditionVariableSRW pSleepConditionVariableSRW; -sWakeAllConditionVariable pWakeAllConditionVariable; -sWakeConditionVariable pWakeConditionVariable; -sCancelSynchronousIo pCancelSynchronousIo; -sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - - /* Powrprof.dll function pointer */ sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; @@ -58,7 +43,6 @@ sSetWinEventHook pSetWinEventHook; void uv_winapi_init(void) { HMODULE ntdll_module; - HMODULE kernel32_module; HMODULE powrprof_module; HMODULE user32_module; @@ -114,46 +98,6 @@ void uv_winapi_init(void) { uv_fatal_error(GetLastError(), "GetProcAddress"); } - kernel32_module = GetModuleHandleA("kernel32.dll"); - if (kernel32_module == NULL) { - uv_fatal_error(GetLastError(), "GetModuleHandleA"); - } - - pGetQueuedCompletionStatusEx = (sGetQueuedCompletionStatusEx) GetProcAddress( - kernel32_module, - "GetQueuedCompletionStatusEx"); - - pSetFileCompletionNotificationModes = (sSetFileCompletionNotificationModes) - GetProcAddress(kernel32_module, "SetFileCompletionNotificationModes"); - - pCreateSymbolicLinkW = (sCreateSymbolicLinkW) - GetProcAddress(kernel32_module, "CreateSymbolicLinkW"); - - pCancelIoEx = (sCancelIoEx) - GetProcAddress(kernel32_module, "CancelIoEx"); - - pInitializeConditionVariable = (sInitializeConditionVariable) - GetProcAddress(kernel32_module, "InitializeConditionVariable"); - - pSleepConditionVariableCS = (sSleepConditionVariableCS) - GetProcAddress(kernel32_module, "SleepConditionVariableCS"); - - pSleepConditionVariableSRW = (sSleepConditionVariableSRW) - GetProcAddress(kernel32_module, "SleepConditionVariableSRW"); - - pWakeAllConditionVariable = (sWakeAllConditionVariable) - GetProcAddress(kernel32_module, "WakeAllConditionVariable"); - - pWakeConditionVariable = (sWakeConditionVariable) - GetProcAddress(kernel32_module, "WakeConditionVariable"); - - pCancelSynchronousIo = (sCancelSynchronousIo) - GetProcAddress(kernel32_module, "CancelSynchronousIo"); - - pGetFinalPathNameByHandleW = (sGetFinalPathNameByHandleW) - GetProcAddress(kernel32_module, "GetFinalPathNameByHandleW"); - - powrprof_module = LoadLibraryA("powrprof.dll"); if (powrprof_module != NULL) { pPowerRegisterSuspendResumeNotification = (sPowerRegisterSuspendResumeNotification) diff --git a/deps/libuv/src/win/winapi.h b/deps/libuv/src/win/winapi.h index cc54b79b0..d0fcfd8e7 100644 --- a/deps/libuv/src/win/winapi.h +++ b/deps/libuv/src/win/winapi.h @@ -4076,8 +4076,8 @@ # define STATUS_HASH_NOT_PRESENT ((NTSTATUS) 0xC000A101L) #endif -/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the */ -/* DDK got it wrong! */ +/* This is not the NTSTATUS_FROM_WIN32 that the DDK provides, because the DDK + * got it wrong! */ #ifdef NTSTATUS_FROM_WIN32 # undef NTSTATUS_FROM_WIN32 #endif @@ -4642,56 +4642,6 @@ typedef NTSTATUS (NTAPI *sNtQueryDirectoryFile) # define ERROR_MUI_FILE_NOT_LOADED 15105 #endif -typedef BOOL (WINAPI *sGetQueuedCompletionStatusEx) - (HANDLE CompletionPort, - LPOVERLAPPED_ENTRY lpCompletionPortEntries, - ULONG ulCount, - PULONG ulNumEntriesRemoved, - DWORD dwMilliseconds, - BOOL fAlertable); - -typedef BOOL (WINAPI* sSetFileCompletionNotificationModes) - (HANDLE FileHandle, - UCHAR Flags); - -typedef BOOLEAN (WINAPI* sCreateSymbolicLinkW) - (LPCWSTR lpSymlinkFileName, - LPCWSTR lpTargetFileName, - DWORD dwFlags); - -typedef BOOL (WINAPI* sCancelIoEx) - (HANDLE hFile, - LPOVERLAPPED lpOverlapped); - -typedef VOID (WINAPI* sInitializeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sSleepConditionVariableCS) - (PCONDITION_VARIABLE ConditionVariable, - PCRITICAL_SECTION CriticalSection, - DWORD dwMilliseconds); - -typedef BOOL (WINAPI* sSleepConditionVariableSRW) - (PCONDITION_VARIABLE ConditionVariable, - PSRWLOCK SRWLock, - DWORD dwMilliseconds, - ULONG Flags); - -typedef VOID (WINAPI* sWakeAllConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef VOID (WINAPI* sWakeConditionVariable) - (PCONDITION_VARIABLE ConditionVariable); - -typedef BOOL (WINAPI* sCancelSynchronousIo) - (HANDLE hThread); - -typedef DWORD (WINAPI* sGetFinalPathNameByHandleW) - (HANDLE hFile, - LPWSTR lpszFilePath, - DWORD cchFilePath, - DWORD dwFlags); - /* from powerbase.h */ #ifndef DEVICE_NOTIFY_CALLBACK # define DEVICE_NOTIFY_CALLBACK 2 @@ -4754,21 +4704,6 @@ extern sNtQueryVolumeInformationFile pNtQueryVolumeInformationFile; extern sNtQueryDirectoryFile pNtQueryDirectoryFile; extern sNtQuerySystemInformation pNtQuerySystemInformation; - -/* Kernel32 function pointers */ -extern sGetQueuedCompletionStatusEx pGetQueuedCompletionStatusEx; -extern sSetFileCompletionNotificationModes pSetFileCompletionNotificationModes; -extern sCreateSymbolicLinkW pCreateSymbolicLinkW; -extern sCancelIoEx pCancelIoEx; -extern sInitializeConditionVariable pInitializeConditionVariable; -extern sSleepConditionVariableCS pSleepConditionVariableCS; -extern sSleepConditionVariableSRW pSleepConditionVariableSRW; -extern sWakeAllConditionVariable pWakeAllConditionVariable; -extern sWakeConditionVariable pWakeConditionVariable; -extern sCancelSynchronousIo pCancelSynchronousIo; -extern sGetFinalPathNameByHandleW pGetFinalPathNameByHandleW; - - /* Powrprof.dll function pointer */ extern sPowerRegisterSuspendResumeNotification pPowerRegisterSuspendResumeNotification; diff --git a/deps/libuv/src/win/winsock.c b/deps/libuv/src/win/winsock.c index 84188954d..5e7da2a8f 100644 --- a/deps/libuv/src/win/winsock.c +++ b/deps/libuv/src/win/winsock.c @@ -256,8 +256,8 @@ int uv_ntstatus_to_winsock_error(NTSTATUS status) { default: if ((status & (FACILITY_NTWIN32 << 16)) == (FACILITY_NTWIN32 << 16) && (status & (ERROR_SEVERITY_ERROR | ERROR_SEVERITY_WARNING))) { - /* It's a windows error that has been previously mapped to an */ - /* ntstatus code. */ + /* It's a windows error that has been previously mapped to an ntstatus + * code. */ return (DWORD) (status & 0xffff); } else { /* The default fallback for unmappable ntstatus codes. */ @@ -519,8 +519,8 @@ int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info_in, sizeof *info_out); if (overlapped == NULL) { - /* If this is a blocking operation, wait for the event to become */ - /* signaled, and then grab the real status from the io status block. */ + /* If this is a blocking operation, wait for the event to become signaled, + * and then grab the real status from the io status block. */ if (status == STATUS_PENDING) { DWORD r = WaitForSingleObject(event, INFINITE); diff --git a/deps/libuv/uv.gyp b/deps/libuv/uv.gyp index e41f9ff5d..37dcb3604 100644 --- a/deps/libuv/uv.gyp +++ b/deps/libuv/uv.gyp @@ -64,15 +64,16 @@ 'sources': [ 'common.gypi', 'include/uv.h', - 'include/tree.h', - 'include/uv-errno.h', - 'include/uv-threadpool.h', - 'include/uv-version.h', + 'include/uv/tree.h', + 'include/uv/errno.h', + 'include/uv/threadpool.h', + 'include/uv/version.h', 'src/fs-poll.c', 'src/heap-inl.h', 'src/inet.c', 'src/queue.h', 'src/threadpool.c', + 'src/timer.c', 'src/uv-data-getter-setters.c', 'src/uv-common.c', 'src/uv-common.h', @@ -95,7 +96,7 @@ '_GNU_SOURCE', ], 'sources': [ - 'include/uv-win.h', + 'include/uv/win.h', 'src/win/async.c', 'src/win/atomicops-inl.h', 'src/win/core.c', @@ -123,7 +124,6 @@ 'src/win/stream-inl.h', 'src/win/tcp.c', 'src/win/tty.c', - 'src/win/timer.c', 'src/win/udp.c', 'src/win/util.c', 'src/win/winapi.c', @@ -144,12 +144,12 @@ }, }, { # Not Windows i.e. POSIX 'sources': [ - 'include/uv-unix.h', - 'include/uv-linux.h', - 'include/uv-sunos.h', - 'include/uv-darwin.h', - 'include/uv-bsd.h', - 'include/uv-aix.h', + 'include/uv/unix.h', + 'include/uv/linux.h', + 'include/uv/sunos.h', + 'include/uv/darwin.h', + 'include/uv/bsd.h', + 'include/uv/aix.h', 'src/unix/async.c', 'src/unix/atomic-ops.h', 'src/unix/core.c', @@ -168,7 +168,6 @@ 'src/unix/stream.c', 'src/unix/tcp.c', 'src/unix/thread.c', - 'src/unix/timer.c', 'src/unix/tty.c', 'src/unix/udp.c', ], @@ -199,7 +198,7 @@ ['uv_library=="shared_library" and OS!="mac" and OS!="zos"', { # This will cause gyp to set soname # Must correspond with UV_VERSION_MAJOR - # in include/uv-version.h + # in include/uv/version.h 'product_extension': 'so.1', }], ], diff --git a/src/gevent/libuv/_corecffi_build.py b/src/gevent/libuv/_corecffi_build.py index f6d28971c..722157db0 100644 --- a/src/gevent/libuv/_corecffi_build.py +++ b/src/gevent/libuv/_corecffi_build.py @@ -81,6 +81,7 @@ def _libuv_source(rel_path): _libuv_source('uv-common.c'), _libuv_source('version.c'), _libuv_source('uv-data-getter-setters.c'), + _libuv_source('timer.c'), ] if WIN: @@ -116,7 +117,6 @@ def _libuv_source(rel_path): _libuv_source('win/stream.c'), _libuv_source('win/tcp.c'), _libuv_source('win/thread.c'), - _libuv_source('win/timer.c'), _libuv_source('win/tty.c'), _libuv_source('win/udp.c'), _libuv_source('win/util.c'), @@ -140,7 +140,6 @@ def _libuv_source(rel_path): _libuv_source('unix/stream.c'), _libuv_source('unix/tcp.c'), _libuv_source('unix/thread.c'), - _libuv_source('unix/timer.c'), _libuv_source('unix/tty.c'), _libuv_source('unix/udp.c'), ] @@ -211,6 +210,8 @@ def _add_library(name): if sys.platform.startswith('linux'): _add_library('dl') _add_library('rt') + _define_macro('_GNU_SOURCE', 1) + _define_macro('_POSIX_C_SOURCE', '200112') elif sys.platform == 'darwin': _define_macro('_DARWIN_USE_64_BIT_INODE', 1) _define_macro('_DARWIN_UNLIMITED_SELECT', 1) @@ -230,6 +231,7 @@ def _add_library(name): _define_macro('_CRT_NONSTDC_NO_DEPRECATE', 1) _define_macro('_CRT_SECURE_NO_WARNINGS', 1) _define_macro('_WIN32_WINNT', '0x0600') + _define_macro('WIN32_LEAN_AND_MEAN', 1) _add_library('advapi32') _add_library('iphlpapi') _add_library('psapi') diff --git a/src/gevent/libuv/loop.py b/src/gevent/libuv/loop.py index 323ab62a0..0f317c00b 100644 --- a/src/gevent/libuv/loop.py +++ b/src/gevent/libuv/loop.py @@ -151,8 +151,9 @@ def _init_and_start_check(self): self._signal_idle = ffi.new("uv_timer_t*") libuv.uv_timer_init(self._ptr, self._signal_idle) self._signal_idle.data = self._handle_to_self + sig_cb = ffi.cast('void(*)(uv_timer_t*)', libuv.python_check_callback) libuv.uv_timer_start(self._signal_idle, - ffi.cast('void(*)(uv_timer_t*)', libuv.python_check_callback), + sig_cb, 300, 300) libuv.uv_unref(self._signal_idle)