From a35a212f258812bd178f7f002660a0ddc0bf10b2 Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Tue, 29 Oct 2013 16:33:17 -0700 Subject: [PATCH] uv: Upgrade to v0.11.14 --- deps/uv/.gitignore | 4 +- deps/uv/.mailmap | 1 + deps/uv/AUTHORS | 5 + deps/uv/ChangeLog | 171 +++++++++++++++++++++++++++++- deps/uv/Makefile.am | 21 +++- deps/uv/README.md | 67 +++++++----- deps/uv/common.gypi | 1 - deps/uv/configure.ac | 2 +- deps/uv/include/uv-errno.h | 112 ++++++++++--------- deps/uv/include/uv-unix.h | 6 +- deps/uv/include/uv.h | 75 +++++++++---- deps/uv/src/unix/aix.c | 36 ++++--- deps/uv/src/unix/async.c | 4 +- deps/uv/src/unix/atomic-ops.h | 60 +++++++++++ deps/uv/src/unix/core.c | 26 ++++- deps/uv/src/unix/darwin-proctitle.c | 54 ++++++++-- deps/uv/src/unix/freebsd.c | 4 +- deps/uv/src/unix/fsevents.c | 15 ++- deps/uv/src/unix/internal.h | 1 + deps/uv/src/unix/kqueue.c | 41 ++++--- deps/uv/src/unix/linux-core.c | 5 +- deps/uv/src/unix/linux-inotify.c | 43 +++++--- deps/uv/src/unix/loop.c | 4 +- deps/uv/src/unix/pipe.c | 32 +----- deps/uv/src/unix/process.c | 129 ++++++++++++---------- deps/uv/src/unix/signal.c | 13 ++- deps/uv/src/unix/spinlock.h | 53 +++++++++ deps/uv/src/unix/stream.c | 39 ++++--- deps/uv/src/unix/sunos.c | 95 +++++++++++------ deps/uv/src/unix/tcp.c | 2 +- deps/uv/src/unix/tty.c | 55 +++++----- deps/uv/src/unix/udp.c | 9 +- deps/uv/src/version.c | 2 +- deps/uv/src/win/core.c | 7 +- deps/uv/src/win/error.c | 2 + deps/uv/src/win/fs-event.c | 146 ++++++++++++++----------- deps/uv/src/win/fs.c | 77 +++++++++----- deps/uv/src/win/handle.c | 3 +- deps/uv/src/win/pipe.c | 2 +- deps/uv/src/win/stream.c | 4 - deps/uv/src/win/thread.c | 1 + deps/uv/src/win/tty.c | 5 +- deps/uv/src/win/udp.c | 3 +- deps/uv/src/win/winsock.c | 20 ++-- deps/uv/test/benchmark-async.c | 4 +- deps/uv/test/benchmark-million-timers.c | 20 ++-- deps/uv/test/benchmark-ping-pongs.c | 4 +- deps/uv/test/benchmark-pound.c | 33 +++++- deps/uv/test/benchmark-pump.c | 22 ++-- deps/uv/test/benchmark-udp-pummel.c | 2 +- deps/uv/test/dns-server.c | 12 ++- deps/uv/test/runner-win.c | 17 ++- deps/uv/test/runner.c | 3 +- deps/uv/test/task.h | 2 +- deps/uv/test/test-active.c | 21 ++-- deps/uv/test/test-close-order.c | 80 ++++++++++++++ deps/uv/test/test-fs-event.c | 92 ++++++++++++---- deps/uv/test/test-fs-poll.c | 2 +- deps/uv/test/test-fs.c | 21 +++- deps/uv/test/test-get-currentexe.c | 4 +- deps/uv/test/test-ipc-send-recv.c | 6 +- deps/uv/test/test-ipc.c | 12 +-- deps/uv/test/test-list.h | 4 + deps/uv/test/test-loop-stop.c | 2 +- deps/uv/test/test-ping-pong.c | 12 ++- deps/uv/test/test-poll.c | 6 +- deps/uv/test/test-ref.c | 3 +- deps/uv/test/test-shutdown-close.c | 4 +- deps/uv/test/test-signal-multiple-loops.c | 57 ++++++---- deps/uv/test/test-spawn.c | 34 ++++-- deps/uv/test/test-stdio-over-pipes.c | 1 - deps/uv/test/test-tcp-bind-error.c | 3 +- deps/uv/test/test-tcp-bind6-error.c | 3 +- deps/uv/test/test-timer-again.c | 5 +- deps/uv/test/test-timer.c | 8 +- deps/uv/test/test-tty.c | 8 +- deps/uv/test/test-udp-send-and-recv.c | 2 +- deps/uv/uv.gyp | 3 + 78 files changed, 1389 insertions(+), 580 deletions(-) create mode 100644 deps/uv/src/unix/atomic-ops.h create mode 100644 deps/uv/src/unix/spinlock.h create mode 100644 deps/uv/test/test-close-order.c diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index ff74c1d..506f04a 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -8,8 +8,8 @@ core vgcore.* .buildstamp - -/.deps/ +.dirstamp +.deps/ /.libs/ /aclocal.m4 /ar-lib diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap index 2d5606f..a2cf836 100644 --- a/deps/uv/.mailmap +++ b/deps/uv/.mailmap @@ -6,6 +6,7 @@ Brian White Brian White Frank Denis Isaac Z. Schlueter +Keno Fischer Keno Fischer Robert Mustacchi Ryan Dahl diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index 1d99256..4d56a3b 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -92,3 +92,8 @@ Andrei Sedoi Navaneeth Kedaram Nambiathan Alex Crichton Brent Cook +Brian Kaisner +Luca Bruno +Reini Urban +Maks Naumov +Sean Farrell diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 15105f4..ef3cfd3 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,152 @@ -2013.09.05, Version 0.11.13 (Unstable) +2013.10.30, Version 0.11.14 (Unstable) + +Changes since version 0.11.13: + +* darwin: create fsevents thread on demand (Ben Noordhuis) + +* fsevents: FSEvents is most likely not thread-safe (Fedor Indutny) + +* fsevents: use shared FSEventStream (Fedor Indutny) + +* windows: make uv_fs_chmod() report errors correctly (Bert Belder) + +* windows: make uv_shutdown() for write-only pipes work (Bert Belder) + +* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) + +* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) + +* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) + +* windows/fs: wrap multi-statement macros in do..while block (Bert Belder) + +* windows/fs: make uv_fs_open() report EINVAL correctly (Bert Belder) + +* windows/fs: handle _open_osfhandle() failure correctly (Bert Belder) + +* build: clarify instructions for Windows (Brian Kaisner) + +* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) + +* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) + +* windows: run close callbacks after polling for i/o (Saúl Ibarra Corretgé) + +* include: clarify uv_tcp_bind() behavior (Ben Noordhuis) + +* include: clean up includes in uv.h (Ben Noordhuis) + +* include: remove UV_IO_PRIVATE_FIELDS macro (Ben Noordhuis) + +* include: fix typo in comment in uv.h (Ben Noordhuis) + +* include: update uv_is_active() documentation (Ben Noordhuis) + +* include: make uv_process_options_t.cwd const (Ben Noordhuis) + +* unix: wrap long lines at 80 columns (Ben Noordhuis) + +* unix, windows: make uv_is_*() always return 0 or 1 (Ben Noordhuis) + +* bench: measure total/init/dispatch/cleanup times (Ben Noordhuis) + +* build: use -pthread on sunos (Timothy J. Fontaine) + +* windows: remove duplicate check in stream.c (Ben Noordhuis) + +* unix: sanity-check fds before closing (Ben Noordhuis) + +* unix: remove uv__pipe_accept() (Ben Noordhuis) + +* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) + +* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) + +* unix: revert recent FSEvent changes (Ben Noordhuis) + +* fsevents: fix clever rescheduling (Fedor Indutny) + +* linux: ignore fractional time in uv_uptime() (Ben Noordhuis) + +* unix: fix SIGCHLD waitpid() race in process.c (Ben Noordhuis) + +* unix, windows: add uv_fs_event_start/stop functions (Saúl Ibarra Corretgé) + +* unix: fix non-synchronized access in signal.c (Ben Noordhuis) + +* unix: add atomic-ops.h (Ben Noordhuis) + +* unix: add spinlock.h (Ben Noordhuis) + +* unix: clean up uv_tty_set_mode() a little (Ben Noordhuis) + +* unix: make uv_tty_reset_mode() async signal-safe (Ben Noordhuis) + +* include: add E2BIG status code mapping (Ben Noordhuis) + +* windows: fix duplicate case build error (Ben Noordhuis) + +* windows: remove unneeded check (Saúl Ibarra Corretgé) + +* include: document pipe path truncation behavior (Ben Noordhuis) + +* fsevents: increase stack size for OSX 10.9 (Fedor Indutny) + +* windows: _snprintf expected wrong parameter type in string (Maks Naumov) + +* windows: "else" keyword is missing (Maks Naumov) + +* windows: incorrect check for SOCKET_ERROR (Maks Naumov) + +* windows: add stdlib.h to satisfy reference to abort (Sean Farrell) + +* build: fix check target for mingw (Sean Farrell) + +* unix: move uv_shutdown() assertion (Keno Fischer) + +* darwin: avoid calling GetCurrentProcess (Fedor Indutny) + + +2013.10.19, Version 0.10.18 (Stable), 9ec52963b585e822e87bdc5de28d6143aff0d2e5 + +Changes since version 0.10.17: + +* unix: fix uv_spawn() NULL pointer deref on ENOMEM (Ben Noordhuis) + +* unix: don't close inherited fds on uv_spawn() fail (Ben Noordhuis) + +* unix: revert recent FSEvent changes (Ben Noordhuis) + +* unix: fix non-synchronized access in signal.c (Ben Noordhuis) + + +2013.09.25, Version 0.10.17 (Stable), 9670e0a93540c2f0d86c84a375f2303383c11e7e + +Changes since version 0.10.16: + +* build: remove GCC_WARN_ABOUT_MISSING_NEWLINE (Ben Noordhuis) + +* darwin: fix 10.6 build error in fsevents.c (Ben Noordhuis) + + +2013.09.06, Version 0.10.16 (Stable), 2bce230d81f4853a23662cbeb26fe98010b1084b + +Changes since version 0.10.15: + +* windows: make uv_shutdown() for write-only pipes work (Bert Belder) + +* windows: make uv_fs_open() report EINVAL when invalid arguments are passed + (Bert Belder) + +* windows: make uv_fs_open() report _open_osfhandle() failure correctly (Bert + Belder) + +* windows: make uv_fs_chmod() report errors correctly (Bert Belder) + +* windows: wrap multi-statement macros in do..while block (Bert Belder) + + +2013.09.05, Version 0.11.13 (Unstable), f5b6db6c1d7f93d28281207fd47c3841c9a9792e Changes since version 0.11.12: @@ -113,6 +261,20 @@ Changes since version 0.11.8: par with libuv's behavior on unix. (Bert Belder) +2013.08.24, Version 0.10.15 (Stable), 221078a8fdd9b853c6b557b3d9a5dd744b4fdd6b + +Changes since version 0.10.14: + +* fsevents: create FSEvents thread on demand (Ben Noordhuis) + +* fsevents: use a single thread for interacting with FSEvents, because it's not + thread-safe. (Fedor Indutny) + +* fsevents: share FSEventStream between multiple FS watchers, which removes a + limit on the maximum number of file watchers that can be created on OS X. + (Fedor Indutny) + + 2013.08.22, Version 0.11.8 (Unstable), a5260462db80ab0deab6b9e6a8991dd8f5a9a2f8 Changes since version 0.11.7: @@ -164,6 +326,13 @@ Changes since version 0.11.7: * windows: omit stdint.h, fix msvc 2008 build error (Ben Noordhuis) +2013.08.22, Version 0.10.14 (Stable), 15d64132151c18b26346afa892444b95e2addad0 + +Changes since version 0.10.13: + +* unix: retry waitpid() on EINTR (Ben Noordhuis) + + 2013.08.07, Version 0.11.7 (Unstable), 3cad361f8776f70941b39d65bd9426bcb1aa817b Changes since version 0.11.6: diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am index bd54e45..9080b94 100644 --- a/deps/uv/Makefile.am +++ b/deps/uv/Makefile.am @@ -31,13 +31,17 @@ libuv_la_SOURCES = src/fs-poll.c \ src/uv-common.h \ src/version.c +if SUNOS +libuv_la_CFLAGS += -pthread +endif + if WINNT include_HEADERS += include/uv-win.h include/tree.h AM_CPPFLAGS += -I$(top_srcdir)/src/win \ -DWIN32_LEAN_AND_MEAN \ -D_WIN32_WINNT=0x0600 -LIBS += -lws2_32 -lpsapi -lphlpapi2 +LIBS += -lws2_32 -lpsapi -liphlpapi -lshell32 libuv_la_SOURCES += src/win/async.c \ src/win/atomicops-inl.h \ src/win/core.c \ @@ -76,6 +80,7 @@ else # WINNT include_HEADERS += include/uv-unix.h AM_CPPFLAGS += -I$(top_srcdir)/src/unix libuv_la_SOURCES += src/unix/async.c \ + src/unix/atomic-ops.h \ src/unix/core.c \ src/unix/dl.c \ src/unix/fs.c \ @@ -87,6 +92,7 @@ libuv_la_SOURCES += src/unix/async.c \ src/unix/poll.c \ src/unix/process.c \ src/unix/signal.c \ + src/unix/spinlock.h \ src/unix/stream.c \ src/unix/tcp.c \ src/unix/thread.c \ @@ -103,8 +109,6 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ test/echo-server.c \ test/run-tests.c \ - test/runner-unix.c \ - test/runner-unix.h \ test/runner.c \ test/runner.h \ test/task.h \ @@ -114,6 +118,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-barrier.c \ test/test-callback-order.c \ test/test-callback-stack.c \ + test/test-close-order.c \ test/test-condvar.c \ test/test-connection-fail.c \ test/test-cwd-and-chdir.c \ @@ -192,6 +197,16 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-walk-handles.c test_run_tests_LDADD = libuv.la +if WINNT +test_run_tests_SOURCES += test/runner-win.c \ + test/runner-win.h +else +test_run_tests_SOURCES += test/runner-unix.c \ + test/runner-unix.h +endif + + + if AIX libuv_la_CFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 libuv_la_SOURCES += src/unix/aix.c diff --git a/deps/uv/README.md b/deps/uv/README.md index e485710..aab9e80 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -1,37 +1,37 @@ # libuv -libuv is a platform layer for [node.js][]. Its purpose is to abstract IOCP -on Windows and epoll/kqueue/event ports/etc. on Unix systems. We intend to -eventually contain all platform differences in this library. +libuv is a multi-platform support library with a focus on asynchronous I/O. It +was primarily developed for use by [Node.js](http://node.js.org), but it's also +used by Mozilla's [Rust language](http://www.rust-lang.org/), +[Luvit](http://luvit.io/), [Julia](http://julialang.org/), +[pyuv](https://crate.io/packages/pyuv/), and others. -## Features +## Feature highlights - * Non-blocking TCP sockets + * Full-featured event loop backed by epoll, kqueue, IOCP, event ports. - * Non-blocking named pipes + * Asynchronous TCP and UDP sockets - * UDP + * Asynchronous DNS resolution - * Timers + * Asynchronous file and file system operations - * Child process spawning + * File system events - * Asynchronous DNS via `uv_getaddrinfo`. + * ANSI escape code controlled TTY - * Asynchronous file system APIs `uv_fs_*` + * IPC with socket sharing, using Unix domain sockets or named pipes (Windows) - * High resolution time `uv_hrtime` + * Child processes - * Current executable path look up `uv_exepath` + * Thread pool - * Thread pool scheduling `uv_queue_work` + * Signal handling - * ANSI escape code controlled TTY `uv_tty_t` + * High resolution clock - * File system events using inotify, kqueue, event ports, - FSEvents and `ReadDirectoryChangesW` + * Threading and synchronization primitives - * IPC and socket sharing between processes `uv_write2` ## Community @@ -62,31 +62,40 @@ To build with autotools: $ make check $ make install -To build with Visual Studio run the vcbuild.bat file which will -checkout the GYP code into build/gyp and generate the uv.sln and -related files. +### Windows -Windows users can also build from the command line using msbuild. -This is done by running vcbuild.bat from Visual Studio command prompt. +First, Python 2.6 or 2.7 must be installed as it is required by [GYP][]. -To have GYP generate build script for another system, make sure that -you have Python 2.6 or 2.7 installed, then checkout GYP into the +Also, the directory for the preferred Python executable must be specified +by the `PYTHON` or `Path` environment variables. + +To build with Visual Studio, launch a git shell (e.g. Cmd or PowerShell) +and run vcbuild.bat which will checkout the GYP code into build/gyp and +generate uv.sln as well as related project files. + +To have GYP generate build script for another system, checkout GYP into the project tree manually: $ mkdir -p build $ git clone https://git.chromium.org/external/gyp.git build/gyp -Unix users run: +### Unix + +Run: $ ./gyp_uv -f make $ make -C out -Macintosh users run: +### OS X + +Run: $ ./gyp_uv -f xcode $ xcodebuild -project uv.xcodeproj -configuration Release -target All -To build for android: +### Android + +Run: $ source ./android-configure NDK_PATH gyp $ make -C out @@ -103,7 +112,7 @@ Studio license. Linux using the GCC toolchain. -MacOS using the GCC or XCode toolchain. +OS X using the GCC or XCode toolchain. Solaris 121 and later using GCC toolchain. diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi index df7da88..7adbbbd 100644 --- a/deps/uv/common.gypi +++ b/deps/uv/common.gypi @@ -172,7 +172,6 @@ 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics - 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof 'PREBINDING': 'NO', # No -Wl,-prebind 'USE_HEADERMAP': 'NO', 'OTHER_CFLAGS': [ diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac index 0c97737..ede6c6f 100644 --- a/deps/uv/configure.ac +++ b/deps/uv/configure.ac @@ -13,7 +13,7 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. AC_PREREQ(2.57) -AC_INIT([libuv], [0.11.13], [https://github.com/joyent/libuv/issues]) +AC_INIT([libuv], [0.11.14], [https://github.com/joyent/libuv/issues]) AC_CONFIG_MACRO_DIR([m4]) m4_include([m4/libuv-extra-automake-flags.m4]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects] UV_EXTRA_AUTOMAKE_FLAGS) diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h index 2b12917..ce895b7 100644 --- a/deps/uv/include/uv-errno.h +++ b/deps/uv/include/uv-errno.h @@ -44,322 +44,328 @@ /* Only map to the system errno on non-Windows platforms. It's apparently * a fairly common practice for Windows programmers to redefine errno codes. */ +#if defined(E2BIG) && !defined(_WIN32) +# define UV__E2BIG (-E2BIG) +#else +# define UV__E2BIG (-4093) +#endif + #if defined(EACCES) && !defined(_WIN32) # define UV__EACCES (-EACCES) #else -# define UV__EACCES (-4093) +# define UV__EACCES (-4092) #endif #if defined(EADDRINFO) && !defined(_WIN32) # define UV__EADDRINFO EADDRINFO #else -# define UV__EADDRINFO (-4092) +# define UV__EADDRINFO (-4091) #endif #if defined(EADDRINUSE) && !defined(_WIN32) # define UV__EADDRINUSE (-EADDRINUSE) #else -# define UV__EADDRINUSE (-4092) +# define UV__EADDRINUSE (-4091) #endif #if defined(EADDRNOTAVAIL) && !defined(_WIN32) # define UV__EADDRNOTAVAIL (-EADDRNOTAVAIL) #else -# define UV__EADDRNOTAVAIL (-4091) +# define UV__EADDRNOTAVAIL (-4090) #endif #if defined(EAFNOSUPPORT) && !defined(_WIN32) # define UV__EAFNOSUPPORT (-EAFNOSUPPORT) #else -# define UV__EAFNOSUPPORT (-4090) +# define UV__EAFNOSUPPORT (-4089) #endif #if defined(EAGAIN) && !defined(_WIN32) # define UV__EAGAIN (-EAGAIN) #else -# define UV__EAGAIN (-4089) +# define UV__EAGAIN (-4088) #endif #if defined(EALREADY) && !defined(_WIN32) # define UV__EALREADY (-EALREADY) #else -# define UV__EALREADY (-4085) +# define UV__EALREADY (-4084) #endif #if defined(EBADF) && !defined(_WIN32) # define UV__EBADF (-EBADF) #else -# define UV__EBADF (-4084) +# define UV__EBADF (-4083) #endif #if defined(EBUSY) && !defined(_WIN32) # define UV__EBUSY (-EBUSY) #else -# define UV__EBUSY (-4083) +# define UV__EBUSY (-4082) #endif #if defined(ECANCELED) && !defined(_WIN32) # define UV__ECANCELED (-ECANCELED) #else -# define UV__ECANCELED (-4082) +# define UV__ECANCELED (-4081) #endif #if defined(ECHARSET) && !defined(_WIN32) # define UV__ECHARSET (-ECHARSET) #else -# define UV__ECHARSET (-4081) +# define UV__ECHARSET (-4080) #endif #if defined(ECONNABORTED) && !defined(_WIN32) # define UV__ECONNABORTED (-ECONNABORTED) #else -# define UV__ECONNABORTED (-4080) +# define UV__ECONNABORTED (-4079) #endif #if defined(ECONNREFUSED) && !defined(_WIN32) # define UV__ECONNREFUSED (-ECONNREFUSED) #else -# define UV__ECONNREFUSED (-4079) +# define UV__ECONNREFUSED (-4078) #endif #if defined(ECONNRESET) && !defined(_WIN32) # define UV__ECONNRESET (-ECONNRESET) #else -# define UV__ECONNRESET (-4078) +# define UV__ECONNRESET (-4077) #endif #if defined(EDESTADDRREQ) && !defined(_WIN32) # define UV__EDESTADDRREQ (-EDESTADDRREQ) #else -# define UV__EDESTADDRREQ (-4077) +# define UV__EDESTADDRREQ (-4076) #endif #if defined(EEXIST) && !defined(_WIN32) # define UV__EEXIST (-EEXIST) #else -# define UV__EEXIST (-4076) +# define UV__EEXIST (-4075) #endif #if defined(EFAULT) && !defined(_WIN32) # define UV__EFAULT (-EFAULT) #else -# define UV__EFAULT (-4075) +# define UV__EFAULT (-4074) #endif #if defined(EHOSTUNREACH) && !defined(_WIN32) # define UV__EHOSTUNREACH (-EHOSTUNREACH) #else -# define UV__EHOSTUNREACH (-4074) +# define UV__EHOSTUNREACH (-4073) #endif #if defined(EINTR) && !defined(_WIN32) # define UV__EINTR (-EINTR) #else -# define UV__EINTR (-4073) +# define UV__EINTR (-4072) #endif #if defined(EINVAL) && !defined(_WIN32) # define UV__EINVAL (-EINVAL) #else -# define UV__EINVAL (-4072) +# define UV__EINVAL (-4071) #endif #if defined(EIO) && !defined(_WIN32) # define UV__EIO (-EIO) #else -# define UV__EIO (-4071) +# define UV__EIO (-4070) #endif #if defined(EISCONN) && !defined(_WIN32) # define UV__EISCONN (-EISCONN) #else -# define UV__EISCONN (-4070) +# define UV__EISCONN (-4069) #endif #if defined(EISDIR) && !defined(_WIN32) # define UV__EISDIR (-EISDIR) #else -# define UV__EISDIR (-4069) +# define UV__EISDIR (-4068) #endif #if defined(ELOOP) && !defined(_WIN32) # define UV__ELOOP (-ELOOP) #else -# define UV__ELOOP (-4068) +# define UV__ELOOP (-4067) #endif #if defined(EMFILE) && !defined(_WIN32) # define UV__EMFILE (-EMFILE) #else -# define UV__EMFILE (-4067) +# define UV__EMFILE (-4066) #endif #if defined(EMSGSIZE) && !defined(_WIN32) # define UV__EMSGSIZE (-EMSGSIZE) #else -# define UV__EMSGSIZE (-4066) +# define UV__EMSGSIZE (-4065) #endif #if defined(ENAMETOOLONG) && !defined(_WIN32) # define UV__ENAMETOOLONG (-ENAMETOOLONG) #else -# define UV__ENAMETOOLONG (-4065) +# define UV__ENAMETOOLONG (-4064) #endif #if defined(ENETDOWN) && !defined(_WIN32) # define UV__ENETDOWN (-ENETDOWN) #else -# define UV__ENETDOWN (-4064) +# define UV__ENETDOWN (-4063) #endif #if defined(ENETUNREACH) && !defined(_WIN32) # define UV__ENETUNREACH (-ENETUNREACH) #else -# define UV__ENETUNREACH (-4063) +# define UV__ENETUNREACH (-4062) #endif #if defined(ENFILE) && !defined(_WIN32) # define UV__ENFILE (-ENFILE) #else -# define UV__ENFILE (-4062) +# define UV__ENFILE (-4061) #endif #if defined(ENOBUFS) && !defined(_WIN32) # define UV__ENOBUFS (-ENOBUFS) #else -# define UV__ENOBUFS (-4061) +# define UV__ENOBUFS (-4060) #endif #if defined(ENODEV) && !defined(_WIN32) # define UV__ENODEV (-ENODEV) #else -# define UV__ENODEV (-4060) +# define UV__ENODEV (-4059) #endif #if defined(ENOENT) && !defined(_WIN32) # define UV__ENOENT (-ENOENT) #else -# define UV__ENOENT (-4059) +# define UV__ENOENT (-4058) #endif #if defined(ENOMEM) && !defined(_WIN32) # define UV__ENOMEM (-ENOMEM) #else -# define UV__ENOMEM (-4058) +# define UV__ENOMEM (-4057) #endif #if defined(ENONET) && !defined(_WIN32) # define UV__ENONET (-ENONET) #else -# define UV__ENONET (-4057) +# define UV__ENONET (-4056) #endif #if defined(ENOSPC) && !defined(_WIN32) # define UV__ENOSPC (-ENOSPC) #else -# define UV__ENOSPC (-4056) +# define UV__ENOSPC (-4055) #endif #if defined(ENOSYS) && !defined(_WIN32) # define UV__ENOSYS (-ENOSYS) #else -# define UV__ENOSYS (-4055) +# define UV__ENOSYS (-4054) #endif #if defined(ENOTCONN) && !defined(_WIN32) # define UV__ENOTCONN (-ENOTCONN) #else -# define UV__ENOTCONN (-4054) +# define UV__ENOTCONN (-4053) #endif #if defined(ENOTDIR) && !defined(_WIN32) # define UV__ENOTDIR (-ENOTDIR) #else -# define UV__ENOTDIR (-4053) +# define UV__ENOTDIR (-4052) #endif #if defined(ENOTEMPTY) && !defined(_WIN32) # define UV__ENOTEMPTY (-ENOTEMPTY) #else -# define UV__ENOTEMPTY (-4052) +# define UV__ENOTEMPTY (-4051) #endif #if defined(ENOTSOCK) && !defined(_WIN32) # define UV__ENOTSOCK (-ENOTSOCK) #else -# define UV__ENOTSOCK (-4051) +# define UV__ENOTSOCK (-4050) #endif #if defined(ENOTSUP) && !defined(_WIN32) # define UV__ENOTSUP (-ENOTSUP) #else -# define UV__ENOTSUP (-4050) +# define UV__ENOTSUP (-4049) #endif #if defined(EPERM) && !defined(_WIN32) # define UV__EPERM (-EPERM) #else -# define UV__EPERM (-4049) +# define UV__EPERM (-4048) #endif #if defined(EPIPE) && !defined(_WIN32) # define UV__EPIPE (-EPIPE) #else -# define UV__EPIPE (-4048) +# define UV__EPIPE (-4047) #endif #if defined(EPROTO) && !defined(_WIN32) # define UV__EPROTO (-EPROTO) #else -# define UV__EPROTO (-4047) +# define UV__EPROTO (-4046) #endif #if defined(EPROTONOSUPPORT) && !defined(_WIN32) # define UV__EPROTONOSUPPORT (-EPROTONOSUPPORT) #else -# define UV__EPROTONOSUPPORT (-4046) +# define UV__EPROTONOSUPPORT (-4045) #endif #if defined(EPROTOTYPE) && !defined(_WIN32) # define UV__EPROTOTYPE (-EPROTOTYPE) #else -# define UV__EPROTOTYPE (-4045) +# define UV__EPROTOTYPE (-4044) #endif #if defined(EROFS) && !defined(_WIN32) # define UV__EROFS (-EROFS) #else -# define UV__EROFS (-4044) +# define UV__EROFS (-4043) #endif #if defined(ESHUTDOWN) && !defined(_WIN32) # define UV__ESHUTDOWN (-ESHUTDOWN) #else -# define UV__ESHUTDOWN (-4043) +# define UV__ESHUTDOWN (-4042) #endif #if defined(ESPIPE) && !defined(_WIN32) # define UV__ESPIPE (-ESPIPE) #else -# define UV__ESPIPE (-4042) +# define UV__ESPIPE (-4041) #endif #if defined(ESRCH) && !defined(_WIN32) # define UV__ESRCH (-ESRCH) #else -# define UV__ESRCH (-4041) +# define UV__ESRCH (-4040) #endif #if defined(ETIMEDOUT) && !defined(_WIN32) # define UV__ETIMEDOUT (-ETIMEDOUT) #else -# define UV__ETIMEDOUT (-4040) +# define UV__ETIMEDOUT (-4039) #endif #if defined(EXDEV) && !defined(_WIN32) # define UV__EXDEV (-EXDEV) #else -# define UV__EXDEV (-4038) +# define UV__EXDEV (-4037) #endif #endif /* UV_ERRNO_H_ */ diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h index 38c1853..965fbaf 100644 --- a/deps/uv/include/uv-unix.h +++ b/deps/uv/include/uv-unix.h @@ -59,9 +59,6 @@ # define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */ #endif -#define UV_IO_PRIVATE_FIELDS \ - UV_IO_PRIVATE_PLATFORM_FIELDS \ - struct uv__io_s; struct uv__async; struct uv_loop_s; @@ -78,7 +75,7 @@ struct uv__io_s { unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ unsigned int events; /* Current event mask. */ int fd; - UV_IO_PRIVATE_FIELDS + UV_IO_PRIVATE_PLATFORM_FIELDS }; typedef void (*uv__async_cb)(struct uv_loop_s* loop, @@ -291,6 +288,7 @@ typedef struct { #define UV_PROCESS_PRIVATE_FIELDS \ void* queue[2]; \ int errorno; \ + int status; \ #define UV_FS_PRIVATE_FIELDS \ const char *new_path; \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 134759f..5a1d1d9 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -46,6 +46,7 @@ extern "C" { #endif #include "uv-errno.h" +#include #if defined(_MSC_VER) && _MSC_VER < 1600 # include "stdint-msvc2008.h" @@ -53,21 +54,15 @@ extern "C" { # include #endif -#include /* size_t */ - -#if defined(__SVR4) && !defined(__unix__) -# define __unix__ -#endif - -#if defined(__unix__) || defined(__POSIX__) || \ - defined(__APPLE__) || defined(_AIX) -# include "uv-unix.h" -#else +#if defined(_WIN32) # include "uv-win.h" +#else +# include "uv-unix.h" #endif /* Expand this list if necessary. */ #define UV_ERRNO_MAP(XX) \ + XX(E2BIG, "argument list too long") \ XX(EACCES, "permission denied") \ XX(EADDRINUSE, "address already in use") \ XX(EADDRNOTAVAIL, "address not available") \ @@ -310,7 +305,7 @@ UV_EXTERN void uv_update_time(uv_loop_t*); * Don't make assumptions about the starting point, you will only get * disappointed. * - * Use uv_hrtime() if you need sub-milliseond granularity. + * Use uv_hrtime() if you need sub-millisecond granularity. */ UV_EXTERN uint64_t uv_now(uv_loop_t*); @@ -522,8 +517,24 @@ UV_EXTERN size_t uv_handle_size(uv_handle_type type); UV_EXTERN size_t uv_req_size(uv_req_type type); /* - * Returns 1 if the prepare/check/idle/timer handle has been started, 0 - * otherwise. For other handle types this always returns 1. + * Returns non-zero if the handle is active, zero if it's inactive. + * + * What "active" means depends on the type of handle: + * + * - A uv_async_t handle is always active and cannot be deactivated, except + * by closing it with uv_close(). + * + * - A uv_pipe_t, uv_tcp_t, uv_udp_t, etc. handle - basically any handle that + * deals with I/O - is active when it is doing something that involves I/O, + * like reading, writing, connecting, accepting new connections, etc. + * + * - A uv_check_t, uv_idle_t, uv_timer_t, etc. handle is active when it has + * been started with a call to uv_check_start(), uv_idle_start(), etc. + * + * Rule of thumb: if a handle of type uv_foo_t has a uv_foo_start() + * function, then it's active from the moment that function is called. + * Likewise, uv_foo_stop() deactivates the handle again. + * */ UV_EXTERN int uv_is_active(const uv_handle_t* handle); @@ -769,6 +780,12 @@ UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable); /* * Bind the handle to an address and port. `addr` should point to an * initialized struct sockaddr_in or struct sockaddr_in6. + * + * When the port is already taken, you can expect to see an UV_EADDRINUSE + * error from either uv_tcp_bind(), uv_listen() or uv_tcp_connect(). + * + * That is, a successful call to uv_tcp_bind() does not guarantee that + * the call to uv_listen() or uv_tcp_connect() will succeed as well. */ UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, const struct sockaddr* addr); @@ -1058,8 +1075,11 @@ UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode); /* * To be called when the program exits. Resets TTY settings to default * values for the next process to take over. + * + * This function is async signal-safe on UNIX platforms but can fail with error + * code UV_EBUSY if you call it when execution is inside uv_tty_set_mode(). */ -UV_EXTERN void uv_tty_reset_mode(void); +UV_EXTERN int uv_tty_reset_mode(void); /* * Gets the current Window size. On success zero is returned. @@ -1098,8 +1118,20 @@ UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); */ UV_EXTERN int uv_pipe_open(uv_pipe_t*, uv_file file); +/* + * Bind the pipe to a file path (UNIX) or a name (Windows.) + * + * Paths on UNIX get truncated to `sizeof(sockaddr_un.sun_path)` bytes, + * typically between 92 and 108 bytes. + */ UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); +/* + * Connect to the UNIX domain socket or the named pipe. + * + * Paths on UNIX get truncated to `sizeof(sockaddr_un.sun_path)` bytes, + * typically between 92 and 108 bytes. + */ UV_EXTERN void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb); @@ -1398,7 +1430,7 @@ typedef struct uv_process_options_s { * If non-null this represents a directory the subprocess should execute * in. Stands for current working directory. */ - char* cwd; + const char* cwd; /* * Various flags that control how uv_spawn() behaves. See the definition of * `enum uv_process_flags` below. @@ -1831,7 +1863,7 @@ UV_EXTERN void uv_loadavg(double avg[3]); /* - * Flags to be passed to uv_fs_event_init. + * Flags to be passed to uv_fs_event_start. */ enum uv_fs_event_flags { /* @@ -1861,8 +1893,15 @@ enum uv_fs_event_flags { }; -UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, - const char* filename, uv_fs_event_cb cb, int flags); +UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle); + +UV_EXTERN int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags); + +UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle); + /* Utility */ diff --git a/deps/uv/src/unix/aix.c b/deps/uv/src/unix/aix.c index 604a38d..fe0ef42 100644 --- a/deps/uv/src/unix/aix.c +++ b/deps/uv/src/unix/aix.c @@ -85,7 +85,7 @@ int uv_exepath(char* buffer, size_t* size) { return fd; res = read(fd, &ps, sizeof(ps)); - close(fd); + uv__close(fd); if (res < 0) return res; @@ -128,12 +128,20 @@ void uv_loadavg(double avg[3]) { } -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { - loop->counters.fs_event_init++; +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + return -ENOSYS; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags) { + return -ENOSYS; +} + + +int uv_fs_event_stop(uv_fs_event_t* handle) { return -ENOSYS; } @@ -179,7 +187,7 @@ int uv_resident_set_memory(size_t* rss) { *rss = (size_t)psinfo.pr_rssize * 1024; err = 0; } - close(fd); + uv__close(fd); return err; } @@ -291,14 +299,14 @@ int uv_interface_addresses(uv_interface_address_t** addresses, } if (ioctl(sockfd, SIOCGSIZIFCONF, &size) == -1) { - close(sockfd); + uv__close(sockfd); return -ENOSYS; } ifc.ifc_req = (struct ifreq*)malloc(size); ifc.ifc_len = size; if (ioctl(sockfd, SIOCGIFCONF, &ifc) == -1) { - close(sockfd); + uv__close(sockfd); return -ENOSYS; } @@ -317,7 +325,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - close(sockfd); + uv__close(sockfd); return -ENOSYS; } @@ -331,7 +339,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, *addresses = (uv_interface_address_t*) malloc(*count * sizeof(uv_interface_address_t)); if (!(*addresses)) { - close(sockfd); + uv__close(sockfd); return -ENOMEM; } address = *addresses; @@ -348,7 +356,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, memcpy(flg.ifr_name, p->ifr_name, sizeof(flg.ifr_name)); if (ioctl(sockfd, SIOCGIFFLAGS, &flg) == -1) { - close(sockfd); + uv__close(sockfd); return -ENOSYS; } @@ -374,7 +382,7 @@ int uv_interface_addresses(uv_interface_address_t** addresses, #undef ADDR_SIZE - close(sockfd); + uv__close(sockfd); return 0; } diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c index 5ced3cb..3c23e1d 100644 --- a/deps/uv/src/unix/async.c +++ b/deps/uv/src/unix/async.c @@ -237,11 +237,11 @@ void uv__async_stop(uv_loop_t* loop, struct uv__async* wa) { return; uv__io_stop(loop, &wa->io_watcher, UV__POLLIN); - close(wa->io_watcher.fd); + uv__close(wa->io_watcher.fd); wa->io_watcher.fd = -1; if (wa->wfd != -1) { - close(wa->wfd); + uv__close(wa->wfd); wa->wfd = -1; } } diff --git a/deps/uv/src/unix/atomic-ops.h b/deps/uv/src/unix/atomic-ops.h new file mode 100644 index 0000000..7e4e64b --- /dev/null +++ b/deps/uv/src/unix/atomic-ops.h @@ -0,0 +1,60 @@ +/* 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. + */ + +#ifndef UV_ATOMIC_OPS_H_ +#define UV_ATOMIC_OPS_H_ + +#include "internal.h" /* UV_UNUSED */ + +UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)); +UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)); +UV_UNUSED(static void cpu_relax(void)); + +/* Prefer hand-rolled assembly over the gcc builtins because the latter also + * issue full memory barriers. + */ +UV_UNUSED(static int cmpxchgi(int* ptr, int oldval, int newval)) { +#if defined(__i386__) || defined(__x86_64__) + int out; + __asm__ __volatile__ ("lock; cmpxchg %2, %1;" + : "=a" (out), "+m" (*(volatile int*) ptr) + : "r" (newval), "0" (oldval) + : "memory"); + return out; +#else + return __sync_val_compare_and_swap(ptr, oldval, newval); +#endif +} + +UV_UNUSED(static long cmpxchgl(long* ptr, long oldval, long newval)) { +#if defined(__i386__) || defined(__x86_64__) + long out; + __asm__ __volatile__ ("lock; cmpxchg %2, %1;" + : "=a" (out), "+m" (*(volatile long*) ptr) + : "r" (newval), "0" (oldval) + : "memory"); + return out; +#else + return __sync_val_compare_and_swap(ptr, oldval, newval); +#endif +} + +UV_UNUSED(static void cpu_relax(void)) { +#if defined(__i386__) || defined(__x86_64__) + __asm__ __volatile__ ("rep; nop"); /* a.k.a. PAUSE */ +#endif +} + +#endif /* UV_ATOMIC_OPS_H_ */ diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 7de85bf..b23f6ae 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -340,7 +340,7 @@ int uv__socket(int domain, int type, int protocol) { err = uv__cloexec(sockfd, 1); if (err) { - close(sockfd); + uv__close(sockfd); return err; } @@ -397,7 +397,7 @@ skip: err = uv__nonblock(peerfd, 1); if (err) { - close(peerfd); + uv__close(peerfd); return err; } @@ -406,6 +406,26 @@ skip: } +int uv__close(int fd) { + int saved_errno; + int rc; + + assert(fd > -1); /* Catch uninitialized io_watcher.fd bugs. */ + assert(fd > STDERR_FILENO); /* Catch stdio close bugs. */ + + saved_errno = errno; + rc = close(fd); + if (rc == -1) { + rc = -errno; + if (rc == -EINTR) + rc = -EINPROGRESS; /* For platform/libc consistency. */ + errno = saved_errno; + } + + return rc; +} + + #if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) int uv__nonblock(int fd, int set) { @@ -514,7 +534,7 @@ int uv__dup(int fd) { err = uv__cloexec(fd, 1); if (err) { - close(fd); + uv__close(fd); return err; } diff --git a/deps/uv/src/unix/darwin-proctitle.c b/deps/uv/src/unix/darwin-proctitle.c index c5f53a0..8cd358b 100644 --- a/deps/uv/src/unix/darwin-proctitle.c +++ b/deps/uv/src/unix/darwin-proctitle.c @@ -61,7 +61,6 @@ int uv__set_process_title(const char* title) { CFBundleRef (*pCFBundleGetBundleWithIdentifier)(CFStringRef); void *(*pCFBundleGetDataPointerForName)(CFBundleRef, CFStringRef); void *(*pCFBundleGetFunctionPointerForName)(CFBundleRef, CFStringRef); - OSErr (*pGetCurrentProcess)(ProcessSerialNumber*); CFTypeRef (*pLSGetCurrentApplicationASN)(void); OSStatus (*pLSSetApplicationInformationItem)(int, CFTypeRef, @@ -72,7 +71,13 @@ int uv__set_process_title(const char* title) { void* core_foundation_handle; CFBundleRef launch_services_bundle; CFStringRef* display_name_key; - ProcessSerialNumber psn; + CFDictionaryRef (*pCFBundleGetInfoDictionary)(CFBundleRef); + CFBundleRef (*pCFBundleGetMainBundle)(void); + CFBundleRef hi_services_bundle; + OSStatus (*pSetApplicationIsDaemon)(int); + CFDictionaryRef (*pLSApplicationCheckIn)(int, CFDictionaryRef); + void (*pLSSetApplicationLaunchServicesServerConnectionStatus)(uint64_t, + void*); CFTypeRef asn; int err; @@ -89,8 +94,6 @@ int uv__set_process_title(const char* title) { if (application_services_handle == NULL || core_foundation_handle == NULL) goto out; - pGetCurrentProcess = - dlsym(application_services_handle, "GetCurrentProcess"); pCFStringCreateWithCString = dlsym(core_foundation_handle, "CFStringCreateWithCString"); pCFBundleGetBundleWithIdentifier = @@ -100,8 +103,7 @@ int uv__set_process_title(const char* title) { pCFBundleGetFunctionPointerForName = dlsym(core_foundation_handle, "CFBundleGetFunctionPointerForName"); - if (pGetCurrentProcess == NULL || - pCFStringCreateWithCString == NULL || + if (pCFStringCreateWithCString == NULL || pCFBundleGetBundleWithIdentifier == NULL || pCFBundleGetDataPointerForName == NULL || pCFBundleGetFunctionPointerForName == NULL) { @@ -136,8 +138,44 @@ int uv__set_process_title(const char* title) { if (display_name_key == NULL || *display_name_key == NULL) goto out; - /* Force the process manager to initialize. */ - pGetCurrentProcess(&psn); + pCFBundleGetInfoDictionary = dlsym(core_foundation_handle, + "CFBundleGetInfoDictionary"); + pCFBundleGetMainBundle = dlsym(core_foundation_handle, + "CFBundleGetMainBundle"); + if (pCFBundleGetInfoDictionary == NULL || pCFBundleGetMainBundle == NULL) + goto out; + + /* Black 10.9 magic, to remove (Not responding) mark in Activity Monitor */ + hi_services_bundle = + pCFBundleGetBundleWithIdentifier(S("com.apple.HIServices")); + err = -ENOENT; + if (hi_services_bundle == NULL) + goto out; + + pSetApplicationIsDaemon = pCFBundleGetFunctionPointerForName( + hi_services_bundle, + S("SetApplicationIsDaemon")); + pLSApplicationCheckIn = pCFBundleGetFunctionPointerForName( + launch_services_bundle, + S("_LSApplicationCheckIn")); + pLSSetApplicationLaunchServicesServerConnectionStatus = + pCFBundleGetFunctionPointerForName( + launch_services_bundle, + S("_LSSetApplicationLaunchServicesServerConnectionStatus")); + if (pSetApplicationIsDaemon == NULL || + pLSApplicationCheckIn == NULL || + pLSSetApplicationLaunchServicesServerConnectionStatus == NULL) { + goto out; + } + + if (pSetApplicationIsDaemon(1) != noErr) + goto out; + + pLSSetApplicationLaunchServicesServerConnectionStatus(0, NULL); + + /* Check into process manager?! */ + pLSApplicationCheckIn(-2, + pCFBundleGetInfoDictionary(pCFBundleGetMainBundle())); asn = pLSGetCurrentApplicationASN(); diff --git a/deps/uv/src/unix/freebsd.c b/deps/uv/src/unix/freebsd.c index b1e8eb7..bb8fb16 100644 --- a/deps/uv/src/unix/freebsd.c +++ b/deps/uv/src/unix/freebsd.c @@ -273,7 +273,9 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { return -errno; } - /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of ncpu */ + /* kern.cp_times on FreeBSD i386 gives an array up to maxcpus instead of + * ncpu. + */ size = sizeof(maxcpus); if (sysctlbyname(maxcpus_key, &maxcpus, &size, NULL, 0)) { SAVE_ERRNO(free(*cpu_infos)); diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c index e7a493e..305de6d 100644 --- a/deps/uv/src/unix/fsevents.c +++ b/deps/uv/src/unix/fsevents.c @@ -76,7 +76,7 @@ typedef struct uv__cf_loop_state_s uv__cf_loop_state_t; struct uv__cf_loop_state_s { CFRunLoopRef loop; CFRunLoopSourceRef signal_source; - volatile int fsevent_need_reschedule; + int fsevent_need_reschedule; FSEventStreamRef fsevent_stream; uv_sem_t fsevent_sem; uv_mutex_t fsevent_mutex; @@ -360,9 +360,13 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) { /* Optimization to prevent O(n^2) time spent when starting to watch * many files simultaneously */ - if (!state->fsevent_need_reschedule) - return; + uv_mutex_lock(&state->fsevent_mutex); + if (state->fsevent_need_reschedule == 0) { + uv_mutex_unlock(&state->fsevent_mutex); + goto final; + } state->fsevent_need_reschedule = 0; + uv_mutex_unlock(&state->fsevent_mutex); /* Destroy previous FSEventStream */ uv__fsevents_destroy_stream(handle->loop); @@ -399,13 +403,14 @@ static void uv__fsevents_reschedule(uv_fs_event_t* handle) { uv__fsevents_create_stream(handle->loop, cf_paths); } +final: /* * Main thread will block until the removal of handle from the list, * we must tell it when we're ready. * * NOTE: This is coupled with `uv_sem_wait()` in `uv__fsevents_close` */ - if (uv__is_closing(handle)) + if (!uv__is_active(handle)) uv_sem_post(&state->fsevent_sem); } @@ -547,7 +552,7 @@ static int uv__fsevents_loop_init(uv_loop_t* loop) { attr = NULL; if (attr != NULL) - if (pthread_attr_setstacksize(attr, 3 * PTHREAD_STACK_MIN)) + if (pthread_attr_setstacksize(attr, 4 * PTHREAD_STACK_MIN)) abort(); loop->cf_state = state; diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 67c847b..c050c52 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -130,6 +130,7 @@ enum { /* core */ int uv__nonblock(int fd, int set); +int uv__close(int fd); int uv__cloexec(int fd, int set); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 391ab61..470045d 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -296,23 +296,30 @@ static void uv__fs_event(uv_loop_t* loop, uv__io_t* w, unsigned int fflags) { } -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags) { #if defined(__APPLE__) struct stat statbuf; #endif /* defined(__APPLE__) */ int fd; + if (uv__is_active(handle)) + return -EINVAL; + /* TODO open asynchronously - but how do we report back errors? */ fd = open(filename, O_RDONLY); if (fd == -1) return -errno; - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - uv__handle_start(handle); /* FIXME shouldn't start automatically */ + uv__handle_start(handle); uv__io_init(&handle->event_watcher, uv__fs_event, fd); handle->filename = strdup(filename); handle->cb = cb; @@ -335,13 +342,18 @@ int uv_fs_event_init(uv_loop_t* loop, fallback: #endif /* defined(__APPLE__) */ - uv__io_start(loop, &handle->event_watcher, UV__POLLIN); + uv__io_start(handle->loop, &handle->event_watcher, UV__POLLIN); return 0; } -void uv__fs_event_close(uv_fs_event_t* handle) { +int uv_fs_event_stop(uv_fs_event_t* handle) { + if (!uv__is_active(handle)) + return -EINVAL; + + uv__handle_stop(handle); + #if defined(__APPLE__) if (uv__fsevents_close(handle)) uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN); @@ -349,11 +361,16 @@ void uv__fs_event_close(uv_fs_event_t* handle) { uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN); #endif /* defined(__APPLE__) */ - uv__handle_stop(handle); - free(handle->filename); handle->filename = NULL; - close(handle->event_watcher.fd); + uv__close(handle->event_watcher.fd); handle->event_watcher.fd = -1; + + return 0; +} + + +void uv__fs_event_close(uv_fs_event_t* handle) { + uv_fs_event_stop(handle); } diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index fa5dec1..8bdd53d 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -98,7 +98,7 @@ int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { void uv__platform_loop_delete(uv_loop_t* loop) { if (loop->inotify_fd == -1) return; uv__io_stop(loop, &loop->inotify_read_watcher, UV__POLLIN); - close(loop->inotify_fd); + uv__close(loop->inotify_fd); loop->inotify_fd = -1; } @@ -309,7 +309,7 @@ int uv_resident_set_memory(size_t* rss) { n = read(fd, buf, sizeof(buf) - 1); while (n == -1 && errno == EINTR); - SAVE_ERRNO(close(fd)); + uv__close(fd); if (n == -1) return -errno; buf[n] = '\0'; @@ -368,7 +368,6 @@ int uv_uptime(double* uptime) { return -errno; *uptime = now.tv_sec; - *uptime += (double)now.tv_nsec / 1000000000.0; return 0; } diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c index 4bf30db..7641f38 100644 --- a/deps/uv/src/unix/linux-inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -81,7 +81,7 @@ static int new_inotify_fd(void) { err = uv__nonblock(fd, 1); if (err) { - close(fd); + uv__close(fd); return err; } @@ -168,17 +168,25 @@ static void uv__inotify_read(uv_loop_t* loop, } -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* path, - uv_fs_event_cb cb, - int flags) { +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* path, + unsigned int flags) { struct watcher_list* w; int events; int err; int wd; - err = init_inotify(loop); + if (uv__is_active(handle)) + return -EINVAL; + + err = init_inotify(handle->loop); if (err) return err; @@ -191,11 +199,11 @@ int uv_fs_event_init(uv_loop_t* loop, | UV__IN_MOVED_FROM | UV__IN_MOVED_TO; - wd = uv__inotify_add_watch(loop->inotify_fd, path, events); + wd = uv__inotify_add_watch(handle->loop->inotify_fd, path, events); if (wd == -1) return -errno; - w = find_watcher(loop, wd); + w = find_watcher(handle->loop, wd); if (w) goto no_insert; @@ -206,11 +214,10 @@ int uv_fs_event_init(uv_loop_t* loop, w->wd = wd; w->path = strcpy((char*)(w + 1), path); QUEUE_INIT(&w->watchers); - RB_INSERT(watcher_root, CAST(&loop->inotify_watchers), w); + RB_INSERT(watcher_root, CAST(&handle->loop->inotify_watchers), w); no_insert: - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - uv__handle_start(handle); /* FIXME shouldn't start automatically */ + uv__handle_start(handle); QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers); handle->filename = w->path; handle->cb = cb; @@ -220,9 +227,12 @@ no_insert: } -void uv__fs_event_close(uv_fs_event_t* handle) { +int uv_fs_event_stop(uv_fs_event_t* handle) { struct watcher_list* w; + if (!uv__is_active(handle)) + return -EINVAL; + w = find_watcher(handle->loop, handle->wd); assert(w != NULL); @@ -237,4 +247,11 @@ void uv__fs_event_close(uv_fs_event_t* handle) { uv__inotify_rm_watch(handle->loop->inotify_fd, w->wd); free(w); } + + return 0; +} + + +void uv__fs_event_close(uv_fs_event_t* handle) { + uv_fs_event_stop(handle); } diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index 4c10f0f..cbe9317 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -136,12 +136,12 @@ static void uv__loop_delete(uv_loop_t* loop) { uv__async_stop(loop, &loop->async_watcher); if (loop->emfile_fd != -1) { - close(loop->emfile_fd); + uv__close(loop->emfile_fd); loop->emfile_fd = -1; } if (loop->backend_fd != -1) { - close(loop->backend_fd); + uv__close(loop->backend_fd); loop->backend_fd = -1; } diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c index d7c4794..705a973 100644 --- a/deps/uv/src/unix/pipe.c +++ b/deps/uv/src/unix/pipe.c @@ -29,8 +29,6 @@ #include #include -static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, unsigned int events); - int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) { uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE); @@ -93,11 +91,11 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { out: if (bound) { - /* unlink() before close() to avoid races. */ + /* unlink() before uv__close() to avoid races. */ assert(pipe_fname != NULL); unlink(pipe_fname); } - close(sockfd); + uv__close(sockfd); free((void*)pipe_fname); return err; } @@ -111,7 +109,7 @@ int uv_pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) { return -errno; handle->connection_cb = cb; - handle->io_watcher.cb = uv__pipe_accept; + handle->io_watcher.cb = uv__server_io; uv__io_start(handle->loop, &handle->io_watcher, UV__POLLIN); return 0; } @@ -212,29 +210,5 @@ out: } -/* TODO merge with uv__server_io()? */ -static void uv__pipe_accept(uv_loop_t* loop, uv__io_t* w, unsigned int events) { - uv_pipe_t* pipe; - int sockfd; - - pipe = container_of(w, uv_pipe_t, io_watcher); - assert(pipe->type == UV_NAMED_PIPE); - - sockfd = uv__accept(uv__stream_fd(pipe)); - if (sockfd == -1) { - if (errno != EAGAIN && errno != EWOULDBLOCK) - pipe->connection_cb((uv_stream_t*)pipe, -errno); - return; - } - - pipe->accepted_fd = sockfd; - pipe->connection_cb((uv_stream_t*)pipe, 0); - if (pipe->accepted_fd == sockfd) { - /* The user hasn't called uv_accept() yet */ - uv__io_stop(pipe->loop, &pipe->io_watcher, UV__POLLIN); - } -} - - void uv_pipe_pending_instances(uv_pipe_t* handle, int count) { } diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c index 990ea15..42990ce 100644 --- a/deps/uv/src/unix/process.c +++ b/deps/uv/src/unix/process.c @@ -47,68 +47,73 @@ static QUEUE* uv__process_queue(uv_loop_t* loop, int pid) { } -static uv_process_t* uv__process_find(uv_loop_t* loop, int pid) { - uv_process_t* handle; - QUEUE* h; - QUEUE* q; - - h = uv__process_queue(loop, pid); - - QUEUE_FOREACH(q, h) { - handle = QUEUE_DATA(q, uv_process_t, queue); - if (handle->pid == pid) return handle; - } - - return NULL; -} - - static void uv__chld(uv_signal_t* handle, int signum) { uv_process_t* process; + uv_loop_t* loop; int exit_status; int term_signal; + unsigned int i; int status; pid_t pid; + QUEUE pending; + QUEUE* h; + QUEUE* q; assert(signum == SIGCHLD); - for (;;) { - do - pid = waitpid(-1, &status, WNOHANG); - while (pid == -1 && errno == EINTR); + QUEUE_INIT(&pending); + loop = handle->loop; - if (pid == 0) - return; + for (i = 0; i < ARRAY_SIZE(loop->process_handles); i++) { + h = loop->process_handles + i; + q = QUEUE_HEAD(h); - if (pid == -1) { - if (errno == ECHILD) - return; /* XXX stop signal watcher? */ - else - abort(); - } + while (q != h) { + process = QUEUE_DATA(q, uv_process_t, queue); + q = QUEUE_NEXT(q); - process = uv__process_find(handle->loop, pid); - if (process == NULL) - continue; /* XXX bug? abort? */ + do + pid = waitpid(process->pid, &status, WNOHANG); + while (pid == -1 && errno == EINTR); - uv__handle_stop(process); + if (pid == 0) + continue; - if (process->exit_cb == NULL) - continue; + if (pid == -1) { + if (errno != ECHILD) + abort(); + continue; + } + + process->status = status; + QUEUE_REMOVE(&process->queue); + QUEUE_INSERT_TAIL(&pending, &process->queue); + } + + while (!QUEUE_EMPTY(&pending)) { + q = QUEUE_HEAD(&pending); + QUEUE_REMOVE(q); + QUEUE_INIT(q); + + process = QUEUE_DATA(q, uv_process_t, queue); + uv__handle_stop(process); - exit_status = 0; - term_signal = 0; + if (process->exit_cb == NULL) + continue; - if (WIFEXITED(status)) - exit_status = WEXITSTATUS(status); + exit_status = 0; + if (WIFEXITED(process->status)) + exit_status = WEXITSTATUS(process->status); - if (WIFSIGNALED(status)) - term_signal = WTERMSIG(status); + term_signal = 0; + if (WIFSIGNALED(process->status)) + term_signal = WTERMSIG(process->status); - if (process->errorno) - exit_status = process->errorno; /* execve() failed */ + if (process->errorno != 0) + exit_status = process->errorno; /* execve() failed */ - process->exit_cb(process, exit_status, term_signal); + process->exit_cb(process, exit_status, term_signal); + } } } @@ -183,8 +188,8 @@ skip: /* - * Used for initializing stdio streams like options->stdin_stream. Returns - * zero on success. + * Used for initializing stdio streams like options.stdin_stream. Returns + * zero on success. See also the cleanup section in uv_spawn(). */ static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { int mask; @@ -231,7 +236,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container, if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) return 0; - if (close(pipefds[1])) + if (uv__close(pipefds[1])) if (errno != EINTR && errno != EINPROGRESS) abort(); @@ -285,8 +290,10 @@ static void uv__process_child_init(const uv_process_options_t* options, close_fd = pipes[fd][0]; use_fd = pipes[fd][1]; - if (use_fd >= 0) - close(close_fd); + if (use_fd >= 0) { + if (close_fd != -1) + uv__close(close_fd); + } else if (fd >= 3) continue; else { @@ -306,7 +313,7 @@ static void uv__process_child_init(const uv_process_options_t* options, uv__cloexec(use_fd, 0); else { dup2(use_fd, fd); - close(use_fd); + uv__close(use_fd); } if (fd <= 2) @@ -414,8 +421,8 @@ int uv_spawn(uv_loop_t* loop, if (pid == -1) { err = -errno; - close(signal_pipe[0]); - close(signal_pipe[1]); + uv__close(signal_pipe[0]); + uv__close(signal_pipe[1]); goto error; } @@ -424,8 +431,9 @@ int uv_spawn(uv_loop_t* loop, abort(); } - close(signal_pipe[1]); + uv__close(signal_pipe[1]); + process->status = 0; process->errorno = 0; do r = read(signal_pipe[0], &process->errorno, sizeof(process->errorno)); @@ -440,7 +448,7 @@ int uv_spawn(uv_loop_t* loop, else abort(); - close(signal_pipe[0]); + uv__close(signal_pipe[0]); for (i = 0; i < options->stdio_count; i++) { err = uv__process_open_stream(options->stdio + i, pipes[i], i == 0); @@ -464,11 +472,18 @@ int uv_spawn(uv_loop_t* loop, return 0; error: - for (i = 0; i < stdio_count; i++) { - close(pipes[i][0]); - close(pipes[i][1]); + if (pipes != NULL) { + for (i = 0; i < stdio_count; i++) { + if (i < options->stdio_count) + if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) + continue; + if (pipes[i][0] != -1) + close(pipes[i][0]); + if (pipes[i][1] != -1) + close(pipes[i][1]); + } + free(pipes); } - free(pipes); return err; } diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index 53e524a..8c0d62f 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -141,7 +141,10 @@ static void uv__signal_handler(int signum) { saved_errno = errno; memset(&msg, 0, sizeof msg); - uv__signal_lock(); + if (uv__signal_lock()) { + errno = saved_errno; + return; + } for (handle = uv__signal_first_handle(signum); handle != NULL && handle->signum == signum; @@ -240,12 +243,12 @@ void uv__signal_loop_cleanup(uv_loop_t* loop) { } if (loop->signal_pipefd[0] != -1) { - close(loop->signal_pipefd[0]); + uv__close(loop->signal_pipefd[0]); loop->signal_pipefd[0] = -1; } if (loop->signal_pipefd[1] != -1) { - close(loop->signal_pipefd[1]); + uv__close(loop->signal_pipefd[1]); loop->signal_pipefd[1] = -1; } } @@ -335,7 +338,9 @@ int uv_signal_start(uv_signal_t* handle, uv_signal_cb signal_cb, int signum) { } -static void uv__signal_event(uv_loop_t* loop, uv__io_t* w, unsigned int events) { +static void uv__signal_event(uv_loop_t* loop, + uv__io_t* w, + unsigned int events) { uv__signal_msg_t* msg; uv_signal_t* handle; char buf[sizeof(uv__signal_msg_t) * 32]; diff --git a/deps/uv/src/unix/spinlock.h b/deps/uv/src/unix/spinlock.h new file mode 100644 index 0000000..a20c83c --- /dev/null +++ b/deps/uv/src/unix/spinlock.h @@ -0,0 +1,53 @@ +/* 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. + */ + +#ifndef UV_SPINLOCK_H_ +#define UV_SPINLOCK_H_ + +#include "internal.h" /* ACCESS_ONCE, UV_UNUSED */ +#include "atomic-ops.h" + +#define UV_SPINLOCK_INITIALIZER { 0 } + +typedef struct { + int lock; +} uv_spinlock_t; + +UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)); +UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)); +UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)); +UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)); + +UV_UNUSED(static void uv_spinlock_init(uv_spinlock_t* spinlock)) { + ACCESS_ONCE(int, spinlock->lock) = 0; +} + +UV_UNUSED(static void uv_spinlock_lock(uv_spinlock_t* spinlock)) { + while (!uv_spinlock_trylock(spinlock)) cpu_relax(); +} + +UV_UNUSED(static void uv_spinlock_unlock(uv_spinlock_t* spinlock)) { + ACCESS_ONCE(int, spinlock->lock) = 0; +} + +UV_UNUSED(static int uv_spinlock_trylock(uv_spinlock_t* spinlock)) { + /* TODO(bnoordhuis) Maybe change to a ticket lock to guarantee fair queueing. + * Not really critical until we have locks that are (frequently) contended + * for by several threads. + */ + return 0 == cmpxchgi(&spinlock->lock, 0, 1); +} + +#endif /* UV_SPINLOCK_H_ */ diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index c8e9f6d..d910a68 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -85,7 +85,7 @@ static int uv__open_cloexec(const char* path, int flags) { err = uv__cloexec(fd, 1); if (err) { - close(fd); + uv__close(fd); return err; } @@ -309,7 +309,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { timeout.tv_nsec = 1; ret = kevent(kq, filter, 1, events, 1, &timeout); - SAVE_ERRNO(close(kq)); + uv__close(kq); if (ret == -1) return -errno; @@ -357,8 +357,8 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) { return 0; fatal4: - close(s->fake_fd); - close(s->int_fd); + uv__close(s->fake_fd); + uv__close(s->int_fd); s->fake_fd = -1; s->int_fd = -1; fatal3: @@ -467,13 +467,13 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { if (loop->emfile_fd == -1) return -EMFILE; - close(loop->emfile_fd); + uv__close(loop->emfile_fd); for (;;) { fd = uv__accept(accept_fd); if (fd != -1) { - close(fd); + uv__close(fd); continue; } @@ -572,7 +572,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { UV_STREAM_READABLE | UV_STREAM_WRITABLE); if (err) { /* TODO handle error */ - close(server->accepted_fd); + uv__close(server->accepted_fd); server->accepted_fd = -1; return err; } @@ -581,7 +581,7 @@ int uv_accept(uv_stream_t* server, uv_stream_t* client) { case UV_UDP: err = uv_udp_open((uv_udp_t*) client, server->accepted_fd); if (err) { - close(server->accepted_fd); + uv__close(server->accepted_fd); server->accepted_fd = -1; return err; } @@ -1092,7 +1092,6 @@ static void uv__read(uv_stream_t* stream) { int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { assert((stream->type == UV_TCP || stream->type == UV_NAMED_PIPE) && "uv_shutdown (unix) only supports uv_handle_t right now"); - assert(uv__stream_fd(stream) >= 0); if (!(stream->flags & UV_STREAM_WRITABLE) || stream->flags & UV_STREAM_SHUT || @@ -1101,6 +1100,8 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) { return -ENOTCONN; } + assert(uv__stream_fd(stream) >= 0); + /* Initialize request */ uv__req_init(stream->loop, req, UV_SHUTDOWN); req->handle = stream; @@ -1384,12 +1385,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_STREAM_READABLE); } int uv_is_writable(const uv_stream_t* stream) { - return stream->flags & UV_STREAM_WRITABLE; + return !!(stream->flags & UV_STREAM_WRITABLE); } @@ -1424,8 +1425,8 @@ void uv__stream_close(uv_stream_t* handle) { uv_thread_join(&s->thread); uv_sem_destroy(&s->close_sem); uv_sem_destroy(&s->async_sem); - close(s->fake_fd); - close(s->int_fd); + uv__close(s->fake_fd); + uv__close(s->int_fd); uv_close((uv_handle_t*) &s->async, uv__stream_osx_cb_close); handle->select = NULL; @@ -1436,11 +1437,15 @@ void uv__stream_close(uv_stream_t* handle) { uv_read_stop(handle); uv__handle_stop(handle); - close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; + if (handle->io_watcher.fd != -1) { + /* Don't close stdio file descriptors. Nothing good comes from it. */ + if (handle->io_watcher.fd > STDERR_FILENO) + uv__close(handle->io_watcher.fd); + handle->io_watcher.fd = -1; + } - if (handle->accepted_fd >= 0) { - close(handle->accepted_fd); + if (handle->accepted_fd != -1) { + uv__close(handle->accepted_fd); handle->accepted_fd = -1; } diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 5cf8493..fe99d08 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -75,7 +75,7 @@ int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { err = uv__cloexec(fd, 1); if (err) { - close(fd); + uv__close(fd); return err; } loop->backend_fd = fd; @@ -86,12 +86,12 @@ int uv__platform_loop_init(uv_loop_t* loop, int default_loop) { void uv__platform_loop_delete(uv_loop_t* loop) { if (loop->fs_fd != -1) { - close(loop->fs_fd); + uv__close(loop->fs_fd); loop->fs_fd = -1; } if (loop->backend_fd != -1) { - close(loop->backend_fd); + uv__close(loop->backend_fd); loop->backend_fd = -1; } } @@ -256,7 +256,7 @@ int uv_exepath(char* buffer, size_t* size) { if (buffer == NULL || size == NULL) return -EINVAL; - (void) snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); + snprintf(buf, sizeof(buf), "/proc/%lu/path/a.out", (unsigned long) getpid()); res = readlink(buf, buffer, *size - 1); if (res == -1) return -errno; @@ -352,24 +352,32 @@ static void uv__fs_event_read(uv_loop_t* loop, } -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags) { int portfd; - int first_run = 0; + int first_run; + + if (uv__is_active(handle)) + return -EINVAL; - if (loop->fs_fd == -1) { + first_run = 0; + if (handle->loop->fs_fd == -1) { portfd = port_create(); if (portfd == -1) return -errno; - loop->fs_fd = portfd; + handle->loop->fs_fd = portfd; first_run = 1; } - uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); - uv__handle_start(handle); /* FIXME shouldn't start automatically */ + uv__handle_start(handle); handle->filename = strdup(filename); handle->fd = PORT_UNUSED; handle->cb = cb; @@ -379,32 +387,53 @@ int uv_fs_event_init(uv_loop_t* loop, uv__fs_event_rearm(handle); /* FIXME(bnoordhuis) Check return code. */ if (first_run) { - uv__io_init(&loop->fs_event_watcher, uv__fs_event_read, portfd); - uv__io_start(loop, &loop->fs_event_watcher, UV__POLLIN); + uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd); + uv__io_start(handle->loop, &handle->loop->fs_event_watcher, UV__POLLIN); } return 0; } -void uv__fs_event_close(uv_fs_event_t* handle) { +int uv_fs_event_stop(uv_fs_event_t* handle) { + if (!uv__is_active(handle)) + return -EINVAL; + if (handle->fd == PORT_FIRED || handle->fd == PORT_LOADED) { - port_dissociate(handle->loop->fs_fd, PORT_SOURCE_FILE, (uintptr_t)&handle->fo); + port_dissociate(handle->loop->fs_fd, + PORT_SOURCE_FILE, + (uintptr_t) &handle->fo); } + handle->fd = PORT_DELETED; free(handle->filename); handle->filename = NULL; handle->fo.fo_name = NULL; uv__handle_stop(handle); + + return 0; +} + +void uv__fs_event_close(uv_fs_event_t* handle) { + uv_fs_event_stop(handle); } #else /* !defined(PORT_SOURCE_FILE) */ -int uv_fs_event_init(uv_loop_t* loop, - uv_fs_event_t* handle, - const char* filename, - uv_fs_event_cb cb, - int flags) { +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + return -ENOSYS; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags) { + return -ENOSYS; +} + + +int uv_fs_event_stop(uv_fs_event_t* handle) { return -ENOSYS; } @@ -449,7 +478,7 @@ int uv_resident_set_memory(size_t* rss) { *rss = (size_t)psinfo.pr_rssize * 1024; err = 0; } - close(fd); + uv__close(fd); return err; } @@ -511,13 +540,13 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { cpu_info->speed = 0; cpu_info->model = NULL; } else { - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "clock_MHz"); + knp = kstat_data_lookup(ksp, (char*) "clock_MHz"); assert(knp->data_type == KSTAT_DATA_INT32 || knp->data_type == KSTAT_DATA_INT64); cpu_info->speed = (knp->data_type == KSTAT_DATA_INT32) ? knp->value.i32 : knp->value.i64; - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "brand"); + knp = kstat_data_lookup(ksp, (char*) "brand"); assert(knp->data_type == KSTAT_DATA_STRING); cpu_info->model = strdup(KSTAT_NAMED_STR_PTR(knp)); } @@ -528,7 +557,11 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { cpu_info = *cpu_infos; lookup_instance = 0; - while ((ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys"))){ + for (;;) { + ksp = kstat_lookup(kc, (char*) "cpu", lookup_instance, (char*) "sys"); + + if (ksp == NULL) + break; if (kstat_read(kc, ksp, NULL) == -1) { cpu_info->cpu_times.user = 0; @@ -537,19 +570,19 @@ int uv_cpu_info(uv_cpu_info_t** cpu_infos, int* count) { cpu_info->cpu_times.idle = 0; cpu_info->cpu_times.irq = 0; } else { - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "cpu_ticks_user"); + knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_user"); assert(knp->data_type == KSTAT_DATA_UINT64); cpu_info->cpu_times.user = knp->value.ui64; - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel"); + knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_kernel"); assert(knp->data_type == KSTAT_DATA_UINT64); cpu_info->cpu_times.sys = knp->value.ui64; - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "cpu_ticks_idle"); + knp = kstat_data_lookup(ksp, (char*) "cpu_ticks_idle"); assert(knp->data_type == KSTAT_DATA_UINT64); cpu_info->cpu_times.idle = knp->value.ui64; - knp = (kstat_named_t*) kstat_data_lookup(ksp, (char*) "intr"); + knp = kstat_data_lookup(ksp, (char*) "intr"); assert(knp->data_type == KSTAT_DATA_UINT64); cpu_info->cpu_times.irq = knp->value.ui64; cpu_info->cpu_times.nice = 0; diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c index 8ff26dc..e5f226c 100644 --- a/deps/uv/src/unix/tcp.c +++ b/deps/uv/src/unix/tcp.c @@ -48,7 +48,7 @@ static int maybe_new_socket(uv_tcp_t* handle, int domain, int flags) { err = uv__stream_open((uv_stream_t*) handle, sockfd, flags); if (err) { - close(sockfd); + uv__close(sockfd); return err; } diff --git a/deps/uv/src/unix/tty.c b/deps/uv/src/unix/tty.c index 91baa6a..ca9459d 100644 --- a/deps/uv/src/unix/tty.c +++ b/deps/uv/src/unix/tty.c @@ -21,6 +21,7 @@ #include "uv.h" #include "internal.h" +#include "spinlock.h" #include #include @@ -28,9 +29,9 @@ #include #include - static int orig_termios_fd = -1; static struct termios orig_termios; +static uv_spinlock_t termios_spinlock = UV_SPINLOCK_INITIALIZER; int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { @@ -64,18 +65,17 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) { fd = uv__stream_fd(tty); - if (mode && tty->mode == 0) { - /* on */ - - if (tcgetattr(fd, &tty->orig_termios)) { - goto fatal; - } + if (mode && tty->mode == 0) { /* on */ + if (tcgetattr(fd, &tty->orig_termios)) + return -errno; /* This is used for uv_tty_reset_mode() */ + uv_spinlock_lock(&termios_spinlock); if (orig_termios_fd == -1) { orig_termios = tty->orig_termios; orig_termios_fd = fd; } + uv_spinlock_unlock(&termios_spinlock); raw = tty->orig_termios; raw.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON); @@ -86,26 +86,18 @@ int uv_tty_set_mode(uv_tty_t* tty, int mode) { raw.c_cc[VTIME] = 0; /* Put terminal in raw mode after draining */ - if (tcsetattr(fd, TCSADRAIN, &raw)) { - goto fatal; - } + if (tcsetattr(fd, TCSADRAIN, &raw)) + return -errno; tty->mode = 1; - return 0; - } else if (mode == 0 && tty->mode) { - /* off */ - + } else if (mode == 0 && tty->mode) { /* off */ /* Put terminal in original mode after flushing */ - if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios)) { - goto fatal; - } - + if (tcsetattr(fd, TCSAFLUSH, &tty->orig_termios)) + return -errno; tty->mode = 0; - return 0; } -fatal: - return -errno; + return 0; } @@ -172,8 +164,21 @@ uv_handle_type uv_guess_handle(uv_file file) { } -void uv_tty_reset_mode(void) { - if (orig_termios_fd >= 0) { - tcsetattr(orig_termios_fd, TCSANOW, &orig_termios); - } +/* This function is async signal-safe, meaning that it's safe to call from + * inside a signal handler _unless_ execution was inside uv_tty_set_mode()'s + * critical section when the signal was raised. + */ +int uv_tty_reset_mode(void) { + int err; + + if (!uv_spinlock_trylock(&termios_spinlock)) + return -EBUSY; /* In uv_tty_set_mode(). */ + + err = 0; + if (orig_termios_fd != -1) + if (tcsetattr(orig_termios_fd, TCSANOW, &orig_termios)) + err = -errno; + + uv_spinlock_unlock(&termios_spinlock); + return err; } diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 47e8b03..a2b3dc3 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -40,8 +40,11 @@ static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain); void uv__udp_close(uv_udp_t* handle) { uv__io_close(handle->loop, &handle->io_watcher); uv__handle_stop(handle); - close(handle->io_watcher.fd); - handle->io_watcher.fd = -1; + + if (handle->io_watcher.fd != -1) { + uv__close(handle->io_watcher.fd); + handle->io_watcher.fd = -1; + } } @@ -337,7 +340,7 @@ int uv__udp_bind(uv_udp_t* handle, return 0; out: - close(handle->io_watcher.fd); + uv__close(handle->io_watcher.fd); handle->io_watcher.fd = -1; return err; } diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index e7f56fc..7ca1ab1 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -31,7 +31,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 11 -#define UV_VERSION_PATCH 13 +#define UV_VERSION_PATCH 14 #define UV_VERSION_IS_RELEASE 1 diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 16373da..4a9eca2 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -272,19 +272,13 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { else poll = &uv_poll; - if (!uv__loop_alive(loop)) - return 0; - r = uv__loop_alive(loop); while (r != 0 && loop->stop_flag == 0) { uv_update_time(loop); uv_process_timers(loop); uv_process_reqs(loop); - uv_process_endgames(loop); - uv_idle_invoke(loop); - uv_prepare_invoke(loop); (*poll)(loop, loop->idle_handles == NULL && @@ -296,6 +290,7 @@ int uv_run(uv_loop_t *loop, uv_run_mode mode) { !(mode & UV_RUN_NOWAIT)); uv_check_invoke(loop); + uv_process_endgames(loop); if (mode == UV_RUN_ONCE) { /* UV_RUN_ONCE implies forward progess: at least one callback must have diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index 0937664..3162bc7 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "uv.h" #include "internal.h" @@ -162,6 +163,7 @@ int uv_translate_sys_error(int sys_errno) { case WSAETIMEDOUT: return UV_ETIMEDOUT; case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; case ERROR_INVALID_FUNCTION: return UV_EISDIR; + case ERROR_META_EXPANSION_TOO_LONG: return UV_E2BIG; default: return UV_UNKNOWN; } } diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c index 39aa9c8..2a09bf4 100644 --- a/deps/uv/src/win/fs-event.c +++ b/deps/uv/src/win/fs-event.c @@ -34,30 +34,6 @@ const unsigned int uv_directory_watcher_buffer_size = 4096; -static void uv_fs_event_init_handle(uv_loop_t* loop, uv_fs_event_t* handle, - const char* filename, uv_fs_event_cb cb) { - uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT); - handle->cb = cb; - handle->dir_handle = INVALID_HANDLE_VALUE; - handle->buffer = NULL; - handle->req_pending = 0; - handle->filew = NULL; - handle->short_filew = NULL; - handle->dirw = NULL; - - uv_req_init(loop, (uv_req_t*)&handle->req); - handle->req.type = UV_FS_EVENT_REQ; - handle->req.data = (void*)handle; - - handle->filename = strdup(filename); - if (!handle->filename) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } - - uv__handle_start(handle); -} - - static void uv_fs_event_queue_readdirchanges(uv_loop_t* loop, uv_fs_event_t* handle) { assert(handle->dir_handle != INVALID_HANDLE_VALUE); @@ -131,14 +107,42 @@ static int uv_split_path(const WCHAR* filename, WCHAR** dir, } -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, - const char* filename, uv_fs_event_cb cb, int flags) { +int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) { + uv__handle_init(loop, (uv_handle_t*) handle, UV_FS_EVENT); + handle->dir_handle = INVALID_HANDLE_VALUE; + handle->buffer = NULL; + handle->req_pending = 0; + handle->filew = NULL; + handle->short_filew = NULL; + handle->dirw = NULL; + + uv_req_init(loop, (uv_req_t*)&handle->req); + handle->req.type = UV_FS_EVENT_REQ; + handle->req.data = handle; + + return 0; +} + + +int uv_fs_event_start(uv_fs_event_t* handle, + uv_fs_event_cb cb, + const char* filename, + unsigned int flags) { int name_size, is_path_dir; DWORD attr, last_error; WCHAR* dir = NULL, *dir_to_watch, *filenamew = NULL; WCHAR short_path[MAX_PATH]; - uv_fs_event_init_handle(loop, handle, filename, cb); + if (uv__is_active(handle)) + return UV_EINVAL; + + handle->cb = cb; + handle->filename = strdup(filename); + if (!handle->filename) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); + } + + uv__handle_start(handle); /* Convert name to UTF16. */ name_size = uv_utf8_to_utf16(filename, NULL, 0) * sizeof(WCHAR); @@ -213,15 +217,17 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, } if (CreateIoCompletionPort(handle->dir_handle, - loop->iocp, + handle->loop->iocp, (ULONG_PTR)handle, 0) == NULL) { last_error = GetLastError(); goto error; } - handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size, - sizeof(DWORD)); + if (!handle->buffer) { + handle->buffer = (char*)_aligned_malloc(uv_directory_watcher_buffer_size, + sizeof(DWORD)); + } if (!handle->buffer) { uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } @@ -282,6 +288,41 @@ error: } +int uv_fs_event_stop(uv_fs_event_t* handle) { + if (!uv__is_active(handle)) + return UV_EINVAL; + + if (handle->dir_handle != INVALID_HANDLE_VALUE) { + CloseHandle(handle->dir_handle); + handle->dir_handle = INVALID_HANDLE_VALUE; + } + + uv__handle_stop(handle); + + if (handle->filew) { + free(handle->filew); + handle->filew = NULL; + } + + if (handle->short_filew) { + free(handle->short_filew); + handle->short_filew = NULL; + } + + if (handle->filename) { + free(handle->filename); + handle->filename = NULL; + } + + if (handle->dirw) { + free(handle->dirw); + handle->dirw = NULL; + } + + return 0; +} + + void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; @@ -294,12 +335,16 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, assert(handle->req_pending); handle->req_pending = 0; - /* If we're closing, don't report any callbacks, and just push the handle */ - /* onto the endgame queue. */ - if (handle->flags & UV__HANDLE_CLOSING) { - uv_want_endgame(loop, (uv_handle_t*) handle); + /* Don't report any callbacks if: + * - We're closing, just push the handle onto the endgame queue + * - We are not active, just ignore the callback + */ + if (!uv__is_active(handle)) { + if (handle->flags & UV__HANDLE_CLOSING) { + uv_want_endgame(loop, (uv_handle_t*) handle); + } return; - }; + } file_info = (FILE_NOTIFY_INFORMATION*)(handle->buffer + offset); @@ -456,22 +501,19 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, void uv_fs_event_close(uv_loop_t* loop, uv_fs_event_t* handle) { - if (handle->dir_handle != INVALID_HANDLE_VALUE) { - CloseHandle(handle->dir_handle); - handle->dir_handle = INVALID_HANDLE_VALUE; - } + uv_fs_event_stop(handle); + + uv__handle_closing(handle); if (!handle->req_pending) { uv_want_endgame(loop, (uv_handle_t*)handle); } - uv__handle_closing(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) { @@ -479,26 +521,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle) { handle->buffer = NULL; } - if (handle->filew) { - free(handle->filew); - handle->filew = NULL; - } - - if (handle->short_filew) { - free(handle->short_filew); - handle->short_filew = NULL; - } - - if (handle->filename) { - free(handle->filename); - handle->filename = NULL; - } - - if (handle->dirw) { - free(handle->dirw); - handle->dirw = NULL; - } - uv__handle_close(handle); } } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 0475f43..a51f8f0 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -42,27 +42,35 @@ #define QUEUE_FS_TP_JOB(loop, req) \ - if (!QueueUserWorkItem(&uv_fs_thread_proc, \ - req, \ - WT_EXECUTEDEFAULT)) { \ - return uv_translate_sys_error(GetLastError()); \ - } \ - uv__req_register(loop, req); + do { \ + if (!QueueUserWorkItem(&uv_fs_thread_proc, \ + req, \ + WT_EXECUTEDEFAULT)) { \ + return uv_translate_sys_error(GetLastError()); \ + } \ + uv__req_register(loop, req); \ + } while (0) #define SET_REQ_RESULT(req, result_value) \ - req->result = (result_value); \ - if (req->result == -1) { \ - req->sys_errno_ = _doserrno; \ - req->result = uv_translate_sys_error(req->sys_errno_); \ - } + do { \ + req->result = (result_value); \ + if (req->result == -1) { \ + req->sys_errno_ = _doserrno; \ + req->result = uv_translate_sys_error(req->sys_errno_); \ + } \ + } while (0) #define SET_REQ_WIN32_ERROR(req, sys_errno) \ - req->sys_errno_ = (sys_errno); \ - req->result = uv_translate_sys_error(req->sys_errno_); \ + do { \ + req->sys_errno_ = (sys_errno); \ + req->result = uv_translate_sys_error(req->sys_errno_); \ + } while (0) #define SET_REQ_UV_ERROR(req, uv_errno, sys_errno) \ - req->result = (uv_errno); \ - req->sys_errno_ = (sys_errno); \ + do { \ + req->result = (uv_errno); \ + req->sys_errno_ = (sys_errno); \ + } while (0) #define VERIFY_FD(fd, req) \ if (fd == -1) { \ @@ -75,10 +83,10 @@ (*((uint64_t*) &(filetime)) - 116444736000000000ULL) #define FILETIME_TO_TIME_T(filetime) \ - (FILETIME_TO_UINT(filetime) / 10000000ULL); + (FILETIME_TO_UINT(filetime) / 10000000ULL) #define FILETIME_TO_TIME_NS(filetime, secs) \ - ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100); + ((FILETIME_TO_UINT(filetime) - (secs * 10000000ULL)) * 100) #define FILETIME_TO_TIMESPEC(ts, filetime) \ do { \ @@ -382,7 +390,7 @@ void fs__open(uv_fs_t* req) { DWORD disposition; DWORD attributes = 0; HANDLE file; - int result, current_umask; + int fd, current_umask; int flags = req->file_flags; /* Obtain the active umask. umask() never fails and returns the previous */ @@ -403,8 +411,7 @@ void fs__open(uv_fs_t* req) { access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; break; default: - result = -1; - goto end; + goto einval; } if (flags & _O_APPEND) { @@ -441,8 +448,7 @@ void fs__open(uv_fs_t* req) { disposition = CREATE_ALWAYS; break; default: - result = -1; - goto end; + goto einval; } attributes |= FILE_ATTRIBUTE_NORMAL; @@ -471,8 +477,7 @@ void fs__open(uv_fs_t* req) { attributes |= FILE_FLAG_RANDOM_ACCESS; break; default: - result = -1; - goto end; + goto einval; } /* Setting this flag makes it possible to open a directory. */ @@ -497,9 +502,27 @@ void fs__open(uv_fs_t* req) { } return; } - result = _open_osfhandle((intptr_t) file, flags); -end: - SET_REQ_RESULT(req, result); + + fd = _open_osfhandle((intptr_t) file, flags); + if (fd < 0) { + /* The only known failure mode for _open_osfhandle() is EMFILE, in which + * case GetLastError() will return zero. However we'll try to handle other + * errors as well, should they ever occur. + */ + if (errno == EMFILE) + SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES); + else if (GetLastError() != ERROR_SUCCESS) + SET_REQ_WIN32_ERROR(req, GetLastError()); + else + SET_REQ_WIN32_ERROR(req, UV_UNKNOWN); + return; + } + + SET_REQ_RESULT(req, fd); + return; + + einval: + SET_REQ_UV_ERROR(req, UV_EINVAL, ERROR_INVALID_PARAMETER); } void fs__close(uv_fs_t* req) { diff --git a/deps/uv/src/win/handle.c b/deps/uv/src/win/handle.c index 64ff1b2..2684820 100644 --- a/deps/uv/src/win/handle.c +++ b/deps/uv/src/win/handle.c @@ -21,6 +21,7 @@ #include #include +#include #include "uv.h" #include "internal.h" @@ -149,5 +150,5 @@ 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/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c index bf98b77..08f0167 100644 --- a/deps/uv/src/win/pipe.c +++ b/deps/uv/src/win/pipe.c @@ -70,7 +70,7 @@ static void eof_timer_close_cb(uv_handle_t* handle); static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - _snprintf(name, size, "\\\\.\\pipe\\uv\\%p-%d", ptr, GetCurrentProcessId()); + _snprintf(name, size, "\\\\.\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); } diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c index e77ce1c..5c792f2 100644 --- a/deps/uv/src/win/stream.c +++ b/deps/uv/src/win/stream.c @@ -209,10 +209,6 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle, uv_shutdown_cb cb) { return UV_EPIPE; } - if (!(handle->flags & UV_HANDLE_WRITABLE)) { - return UV_EPIPE; - } - uv_req_init(loop, (uv_req_t*) req); req->type = UV_SHUTDOWN; req->handle = handle; diff --git a/deps/uv/src/win/thread.c b/deps/uv/src/win/thread.c index 0631da5..5178f8f 100644 --- a/deps/uv/src/win/thread.c +++ b/deps/uv/src/win/thread.c @@ -21,6 +21,7 @@ #include #include +#include #include "uv.h" #include "internal.h" diff --git a/deps/uv/src/win/tty.c b/deps/uv/src/win/tty.c index d380cd0..8855af3 100644 --- a/deps/uv/src/win/tty.c +++ b/deps/uv/src/win/tty.c @@ -22,6 +22,7 @@ #include #include #include +#include #if defined(_MSC_VER) && _MSC_VER < 1600 # include "stdint-msvc2008.h" @@ -1866,7 +1867,7 @@ void uv_process_tty_connect_req(uv_loop_t* loop, uv_tty_t* handle, } -void uv_tty_reset_mode(void) { +int uv_tty_reset_mode(void) { /* Not necessary to do anything. */ - ; + return 0; } diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 49de701..31812e4 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -20,6 +20,7 @@ */ #include +#include #include "uv.h" #include "internal.h" @@ -488,7 +489,7 @@ void uv_process_udp_recv_req(uv_loop_t* loop, uv_udp_t* handle, &buf, (const struct sockaddr*) &from, UV_UDP_PARTIAL); - } if (err == WSAEWOULDBLOCK) { + } else if (err == WSAEWOULDBLOCK) { /* Kernel buffer empty */ handle->recv_cb(handle, 0, &buf, NULL, 0); } else if (err != WSAECONNRESET && err != WSAENETRESET) { diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c index bf1c70f..938b6d0 100644 --- a/deps/uv/src/win/winsock.c +++ b/deps/uv/src/win/winsock.c @@ -106,11 +106,11 @@ void uv_winsock_init() { if (dummy != INVALID_SOCKET) { opt_len = (int) sizeof protocol_info; - if (!getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) + if (getsockopt(dummy, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) uv_fatal_error(WSAGetLastError(), "getsockopt"); if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) @@ -129,11 +129,11 @@ void uv_winsock_init() { if (dummy != INVALID_SOCKET) { opt_len = (int) sizeof protocol_info; - if (!getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) + if (getsockopt(dummy, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) uv_fatal_error(WSAGetLastError(), "getsockopt"); if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) diff --git a/deps/uv/test/benchmark-async.c b/deps/uv/test/benchmark-async.c index 7d3c936..33d9ab4 100644 --- a/deps/uv/test/benchmark-async.c +++ b/deps/uv/test/benchmark-async.c @@ -86,7 +86,9 @@ static int test_async(int nthreads) { ctx->loop = uv_loop_new(); ASSERT(ctx->loop != NULL); ASSERT(0 == uv_async_init(ctx->loop, &ctx->worker_async, worker_async_cb)); - ASSERT(0 == uv_async_init(uv_default_loop(), &ctx->main_async, main_async_cb)); + ASSERT(0 == uv_async_init(uv_default_loop(), + &ctx->main_async, + main_async_cb)); ASSERT(0 == uv_thread_create(&ctx->thread, worker, ctx)); } diff --git a/deps/uv/test/benchmark-million-timers.c b/deps/uv/test/benchmark-million-timers.c index fe88734..64f4a10 100644 --- a/deps/uv/test/benchmark-million-timers.c +++ b/deps/uv/test/benchmark-million-timers.c @@ -22,7 +22,7 @@ #include "task.h" #include "uv.h" -#define NUM_TIMERS (1000 * 1000) +#define NUM_TIMERS (10 * 1000 * 1000) static int timer_cb_called; static int close_cb_called; @@ -41,8 +41,10 @@ static void close_cb(uv_handle_t* handle) { BENCHMARK_IMPL(million_timers) { uv_timer_t* timers; uv_loop_t* loop; - uint64_t before; - uint64_t after; + uint64_t before_all; + uint64_t before_run; + uint64_t after_run; + uint64_t after_all; int timeout; int i; @@ -52,25 +54,31 @@ BENCHMARK_IMPL(million_timers) { loop = uv_default_loop(); timeout = 0; + before_all = uv_hrtime(); for (i = 0; i < NUM_TIMERS; i++) { if (i % 1000 == 0) timeout++; ASSERT(0 == uv_timer_init(loop, timers + i)); ASSERT(0 == uv_timer_start(timers + i, timer_cb, timeout, 0)); } - before = uv_hrtime(); + before_run = uv_hrtime(); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); - after = uv_hrtime(); + after_run = uv_hrtime(); for (i = 0; i < NUM_TIMERS; i++) uv_close((uv_handle_t*) (timers + i), close_cb); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); + after_all = uv_hrtime(); + ASSERT(timer_cb_called == NUM_TIMERS); ASSERT(close_cb_called == NUM_TIMERS); free(timers); - LOGF("%.2f seconds\n", (after - before) / 1e9); + LOGF("%.2f seconds total\n", (after_all - before_all) / 1e9); + LOGF("%.2f seconds init\n", (before_run - before_all) / 1e9); + LOGF("%.2f seconds dispatch\n", (after_run - before_run) / 1e9); + LOGF("%.2f seconds cleanup\n", (after_all - after_run) / 1e9); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/benchmark-ping-pongs.c b/deps/uv/test/benchmark-ping-pongs.c index a6306e3..d93e561 100644 --- a/deps/uv/test/benchmark-ping-pongs.c +++ b/deps/uv/test/benchmark-ping-pongs.c @@ -148,7 +148,9 @@ static void pinger_read_cb(uv_stream_t* tcp, if (pinger->state == 0) { pinger->pongs++; if (uv_now(loop) - start_time > TIME) { - uv_shutdown(&pinger->shutdown_req, (uv_stream_t*) tcp, pinger_shutdown_cb); + uv_shutdown(&pinger->shutdown_req, + (uv_stream_t*) tcp, + pinger_shutdown_cb); break; } else { pinger_write_ping(pinger); diff --git a/deps/uv/test/benchmark-pound.c b/deps/uv/test/benchmark-pound.c index e8d8705..5879285 100644 --- a/deps/uv/test/benchmark-pound.c +++ b/deps/uv/test/benchmark-pound.c @@ -229,7 +229,10 @@ static void pipe_make_connect(conn_rec* p) { r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0); ASSERT(r == 0); - uv_pipe_connect(&((pipe_conn_rec*)p)->conn_req, (uv_pipe_t*)&p->stream, TEST_PIPENAME, connect_cb); + uv_pipe_connect(&((pipe_conn_rec*) p)->conn_req, + (uv_pipe_t*) &p->stream, + TEST_PIPENAME, + connect_cb); #if DEBUG printf("make connect %d\n", p->i); @@ -308,20 +311,40 @@ static int pound_it(int concurrency, BENCHMARK_IMPL(tcp4_pound_100) { - return pound_it(100, "tcp", tcp_do_setup, tcp_do_connect, tcp_make_connect, NULL); + return pound_it(100, + "tcp", + tcp_do_setup, + tcp_do_connect, + tcp_make_connect, + NULL); } BENCHMARK_IMPL(tcp4_pound_1000) { - return pound_it(1000, "tcp", tcp_do_setup, tcp_do_connect, tcp_make_connect, NULL); + return pound_it(1000, + "tcp", + tcp_do_setup, + tcp_do_connect, + tcp_make_connect, + NULL); } BENCHMARK_IMPL(pipe_pound_100) { - return pound_it(100, "pipe", pipe_do_setup, pipe_do_connect, pipe_make_connect, NULL); + return pound_it(100, + "pipe", + pipe_do_setup, + pipe_do_connect, + pipe_make_connect, + NULL); } BENCHMARK_IMPL(pipe_pound_1000) { - return pound_it(1000, "pipe", pipe_do_setup, pipe_do_connect, pipe_make_connect, NULL); + return pound_it(1000, + "pipe", + pipe_do_setup, + pipe_do_connect, + pipe_make_connect, + NULL); } diff --git a/deps/uv/test/benchmark-pump.c b/deps/uv/test/benchmark-pump.c index eda3c14..b557cd4 100644 --- a/deps/uv/test/benchmark-pump.c +++ b/deps/uv/test/benchmark-pump.c @@ -101,11 +101,16 @@ static void show_stats(uv_timer_t* handle, int status) { uv_update_time(loop); diff = uv_now(loop) - start_time; - LOGF("%s_pump%d_client: %.1f gbit/s\n", type == TCP ? "tcp" : "pipe", write_sockets, - gbit(nsent_total, diff)); + LOGF("%s_pump%d_client: %.1f gbit/s\n", + type == TCP ? "tcp" : "pipe", + write_sockets, + gbit(nsent_total, diff)); for (i = 0; i < write_sockets; i++) { - uv_close(type == TCP ? (uv_handle_t*)&tcp_write_handles[i] : (uv_handle_t*)&pipe_write_handles[i], NULL); + if (type == TCP) + uv_close((uv_handle_t*) &tcp_write_handles[i], NULL); + else + uv_close((uv_handle_t*) &pipe_write_handles[i], NULL); } exit(0); @@ -123,8 +128,10 @@ static void read_show_stats(void) { uv_update_time(loop); diff = uv_now(loop) - start_time; - LOGF("%s_pump%d_server: %.1f gbit/s\n", type == TCP ? "tcp" : "pipe", max_read_sockets, - gbit(nrecv_total, diff)); + LOGF("%s_pump%d_server: %.1f gbit/s\n", + type == TCP ? "tcp" : "pipe", + max_read_sockets, + gbit(nrecv_total, diff)); } @@ -219,7 +226,10 @@ static void connect_cb(uv_connect_t* req, int status) { /* Yay! start writing */ for (i = 0; i < write_sockets; i++) { - do_write(type == TCP ? (uv_stream_t*)&tcp_write_handles[i] : (uv_stream_t*)&pipe_write_handles[i]); + if (type == TCP) + do_write((uv_stream_t*) &tcp_write_handles[i]); + else + do_write((uv_stream_t*) &pipe_write_handles[i]); } } } diff --git a/deps/uv/test/benchmark-udp-pummel.c b/deps/uv/test/benchmark-udp-pummel.c index f8f702c..d99250a 100644 --- a/deps/uv/test/benchmark-udp-pummel.c +++ b/deps/uv/test/benchmark-udp-pummel.c @@ -26,7 +26,7 @@ #include #include -#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN" /* "Take eight!" */ +#define EXPECTED "RANG TANG DING DONG I AM THE JAPANESE SANDMAN" #define TEST_DURATION 5000 /* ms */ diff --git a/deps/uv/test/dns-server.c b/deps/uv/test/dns-server.c index 8ffe4e7..8c70122 100644 --- a/deps/uv/test/dns-server.c +++ b/deps/uv/test/dns-server.c @@ -159,12 +159,16 @@ static void process_req(uv_stream_t* handle, /* process len and id */ if (readbuf_remaining < hdrbuf_remaining) { /* too little to get request header. save for next buffer */ - memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, readbuf_remaining); + memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], + dnsreq, + readbuf_remaining); hdrbuf_remaining = DNSREC_LEN - readbuf_remaining; break; } else { /* save header */ - memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], dnsreq, hdrbuf_remaining); + memcpy(&hdrbuf[DNSREC_LEN - hdrbuf_remaining], + dnsreq, + hdrbuf_remaining); dnsreq += hdrbuf_remaining; readbuf_remaining -= hdrbuf_remaining; hdrbuf_remaining = 0; @@ -192,7 +196,9 @@ static void process_req(uv_stream_t* handle, } } - /* if we had to use bytes from prev buffer, start processing the current one */ + /* If we had to use bytes from prev buffer, start processing the current + * one. + */ if (usingprev == 1) { /* free previous buffer */ free(dns->state.prevbuf_ptr); diff --git a/deps/uv/test/runner-win.c b/deps/uv/test/runner-win.c index 5d23259..83d7678 100644 --- a/deps/uv/test/runner-win.c +++ b/deps/uv/test/runner-win.c @@ -110,7 +110,9 @@ int process_start(char *name, char *part, process_info_t *p, int is_helper) { if (!SetHandleInformation(nul, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) goto error; - result = GetModuleFileNameW(NULL, (WCHAR*)&image, sizeof(image) / sizeof(WCHAR)); + result = GetModuleFileNameW(NULL, + (WCHAR*) &image, + sizeof(image) / sizeof(WCHAR)); if (result == 0 || result == sizeof(image)) goto error; @@ -214,8 +216,12 @@ int process_copy_output(process_info_t *p, int fd) { char buf[1024]; char *line, *start; - if (SetFilePointer(p->stdio_out, 0, 0, FILE_BEGIN) == INVALID_SET_FILE_POINTER) + if (SetFilePointer(p->stdio_out, + 0, + 0, + FILE_BEGIN) == INVALID_SET_FILE_POINTER) { return -1; + } if (tap_output) write(fd, "#", 1); @@ -337,8 +343,13 @@ static int clear_line() { if (!SetConsoleCursorPosition(handle, coord)) return -1; - if (!FillConsoleOutputCharacterW(handle, 0x20, info.dwSize.X, coord, &written)) + if (!FillConsoleOutputCharacterW(handle, + 0x20, + info.dwSize.X, + coord, + &written)) { return -1; + } return 0; } diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c index d8e9dde..f4d982c 100644 --- a/deps/uv/test/runner.c +++ b/deps/uv/test/runner.c @@ -410,7 +410,8 @@ static int compare_task(const void* va, const void* vb) { } -static int find_helpers(const task_entry_t* task, const task_entry_t** helpers) { +static int find_helpers(const task_entry_t* task, + const task_entry_t** helpers) { const task_entry_t* helper; int n_helpers; diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h index e050dca..8e7666a 100644 --- a/deps/uv/test/task.h +++ b/deps/uv/test/task.h @@ -153,7 +153,7 @@ enum test_status { return TEST_SKIP; \ } while (0) -#ifdef _WIN32 +#if defined _WIN32 && ! defined __GNUC__ #include diff --git a/deps/uv/test/test-active.c b/deps/uv/test/test-active.c index 1f3d5f1..0fae23c 100644 --- a/deps/uv/test/test-active.c +++ b/deps/uv/test/test-active.c @@ -47,31 +47,32 @@ TEST_IMPL(active) { r = uv_timer_init(uv_default_loop(), &timer); ASSERT(r == 0); - ASSERT(!uv_is_active((uv_handle_t*) &timer)); - ASSERT(!uv_is_closing((uv_handle_t*) &timer)); + /* uv_is_active() and uv_is_closing() should always return either 0 or 1. */ + ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); r = uv_timer_start(&timer, timer_cb, 1000, 0); ASSERT(r == 0); - ASSERT(uv_is_active((uv_handle_t*) &timer)); - ASSERT(!uv_is_closing((uv_handle_t*) &timer)); + ASSERT(1 == uv_is_active((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); r = uv_timer_stop(&timer); ASSERT(r == 0); - ASSERT(!uv_is_active((uv_handle_t*) &timer)); - ASSERT(!uv_is_closing((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); r = uv_timer_start(&timer, timer_cb, 1000, 0); ASSERT(r == 0); - ASSERT(uv_is_active((uv_handle_t*) &timer)); - ASSERT(!uv_is_closing((uv_handle_t*) &timer)); + ASSERT(1 == uv_is_active((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &timer)); uv_close((uv_handle_t*) &timer, close_cb); - ASSERT(!uv_is_active((uv_handle_t*) &timer)); - ASSERT(uv_is_closing((uv_handle_t*) &timer)); + ASSERT(0 == uv_is_active((uv_handle_t*) &timer)); + ASSERT(1 == uv_is_closing((uv_handle_t*) &timer)); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); diff --git a/deps/uv/test/test-close-order.c b/deps/uv/test/test-close-order.c new file mode 100644 index 0000000..e2f25f9 --- /dev/null +++ b/deps/uv/test/test-close-order.c @@ -0,0 +1,80 @@ +/* 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 "uv.h" +#include "task.h" + +static int check_cb_called; +static int timer_cb_called; +static int close_cb_called; + +static uv_check_t check_handle; +static uv_timer_t timer_handle1; +static uv_timer_t timer_handle2; + + +static void close_cb(uv_handle_t* handle) { + ASSERT(handle != NULL); + close_cb_called++; +} + + +/* check_cb should run before any close_cb */ +static void check_cb(uv_check_t* handle, int status) { + ASSERT(check_cb_called == 0); + ASSERT(timer_cb_called == 1); + ASSERT(close_cb_called == 0); + uv_close((uv_handle_t*) handle, close_cb); + uv_close((uv_handle_t*) &timer_handle2, close_cb); + check_cb_called++; +} + + +static void timer_cb(uv_timer_t* handle, int status) { + uv_close((uv_handle_t*) handle, close_cb); + timer_cb_called++; +} + + +TEST_IMPL(close_order) { + uv_loop_t* loop; + loop = uv_default_loop(); + + uv_check_init(loop, &check_handle); + uv_check_start(&check_handle, check_cb); + uv_timer_init(loop, &timer_handle1); + uv_timer_start(&timer_handle1, timer_cb, 0, 0); + uv_timer_init(loop, &timer_handle2); + uv_timer_start(&timer_handle2, timer_cb, 100000, 0); + + ASSERT(check_cb_called == 0); + ASSERT(close_cb_called == 0); + ASSERT(timer_cb_called == 0); + + uv_run(loop, UV_RUN_DEFAULT); + + ASSERT(check_cb_called == 1); + ASSERT(close_cb_called == 3); + ASSERT(timer_cb_called == 1); + + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c index 1df2569..66132e1 100644 --- a/deps/uv/test/test-fs-event.c +++ b/deps/uv/test/test-fs-event.c @@ -103,6 +103,7 @@ static void fs_event_cb_dir(uv_fs_event_t* handle, const char* filename, ASSERT(status == 0); ASSERT(events == UV_RENAME); ASSERT(filename == NULL || strcmp(filename, "file1") == 0); + ASSERT(0 == uv_fs_event_stop(handle)); uv_close((uv_handle_t*)handle, close_cb); } @@ -113,6 +114,7 @@ static void fs_event_cb_file(uv_fs_event_t* handle, const char* filename, ASSERT(status == 0); ASSERT(events == UV_CHANGE); ASSERT(filename == NULL || strcmp(filename, "file2") == 0); + ASSERT(0 == uv_fs_event_stop(handle)); uv_close((uv_handle_t*)handle, close_cb); } @@ -187,7 +189,9 @@ TEST_IMPL(fs_event_watch_dir) { remove("watch_dir/"); create_dir(loop, "watch_dir"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir, 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_dir", 0); ASSERT(r == 0); r = uv_timer_init(loop, &timer); ASSERT(r == 0); @@ -221,7 +225,9 @@ TEST_IMPL(fs_event_watch_file) { create_file(loop, "watch_dir/file1"); create_file(loop, "watch_dir/file2"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file, 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_cb_file, "watch_dir/file2", 0); ASSERT(r == 0); r = uv_timer_init(loop, &timer); ASSERT(r == 0); @@ -252,8 +258,10 @@ TEST_IMPL(fs_event_watch_file_twice) { loop = uv_default_loop(); timer.data = watchers; - ASSERT(0 == uv_fs_event_init(loop, watchers + 0, path, fail_cb, 0)); - ASSERT(0 == uv_fs_event_init(loop, watchers + 1, path, fail_cb, 0)); + ASSERT(0 == uv_fs_event_init(loop, watchers + 0)); + ASSERT(0 == uv_fs_event_start(watchers + 0, fail_cb, path, 0)); + ASSERT(0 == uv_fs_event_init(loop, watchers + 1)); + ASSERT(0 == uv_fs_event_start(watchers + 1, fail_cb, path, 0)); ASSERT(0 == uv_timer_init(loop, &timer)); ASSERT(0 == uv_timer_start(&timer, timer_cb_watch_twice, 10, 0)); ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT)); @@ -273,10 +281,15 @@ TEST_IMPL(fs_event_watch_file_current_dir) { remove("watch_file"); create_file(loop, "watch_file"); - r = uv_fs_event_init(loop, &fs_event, "watch_file", - fs_event_cb_file_current_dir, 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, + fs_event_cb_file_current_dir, + "watch_file", + 0); ASSERT(r == 0); + r = uv_timer_init(loop, &timer); ASSERT(r == 0); @@ -310,13 +323,15 @@ TEST_IMPL(fs_event_no_callback_after_close) { create_dir(loop, "watch_dir"); create_file(loop, "watch_dir/file1"); - r = uv_fs_event_init(loop, - &fs_event, - "watch_dir/file1", - fs_event_cb_file, - 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, + fs_event_cb_file, + "watch_dir/file1", + 0); ASSERT(r == 0); + uv_close((uv_handle_t*)&fs_event, close_cb); touch_file(loop, "watch_dir/file1"); uv_run(loop, UV_RUN_DEFAULT); @@ -342,11 +357,12 @@ TEST_IMPL(fs_event_no_callback_on_close) { create_dir(loop, "watch_dir"); create_file(loop, "watch_dir/file1"); - r = uv_fs_event_init(loop, - &fs_event, - "watch_dir/file1", - fs_event_cb_file, - 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, + fs_event_cb_file, + "watch_dir/file1", + 0); ASSERT(r == 0); uv_close((uv_handle_t*)&fs_event, close_cb); @@ -376,7 +392,9 @@ static void timer_cb(uv_timer_t* handle, int status) { ASSERT(status == 0); - r = uv_fs_event_init(handle->loop, &fs_event, ".", fs_event_fail, 0); + r = uv_fs_event_init(handle->loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_fail, ".", 0); ASSERT(r == 0); uv_close((uv_handle_t*)&fs_event, close_cb); @@ -415,7 +433,9 @@ TEST_IMPL(fs_event_close_with_pending_event) { create_dir(loop, "watch_dir"); create_file(loop, "watch_dir/file"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_fail, 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir", 0); ASSERT(r == 0); /* Generate an fs event. */ @@ -474,7 +494,9 @@ TEST_IMPL(fs_event_close_in_callback) { create_file(loop, "watch_dir/file4"); create_file(loop, "watch_dir/file5"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_close, 0); + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_cb_close, "watch_dir", 0); ASSERT(r == 0); /* Generate a couple of fs events. */ @@ -502,3 +524,35 @@ TEST_IMPL(fs_event_close_in_callback) { } #endif /* HAVE_KQUEUE */ + +TEST_IMPL(fs_event_start_and_close) { + uv_loop_t* loop; + uv_fs_event_t fs_event1; + uv_fs_event_t fs_event2; + int r; + + loop = uv_default_loop(); + + create_dir(loop, "watch_dir"); + + r = uv_fs_event_init(loop, &fs_event1); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event1, fs_event_cb_dir, "watch_dir", 0); + ASSERT(r == 0); + + r = uv_fs_event_init(loop, &fs_event2); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event2, fs_event_cb_dir, "watch_dir", 0); + ASSERT(r == 0); + + uv_close((uv_handle_t*) &fs_event2, close_cb); + uv_close((uv_handle_t*) &fs_event1, close_cb); + + uv_run(loop, UV_RUN_DEFAULT); + + ASSERT(close_cb_called == 2); + + remove("watch_dir/"); + MAKE_VALGRIND_HAPPY(); + return 0; +} diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c index 4a162ab..9213f04 100644 --- a/deps/uv/test/test-fs-poll.c +++ b/deps/uv/test/test-fs-poll.c @@ -81,7 +81,7 @@ static void poll_cb(uv_fs_poll_t* handle, memset(&zero_statbuf, 0, sizeof(zero_statbuf)); ASSERT(handle == &poll_handle); - ASSERT(uv_is_active((uv_handle_t*)handle)); + ASSERT(1 == uv_is_active((uv_handle_t*) handle)); ASSERT(prev != NULL); ASSERT(curr != NULL); diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index 5e02237..f0ff824 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -1333,7 +1333,12 @@ TEST_IMPL(fs_symlink) { close(link); - r = uv_fs_symlink(loop, &req, "test_file_symlink", "test_file_symlink_symlink", 0, NULL); + r = uv_fs_symlink(loop, + &req, + "test_file_symlink", + "test_file_symlink_symlink", + 0, + NULL); ASSERT(r == 0); uv_fs_req_cleanup(&req); @@ -1343,7 +1348,12 @@ TEST_IMPL(fs_symlink) { uv_fs_req_cleanup(&req); /* async link */ - r = uv_fs_symlink(loop, &req, "test_file", "test_file_symlink2", 0, symlink_cb); + r = uv_fs_symlink(loop, + &req, + "test_file", + "test_file_symlink2", + 0, + symlink_cb); ASSERT(r == 0); uv_run(loop, UV_RUN_DEFAULT); ASSERT(symlink_cb_count == 1); @@ -1362,7 +1372,12 @@ TEST_IMPL(fs_symlink) { close(link); - r = uv_fs_symlink(loop, &req, "test_file_symlink2", "test_file_symlink2_symlink", 0, NULL); + r = uv_fs_symlink(loop, + &req, + "test_file_symlink2", + "test_file_symlink2_symlink", + 0, + NULL); ASSERT(r == 0); uv_fs_req_cleanup(&req); diff --git a/deps/uv/test/test-get-currentexe.c b/deps/uv/test/test-get-currentexe.c index 8882732..be578db 100644 --- a/deps/uv/test/test-get-currentexe.c +++ b/deps/uv/test/test-get-currentexe.c @@ -47,7 +47,9 @@ TEST_IMPL(get_currentexe) { } match = strstr(buffer, path); - /* Verify that the path returned from uv_exepath is a subdirectory of executable_path */ + /* Verify that the path returned from uv_exepath is a subdirectory of + * executable_path. + */ ASSERT(match && !strcmp(match, path)); ASSERT(size == strlen(buffer)); diff --git a/deps/uv/test/test-ipc-send-recv.c b/deps/uv/test/test-ipc-send-recv.c index cbd6a95..73013eb 100644 --- a/deps/uv/test/test-ipc-send-recv.c +++ b/deps/uv/test/test-ipc-send-recv.c @@ -211,9 +211,9 @@ int ipc_send_recv_helper(void) { ASSERT(r == 0); uv_pipe_open(&ctx.channel, 0); - ASSERT(uv_is_readable((uv_stream_t*)&ctx.channel)); - ASSERT(uv_is_writable((uv_stream_t*)&ctx.channel)); - ASSERT(!uv_is_closing((uv_handle_t*)&ctx.channel)); + ASSERT(1 == uv_is_readable((uv_stream_t*)&ctx.channel)); + ASSERT(1 == uv_is_writable((uv_stream_t*)&ctx.channel)); + ASSERT(0 == uv_is_closing((uv_handle_t*)&ctx.channel)); r = uv_read2_start((uv_stream_t*)&ctx.channel, alloc_cb, read2_cb); ASSERT(r == 0); diff --git a/deps/uv/test/test-ipc.c b/deps/uv/test/test-ipc.c index d19affa..6826b04 100644 --- a/deps/uv/test/test-ipc.c +++ b/deps/uv/test/test-ipc.c @@ -559,9 +559,9 @@ int ipc_helper(int listen_after_write) { uv_pipe_open(&channel, 0); - ASSERT(uv_is_readable((uv_stream_t*) &channel)); - ASSERT(uv_is_writable((uv_stream_t*) &channel)); - ASSERT(!uv_is_closing((uv_handle_t*) &channel)); + ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); + ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); @@ -609,9 +609,9 @@ int ipc_helper_tcp_connection(void) { uv_pipe_open(&channel, 0); - ASSERT(uv_is_readable((uv_stream_t*)&channel)); - ASSERT(uv_is_writable((uv_stream_t*)&channel)); - ASSERT(!uv_is_closing((uv_handle_t*)&channel)); + ASSERT(1 == uv_is_readable((uv_stream_t*) &channel)); + ASSERT(1 == uv_is_writable((uv_stream_t*) &channel)); + ASSERT(0 == uv_is_closing((uv_handle_t*) &channel)); r = uv_tcp_init(uv_default_loop(), &tcp_server); ASSERT(r == 0); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 334b483..d963f04 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -21,6 +21,7 @@ TEST_DECLARE (platform_output) TEST_DECLARE (callback_order) +TEST_DECLARE (close_order) TEST_DECLARE (run_once) TEST_DECLARE (run_nowait) TEST_DECLARE (loop_stop) @@ -192,6 +193,7 @@ TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_event_immediate_close) TEST_DECLARE (fs_event_close_with_pending_event) TEST_DECLARE (fs_event_close_in_callback) +TEST_DECLARE (fs_event_start_and_close) TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_open_dir) @@ -242,6 +244,7 @@ TASK_LIST_START #if 0 TEST_ENTRY (callback_order) #endif + TEST_ENTRY (close_order) TEST_ENTRY (run_once) TEST_ENTRY (run_nowait) TEST_ENTRY (loop_stop) @@ -486,6 +489,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_immediate_close) TEST_ENTRY (fs_event_close_with_pending_event) TEST_ENTRY (fs_event_close_in_callback) + TEST_ENTRY (fs_event_start_and_close) TEST_ENTRY (fs_readdir_empty_dir) TEST_ENTRY (fs_readdir_file) TEST_ENTRY (fs_open_dir) diff --git a/deps/uv/test/test-loop-stop.c b/deps/uv/test/test-loop-stop.c index db52a09..c519644 100644 --- a/deps/uv/test/test-loop-stop.c +++ b/deps/uv/test/test-loop-stop.c @@ -62,7 +62,7 @@ TEST_IMPL(loop_stop) { r = uv_run(uv_default_loop(), UV_RUN_NOWAIT); ASSERT(r != 0); - ASSERT(prepare_called == 3); + ASSERT(prepare_called > 1); r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); diff --git a/deps/uv/test/test-ping-pong.c b/deps/uv/test/test-ping-pong.c index fb8f566..c579fdd 100644 --- a/deps/uv/test/test-ping-pong.c +++ b/deps/uv/test/test-ping-pong.c @@ -78,7 +78,11 @@ static void pinger_write_ping(pinger_t* pinger) { buf = uv_buf_init(PING, sizeof(PING) - 1); req = malloc(sizeof(*req)); - if (uv_write(req, (uv_stream_t*)&pinger->stream.tcp, &buf, 1, pinger_after_write)) { + if (uv_write(req, + (uv_stream_t*) &pinger->stream.tcp, + &buf, + 1, + pinger_after_write)) { FATAL("uv_write failed"); } @@ -135,9 +139,9 @@ static void pinger_on_connect(uv_connect_t *req, int status) { ASSERT(status == 0); - ASSERT(uv_is_readable(req->handle)); - ASSERT(uv_is_writable(req->handle)); - ASSERT(!uv_is_closing((uv_handle_t *)req->handle)); + ASSERT(1 == uv_is_readable(req->handle)); + ASSERT(1 == uv_is_writable(req->handle)); + ASSERT(0 == uv_is_closing((uv_handle_t *) req->handle)); pinger_write_ping(pinger); diff --git a/deps/uv/test/test-poll.c b/deps/uv/test/test-poll.c index 135c729..0736b9b 100644 --- a/deps/uv/test/test-poll.c +++ b/deps/uv/test/test-poll.c @@ -406,9 +406,9 @@ static void connection_poll_cb(uv_poll_t* handle, int status, int events) { /* Assert that uv_is_active works correctly for poll handles. */ if (context->events != 0) { - ASSERT(uv_is_active((uv_handle_t*) handle)); + ASSERT(1 == uv_is_active((uv_handle_t*) handle)); } else { - ASSERT(!uv_is_active((uv_handle_t*) handle)); + ASSERT(0 == uv_is_active((uv_handle_t*) handle)); } } @@ -418,7 +418,7 @@ static void delay_timer_cb(uv_timer_t* timer, int status) { int r; /* Timer should auto stop. */ - ASSERT(!uv_is_active((uv_handle_t*) timer)); + ASSERT(0 == uv_is_active((uv_handle_t*) timer)); /* Add the requested events to the poll mask. */ ASSERT(context->delayed_events != 0); diff --git a/deps/uv/test/test-ref.c b/deps/uv/test/test-ref.c index ca44ec4..7ff2e84 100644 --- a/deps/uv/test/test-ref.c +++ b/deps/uv/test/test-ref.c @@ -196,7 +196,8 @@ TEST_IMPL(timer_ref2) { TEST_IMPL(fs_event_ref) { uv_fs_event_t h; - uv_fs_event_init(uv_default_loop(), &h, ".", (uv_fs_event_cb)fail_cb, 0); + uv_fs_event_init(uv_default_loop(), &h); + uv_fs_event_start(&h, (uv_fs_event_cb)fail_cb, ".", 0); uv_unref((uv_handle_t*)&h); uv_run(uv_default_loop(), UV_RUN_DEFAULT); do_close(&h); diff --git a/deps/uv/test/test-shutdown-close.c b/deps/uv/test/test-shutdown-close.c index fd2d4b8..78c369b 100644 --- a/deps/uv/test/test-shutdown-close.c +++ b/deps/uv/test/test-shutdown-close.c @@ -56,9 +56,9 @@ static void connect_cb(uv_connect_t* req, int status) { r = uv_shutdown(&shutdown_req, req->handle, shutdown_cb); ASSERT(r == 0); - ASSERT(!uv_is_closing((uv_handle_t*) req->handle)); + ASSERT(0 == uv_is_closing((uv_handle_t*) req->handle)); uv_close((uv_handle_t*) req->handle, close_cb); - ASSERT(uv_is_closing((uv_handle_t*) req->handle)); + ASSERT(1 == uv_is_closing((uv_handle_t*) req->handle)); connect_cb_called++; } diff --git a/deps/uv/test/test-signal-multiple-loops.c b/deps/uv/test/test-signal-multiple-loops.c index c43e02b..e80154e 100644 --- a/deps/uv/test/test-signal-multiple-loops.c +++ b/deps/uv/test/test-signal-multiple-loops.c @@ -34,10 +34,20 @@ #include #include - -#define NUM_SIGNAL_HANDLING_THREADS 25 +/* The value of NUM_SIGNAL_HANDLING_THREADS is not arbitrary; it needs to be a + * multiple of three for reasons that will become clear when you scroll down. + * We're basically creating three different thread groups. The total needs + * to be divisible by three in order for the numbers in the final check to + * match up. + */ +#define NUM_SIGNAL_HANDLING_THREADS 24 #define NUM_LOOP_CREATING_THREADS 10 +enum signal_action { + ONLY_SIGUSR1, + ONLY_SIGUSR2, + SIGUSR1_AND_SIGUSR2 +}; static uv_sem_t sem; static uv_mutex_t counter_lock; @@ -70,18 +80,20 @@ static void signal2_cb(uv_signal_t* handle, int signum) { static void signal_handling_worker(void* context) { - uintptr_t mask = (uintptr_t) context; - uv_loop_t* loop; + enum signal_action action; uv_signal_t signal1a; uv_signal_t signal1b; uv_signal_t signal2; + uv_loop_t* loop; int r; + action = (enum signal_action) (uintptr_t) context; + loop = uv_loop_new(); ASSERT(loop != NULL); /* Setup the signal watchers and start them. */ - if (mask & SIGUSR1) { + if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { r = uv_signal_init(loop, &signal1a); ASSERT(r == 0); r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1); @@ -91,7 +103,8 @@ static void signal_handling_worker(void* context) { r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1); ASSERT(r == 0); } - if (mask & SIGUSR2) { + + if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { r = uv_signal_init(loop, &signal2); ASSERT(r == 0); r = uv_signal_start(&signal2, signal2_cb, SIGUSR2); @@ -108,13 +121,14 @@ static void signal_handling_worker(void* context) { ASSERT(r == 0); /* Restart the signal watchers. */ - if (mask & SIGUSR1) { + if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1); ASSERT(r == 0); r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1); ASSERT(r == 0); } - if (mask & SIGUSR2) { + + if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { r = uv_signal_start(&signal2, signal2_cb, SIGUSR2); ASSERT(r == 0); } @@ -126,11 +140,12 @@ static void signal_handling_worker(void* context) { ASSERT(r == 0); /* Close the watchers. */ - if (mask & SIGUSR1) { + if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) { uv_close((uv_handle_t*) &signal1a, NULL); uv_close((uv_handle_t*) &signal1b, NULL); } - if (mask & SIGUSR2) { + + if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) { uv_close((uv_handle_t*) &signal2, NULL); } @@ -177,10 +192,12 @@ static void loop_creating_worker(void* context) { TEST_IMPL(signal_multiple_loops) { - int i, r; uv_thread_t loop_creating_threads[NUM_LOOP_CREATING_THREADS]; uv_thread_t signal_handling_threads[NUM_SIGNAL_HANDLING_THREADS]; + enum signal_action action; sigset_t sigset; + int i; + int r; r = uv_sem_init(&sem, 0); ASSERT(r == 0); @@ -198,17 +215,15 @@ TEST_IMPL(signal_multiple_loops) { /* Create a couple of threads that actually handle signals. */ for (i = 0; i < NUM_SIGNAL_HANDLING_THREADS; i++) { - uintptr_t mask; - switch (i % 3) { - case 0: mask = SIGUSR1; break; - case 1: mask = SIGUSR2; break; - case 2: mask = SIGUSR1 | SIGUSR2; break; + case 0: action = ONLY_SIGUSR1; break; + case 1: action = ONLY_SIGUSR2; break; + case 2: action = SIGUSR1_AND_SIGUSR2; break; } r = uv_thread_create(&signal_handling_threads[i], signal_handling_worker, - (void*) mask); + (void*) (uintptr_t) action); ASSERT(r == 0); } @@ -256,8 +271,12 @@ TEST_IMPL(signal_multiple_loops) { printf("signal2_cb calls: %d\n", signal2_cb_counter); printf("loops created and destroyed: %d\n", loop_creation_counter); - ASSERT(signal1_cb_counter == 4 * NUM_SIGNAL_HANDLING_THREADS); - ASSERT(signal2_cb_counter == 2 * NUM_SIGNAL_HANDLING_THREADS); + /* The division by three reflects the fact that we spawn three different + * thread groups of (NUM_SIGNAL_HANDLING_THREADS / 3) threads each. + */ + ASSERT(signal1_cb_counter == 8 * (NUM_SIGNAL_HANDLING_THREADS / 3)); + ASSERT(signal2_cb_counter == 4 * (NUM_SIGNAL_HANDLING_THREADS / 3)); + /* We don't know exactly how much loops will be created and destroyed, but at * least there should be 1 for every loop creating thread. */ diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c index 97d08d5..454c181 100644 --- a/deps/uv/test/test-spawn.c +++ b/deps/uv/test/test-spawn.c @@ -113,7 +113,9 @@ static void kill_cb(uv_process_t* process, ASSERT(err == UV_ESRCH); } -static void detach_failure_cb(uv_process_t* process, int64_t exit_status, int term_signal) { +static void detach_failure_cb(uv_process_t* process, + int64_t exit_status, + int term_signal) { printf("detach_cb\n"); exit_cb_called++; } @@ -167,7 +169,7 @@ TEST_IMPL(spawn_fails) { init_process_options("", exit_cb_expect_enoent); options.file = options.args[0] = "program-that-had-better-not-exist"; ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options)); - ASSERT(0 != uv_is_active((uv_handle_t*)&process)); + ASSERT(1 == uv_is_active((uv_handle_t*) &process)); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); ASSERT(1 == exit_cb_called); @@ -630,7 +632,11 @@ TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { options.stdio_count = 2; /* Create a pipe that'll cause a collision. */ - _snprintf(name, sizeof(name), "\\\\.\\pipe\\uv\\%p-%d", &out, GetCurrentProcessId()); + _snprintf(name, + sizeof(name), + "\\\\.\\pipe\\uv\\%p-%d", + &out, + GetCurrentProcessId()); pipe_handle = CreateNamedPipeA(name, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, @@ -729,8 +735,12 @@ TEST_IMPL(argument_escaping) { wprintf(L" verbatim_output: %s\n", verbatim_output); wprintf(L"non_verbatim_output: %s\n", non_verbatim_output); - ASSERT(wcscmp(verbatim_output, L"cmd.exe /c c:\\path\\to\\node.exe --eval \"require('c:\\\\path\\\\to\\\\test.js')\"") == 0); - ASSERT(wcscmp(non_verbatim_output, L"cmd.exe /c \"c:\\path\\to\\node.exe --eval \\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0); + ASSERT(wcscmp(verbatim_output, + L"cmd.exe /c c:\\path\\to\\node.exe --eval " + L"\"require('c:\\\\path\\\\to\\\\test.js')\"") == 0); + ASSERT(wcscmp(non_verbatim_output, + L"cmd.exe /c \"c:\\path\\to\\node.exe --eval " + L"\\\"require('c:\\\\path\\\\to\\\\test.js')\\\"\"") == 0); free(verbatim_output); free(non_verbatim_output); @@ -758,17 +768,23 @@ TEST_IMPL(environment_creation) { WCHAR* env; for (i = 0; i < sizeof(environment) / sizeof(environment[0]) - 1; i++) { - ptr += uv_utf8_to_utf16(environment[i], ptr, expected + sizeof(expected) - ptr); + ptr += uv_utf8_to_utf16(environment[i], + ptr, + expected + sizeof(expected) - ptr); } memcpy(ptr, L"SYSTEMROOT=", sizeof(L"SYSTEMROOT=")); ptr += sizeof(L"SYSTEMROOT=")/sizeof(WCHAR) - 1; - ptr += GetEnvironmentVariableW(L"SYSTEMROOT", ptr, expected + sizeof(expected) - ptr); + ptr += GetEnvironmentVariableW(L"SYSTEMROOT", + ptr, + expected + sizeof(expected) - ptr); ++ptr; memcpy(ptr, L"SYSTEMDRIVE=", sizeof(L"SYSTEMDRIVE=")); ptr += sizeof(L"SYSTEMDRIVE=")/sizeof(WCHAR) - 1; - ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE", ptr, expected + sizeof(expected) - ptr); + ptr += GetEnvironmentVariableW(L"SYSTEMDRIVE", + ptr, + expected + sizeof(expected) - ptr); ++ptr; *ptr = '\0'; @@ -946,7 +962,7 @@ TEST_IMPL(spawn_auto_unref) { ASSERT(0 == uv_is_closing((uv_handle_t*) &process)); uv_close((uv_handle_t*) &process, NULL); ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); - ASSERT(0 != uv_is_closing((uv_handle_t*) &process)); + ASSERT(1 == uv_is_closing((uv_handle_t*) &process)); MAKE_VALGRIND_HAPPY(); return 0; } diff --git a/deps/uv/test/test-stdio-over-pipes.c b/deps/uv/test/test-stdio-over-pipes.c index 5f2226c..1574476 100644 --- a/deps/uv/test/test-stdio-over-pipes.c +++ b/deps/uv/test/test-stdio-over-pipes.c @@ -43,7 +43,6 @@ static int output_used; static void close_cb(uv_handle_t* handle) { - printf("close_cb\n"); close_cb_called++; } diff --git a/deps/uv/test/test-tcp-bind-error.c b/deps/uv/test/test-tcp-bind-error.c index 0cecede..42c0106 100644 --- a/deps/uv/test/test-tcp-bind-error.c +++ b/deps/uv/test/test-tcp-bind-error.c @@ -116,7 +116,8 @@ TEST_IMPL(tcp_bind_error_addrnotavail_2) { TEST_IMPL(tcp_bind_error_fault) { - char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah"; + char garbage[] = + "blah blah blah blah blah blah blah blah blah blah blah blah"; struct sockaddr_in* garbage_addr; uv_tcp_t server; int r; diff --git a/deps/uv/test/test-tcp-bind6-error.c b/deps/uv/test/test-tcp-bind6-error.c index 7eb2f05..0877219 100644 --- a/deps/uv/test/test-tcp-bind6-error.c +++ b/deps/uv/test/test-tcp-bind6-error.c @@ -92,7 +92,8 @@ TEST_IMPL(tcp_bind6_error_addrnotavail) { TEST_IMPL(tcp_bind6_error_fault) { - char garbage[] = "blah blah blah blah blah blah blah blah blah blah blah blah"; + char garbage[] = + "blah blah blah blah blah blah blah blah blah blah blah blah"; struct sockaddr_in6* garbage_addr; uv_tcp_t server; int r; diff --git a/deps/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c index 2616a13..1638da2 100644 --- a/deps/uv/test/test-timer-again.c +++ b/deps/uv/test/test-timer-again.c @@ -57,7 +57,7 @@ static void repeat_1_cb(uv_timer_t* handle, int status) { r = uv_timer_again(&repeat_2); ASSERT(r == 0); - if (uv_now(uv_default_loop()) >= start_time + 500) { + if (repeat_1_cb_called == 10) { uv_close((uv_handle_t*)handle, close_cb); /* We're not calling uv_timer_again on repeat_2 any more, so after this */ /* timer_2_cb is expected. */ @@ -78,7 +78,7 @@ static void repeat_2_cb(uv_timer_t* handle, int status) { repeat_2_cb_called++; if (uv_timer_get_repeat(&repeat_2) == 0) { - ASSERT(!uv_is_active((uv_handle_t*)handle)); + ASSERT(0 == uv_is_active((uv_handle_t*) handle)); uv_close((uv_handle_t*)handle, close_cb); return; } @@ -134,7 +134,6 @@ TEST_IMPL(timer_again) { LOGF("Test took %ld ms (expected ~700 ms)\n", (long int)(uv_now(uv_default_loop()) - start_time)); - ASSERT(700 <= uv_now(uv_default_loop()) - start_time); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-timer.c b/deps/uv/test/test-timer.c index 3954957..bbe69f6 100644 --- a/deps/uv/test/test-timer.c +++ b/deps/uv/test/test-timer.c @@ -38,7 +38,7 @@ static void once_close_cb(uv_handle_t* handle) { printf("ONCE_CLOSE_CB\n"); ASSERT(handle != NULL); - ASSERT(!uv_is_active(handle)); + ASSERT(0 == uv_is_active(handle)); once_close_cb_called++; } @@ -49,7 +49,7 @@ static void once_cb(uv_timer_t* handle, int status) { ASSERT(handle != NULL); ASSERT(status == 0); - ASSERT(!uv_is_active((uv_handle_t*)handle)); + ASSERT(0 == uv_is_active((uv_handle_t*) handle)); once_cb_called++; @@ -74,7 +74,7 @@ static void repeat_cb(uv_timer_t* handle, int status) { ASSERT(handle != NULL); ASSERT(status == 0); - ASSERT(uv_is_active((uv_handle_t*)handle)); + ASSERT(1 == uv_is_active((uv_handle_t*) handle)); repeat_cb_called++; @@ -163,7 +163,7 @@ TEST_IMPL(timer_init) { ASSERT(0 == uv_timer_init(uv_default_loop(), &handle)); ASSERT(0 == uv_timer_get_repeat(&handle)); - ASSERT(!uv_is_active((uv_handle_t*)&handle)); + ASSERT(0 == uv_is_active((uv_handle_t*) &handle)); MAKE_VALGRIND_HAPPY(); return 0; diff --git a/deps/uv/test/test-tty.c b/deps/uv/test/test-tty.c index c26f7fa..fb69910 100644 --- a/deps/uv/test/test-tty.c +++ b/deps/uv/test/test-tty.c @@ -65,12 +65,16 @@ TEST_IMPL(tty) { #else /* unix */ ttyin_fd = open("/dev/tty", O_RDONLY, 0); - if (ttyin_fd < 0) + if (ttyin_fd < 0) { LOGF("Cannot open /dev/tty as read-only: %s\n", strerror(errno)); + return TEST_SKIP; + } ttyout_fd = open("/dev/tty", O_WRONLY, 0); - if (ttyout_fd < 0) + if (ttyout_fd < 0) { LOGF("Cannot open /dev/tty as write-only: %s\n", strerror(errno)); + return TEST_SKIP; + } #endif ASSERT(ttyin_fd >= 0); diff --git a/deps/uv/test/test-udp-send-and-recv.c b/deps/uv/test/test-udp-send-and-recv.c index aa9a31c..3020ded 100644 --- a/deps/uv/test/test-udp-send-and-recv.c +++ b/deps/uv/test/test-udp-send-and-recv.c @@ -54,7 +54,7 @@ static void alloc_cb(uv_handle_t* handle, static void close_cb(uv_handle_t* handle) { CHECK_HANDLE(handle); - ASSERT(uv_is_closing(handle)); + ASSERT(1 == uv_is_closing(handle)); close_cb_called++; } diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 3c66243..74768a0 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -134,6 +134,7 @@ 'include/uv-darwin.h', 'include/uv-bsd.h', 'src/unix/async.c', + 'src/unix/atomic-ops.h', 'src/unix/core.c', 'src/unix/dl.c', 'src/unix/fs.c', @@ -145,6 +146,7 @@ 'src/unix/poll.c', 'src/unix/process.c', 'src/unix/signal.c', + 'src/unix/spinlock.h', 'src/unix/stream.c', 'src/unix/tcp.c', 'src/unix/thread.c', @@ -297,6 +299,7 @@ 'test/test-async-null-cb.c', 'test/test-callback-stack.c', 'test/test-callback-order.c', + 'test/test-close-order.c', 'test/test-connection-fail.c', 'test/test-cwd-and-chdir.c', 'test/test-delayed-accept.c', -- 2.7.4