summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimothy J Fontaine <tjfontaine@gmail.com>2014-02-26 18:08:30 -0800
committerTimothy J Fontaine <tjfontaine@gmail.com>2014-02-26 18:08:30 -0800
commitcd08c8a0e5e99ed4933b87fc5e188afcd4299f73 (patch)
treec05e93d47f89df1f7a782ee9c70bb2c97d557cd4
parentf3189ace6b5e31a874df421ac2f74da0e77cb14d (diff)
downloadandroid-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.tar.gz
android-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.tar.bz2
android-node-v8-cd08c8a0e5e99ed4933b87fc5e188afcd4299f73.zip
uv: Upgrade to v0.11.21
-rw-r--r--deps/uv/.gitignore13
-rw-r--r--deps/uv/.mailmap2
-rw-r--r--deps/uv/AUTHORS12
-rw-r--r--deps/uv/ChangeLog105
-rw-r--r--deps/uv/Makefile.am7
-rw-r--r--deps/uv/Makefile.mingw2
-rw-r--r--deps/uv/README.md2
-rwxr-xr-xdeps/uv/android-configure2
-rw-r--r--deps/uv/common.gypi6
-rw-r--r--deps/uv/configure.ac2
-rwxr-xr-xdeps/uv/gyp_uv.py4
-rw-r--r--deps/uv/include/uv-errno.h24
-rw-r--r--deps/uv/include/uv-unix.h24
-rw-r--r--deps/uv/include/uv-version.h38
-rw-r--r--deps/uv/include/uv-win.h5
-rw-r--r--deps/uv/include/uv.h233
-rw-r--r--deps/uv/src/fs-poll.c25
-rw-r--r--deps/uv/src/heap-inl.h238
-rw-r--r--deps/uv/src/unix/core.c32
-rw-r--r--deps/uv/src/unix/fs.c209
-rw-r--r--deps/uv/src/unix/fsevents.c2
-rw-r--r--deps/uv/src/unix/internal.h9
-rw-r--r--deps/uv/src/unix/kqueue.c10
-rw-r--r--deps/uv/src/unix/linux-core.c24
-rw-r--r--deps/uv/src/unix/linux-inotify.c6
-rw-r--r--deps/uv/src/unix/linux-syscalls.c36
-rw-r--r--deps/uv/src/unix/linux-syscalls.h2
-rw-r--r--deps/uv/src/unix/loop.c54
-rw-r--r--deps/uv/src/unix/pipe.c32
-rw-r--r--deps/uv/src/unix/process.c20
-rw-r--r--deps/uv/src/unix/stream.c16
-rw-r--r--deps/uv/src/unix/sunos.c24
-rw-r--r--deps/uv/src/unix/tcp.c4
-rw-r--r--deps/uv/src/unix/timer.c54
-rw-r--r--deps/uv/src/unix/udp.c25
-rw-r--r--deps/uv/src/uv-common.c20
-rw-r--r--deps/uv/src/version.c14
-rw-r--r--deps/uv/src/win/core.c65
-rw-r--r--deps/uv/src/win/fs-event.c50
-rw-r--r--deps/uv/src/win/fs.c124
-rw-r--r--deps/uv/src/win/pipe.c118
-rw-r--r--deps/uv/src/win/process.c6
-rw-r--r--deps/uv/src/win/stream.c3
-rw-r--r--deps/uv/src/win/tcp.c9
-rw-r--r--deps/uv/src/win/udp.c40
-rw-r--r--deps/uv/src/win/util.c37
-rw-r--r--deps/uv/test/benchmark-async.c10
-rw-r--r--deps/uv/test/benchmark-multi-accept.c13
-rw-r--r--deps/uv/test/run-benchmarks.c7
-rw-r--r--deps/uv/test/run-tests.c18
-rw-r--r--deps/uv/test/runner.c7
-rw-r--r--deps/uv/test/runner.h20
-rw-r--r--deps/uv/test/task.h4
-rw-r--r--deps/uv/test/test-embed.c11
-rw-r--r--deps/uv/test/test-fs-event.c49
-rw-r--r--deps/uv/test/test-fs-poll.c39
-rw-r--r--deps/uv/test/test-fs.c107
-rw-r--r--deps/uv/test/test-list.h26
-rw-r--r--deps/uv/test/test-loop-close.c54
-rw-r--r--deps/uv/test/test-pipe-getsockname.c122
-rw-r--r--deps/uv/test/test-platform-output.c15
-rw-r--r--deps/uv/test/test-shutdown-twice.c84
-rw-r--r--deps/uv/test/test-signal-multiple-loops.c26
-rw-r--r--deps/uv/test/test-spawn.c123
-rw-r--r--deps/uv/test/test-thread.c6
-rw-r--r--deps/uv/test/test-threadpool-cancel.c2
-rw-r--r--deps/uv/test/test-udp-multicast-interface.c96
-rw-r--r--deps/uv/uv.gyp14
-rw-r--r--deps/uv/vcbuild.bat13
69 files changed, 2267 insertions, 388 deletions
diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore
index d11c90bbf0..a2e2558115 100644
--- a/deps/uv/.gitignore
+++ b/deps/uv/.gitignore
@@ -43,12 +43,13 @@ Makefile.in
/out/
/build/gyp
-/run-tests
-/run-tests.exe
-/run-tests.dSYM
-/run-benchmarks
-/run-benchmarks.exe
-/run-benchmarks.dSYM
+/test/.libs/
+/test/run-tests
+/test/run-tests.exe
+/test/run-tests.dSYM
+/test/run-benchmarks
+/test/run-benchmarks.exe
+/test/run-benchmarks.dSYM
*.sln
*.vcproj
diff --git a/deps/uv/.mailmap b/deps/uv/.mailmap
index 0f1d843ce8..3b0e5f0925 100644
--- a/deps/uv/.mailmap
+++ b/deps/uv/.mailmap
@@ -12,9 +12,11 @@ Keno Fischer <kenof@stanford.edu> <kfischer+github@college.harvard.edu>
Keno Fischer <kenof@stanford.edu> <kfischer@college.harvard.edu>
Maciej Małecki <maciej.malecki@notimplemented.org> <me@mmalecki.com>
Marc Schlaich <marc.schlaich@googlemail.com> <marc.schlaich@gmail.com>
+Rasmus Pedersen <ruysch@outlook.com> <zerhacken@yahoo.com>
Robert Mustacchi <rm@joyent.com> <rm@fingolfin.org>
Ryan Dahl <ryan@joyent.com> <ry@tinyclouds.org>
Ryan Emery <seebees@gmail.com>
+Sam Roberts <vieuxtech@gmail.com> <sam@strongloop.com>
San-Tai Hsu <vanilla@fatpipi.com>
Saúl Ibarra Corretgé <saghul@gmail.com>
Shigeki Ohtsu <ohtsu@iij.ad.jp> <ohtsu@ohtsu.org>
diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS
index 6633f0651e..b6ea578694 100644
--- a/deps/uv/AUTHORS
+++ b/deps/uv/AUTHORS
@@ -111,4 +111,16 @@ Yazhong Liu <yorkiefixer@gmail.com>
Sam Roberts <vieuxtech@gmail.com>
River Tarnell <river@loreley.flyingparchment.org.uk>
Nathan Sweet <nathanjsweet@gmail.com>
+Alex Crichton <alex@alexcrichton.com>
+Luca Bruno <lucab@debian.org>
Trevor Norris <trev.norris@gmail.com>
+Oguz Bastemur <obastemur@gmail.com>
+Dylan Cali <calid1984@gmail.com>
+Austin Foxley <austinf@cetoncorp.com>
+Benjamin Saunders <ben.e.saunders@gmail.com>
+Geoffry Song <goffrie@gmail.com>
+Rasmus Pedersen <ruysch@outlook.com>
+William Light <wrl@illest.net>
+Oleg Efimov <o.efimov@corp.badoo.com>
+Lars Gierth <larsg@systemli.org>
+rcp <zerhacken@yahoo.com>
diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog
index dacd4d6588..a37b0e4766 100644
--- a/deps/uv/ChangeLog
+++ b/deps/uv/ChangeLog
@@ -1,4 +1,105 @@
-2014.01.23, Version 0.11.18 (Unstable)
+2014.02.28, Version 0.11.21 (Unstable)
+
+Changes since version 0.11.20:
+
+* unix: fix uv_fs_write when using an empty buffer (Saúl Ibarra Corretgé)
+
+* unix, windows: add assertion in uv_loop_delete (Saúl Ibarra Corretgé)
+
+
+2014.02.27, Version 0.11.20 (Unstable), 88355e081b51c69ee1e2b6b0015a4e3d38bd0579
+
+Changes since version 0.11.19:
+
+* stream: start thread after assignments (Oguz Bastemur)
+
+* fs: `uv__cloexec()` opened fd (Fedor Indutny)
+
+* gyp: qualify `library` variable (Fedor Indutny)
+
+* unix, win: add uv_udp_set_multicast_interface() (Austin Foxley)
+
+* unix: fix uv_tcp_nodelay return value in case of error (Saúl Ibarra Corretgé)
+
+* unix: call setgoups before calling setuid/setgid (Saúl Ibarra Corretgé)
+
+* include: mark close_cb field as private (Saúl Ibarra Corretgé)
+
+* unix, windows: map EFBIG errno (Saúl Ibarra Corretgé)
+
+* unix: correct error when calling uv_shutdown twice (Keno Fischer)
+
+* windows: fix building on MinGW (Alex Crichton)
+
+* windows: always initialize uv_process_t (Alex Crichton)
+
+* include: expose libuv version in header files (Saúl Ibarra Corretgé)
+
+* fs: vectored IO API for filesystem read/write (Benjamin Saunders)
+
+* windows: freeze in uv_tcp_endgame (Alexis Campailla)
+
+* sunos: handle rearm errors (Fedor Indutny)
+
+* unix: use a heap for timers (Ben Noordhuis)
+
+* linux: always deregister closing fds from epoll (Geoffry Song)
+
+* linux: include grp.h for setgroups() (William Light)
+
+* unix, windows: add uv_loop_init and uv_loop_close (Saúl Ibarra Corretgé)
+
+* unix, windows: add uv_getrusage() function (Oleg Efimov)
+
+* win: minor error handle fix to uv_pipe_write_impl (Rasmus Pedersen)
+
+* heap: fix node removal (Keno Fischer)
+
+* win: fix C99/C++ comment (Rasmus Pedersen)
+
+* fs: vectored IO API for filesystem read/write (Benjamin Saunders)
+
+* unix, windows: add uv_pipe_getsockname (Saúl Ibarra Corretgé)
+
+* unix, windows: map ENOPROTOOPT errno (Saúl Ibarra Corretgé)
+
+* errno: add ETXTBSY (Fedor Indutny)
+
+* fsevent: rename filename field to path (Saúl Ibarra Corretgé)
+
+* unix, windows: add uv_fs_event_getpath (Saúl Ibarra Corretgé)
+
+* unix, windows: add uv_fs_poll_getpath (Saúl Ibarra Corretgé)
+
+* unix, windows: map ERANGE errno (Saúl Ibarra Corretgé)
+
+* unix, windows: set required size on UV_ENOBUFS (Saúl Ibarra Corretgé)
+
+* unix, windows: clarify what uv_stream_set_blocking does (Saúl Ibarra
+ Corretgé)
+
+* fs: use preadv on Linux if available (Brian White)
+
+
+2014.01.30, Version 0.11.19 (Unstable), 336a1825309744f920230ec3e427e78571772347
+
+Changes since version 0.11.18:
+
+* linux: move sscanf() out of the assert() (Trevor Norris)
+
+* linux: fix C99/C++ comment (Fedor Indutny)
+
+
+2014.01.30, Version 0.10.24 (Stable), aecd296b6bce9b40f06a61c5c94e43d45ac7308a
+
+Changes since version 0.10.23:
+
+* linux: move sscanf() out of the assert() (Trevor Norris)
+
+* linux: fix C99/C++ comment (Fedor Indutny)
+
+
+2014.01.23, Version 0.11.18 (Unstable), d47962e9d93d4a55a9984623feaf546406c9cdbb
Changes since version 0.11.17:
@@ -21,7 +122,7 @@ Changes since version 0.11.17:
* linux: move sscanf() out of the assert() (Trevor Norris)
-2014.01.23, Version 0.10.23 (Stable)
+2014.01.23, Version 0.10.23 (Stable), dbd218e699fec8be311d85e4788be9e28ae884f8
Changes since version 0.10.22:
diff --git a/deps/uv/Makefile.am b/deps/uv/Makefile.am
index c1eae8cea0..75ec751b15 100644
--- a/deps/uv/Makefile.am
+++ b/deps/uv/Makefile.am
@@ -17,7 +17,7 @@ ACLOCAL_AMFLAGS = -I m4
AM_CPPFLAGS = -I$(top_srcdir)/include \
-I$(top_srcdir)/src
-include_HEADERS=include/uv.h include/uv-errno.h
+include_HEADERS=include/uv.h include/uv-errno.h include/uv-version.h
CLEANFILES =
@@ -25,6 +25,7 @@ lib_LTLIBRARIES = libuv.la
libuv_la_CFLAGS = @CFLAGS@
libuv_la_LDFLAGS = -no-undefined -version-info 11:0:0
libuv_la_SOURCES = src/fs-poll.c \
+ src/heap-inl.h \
src/inet.c \
src/queue.h \
src/uv-common.c \
@@ -146,6 +147,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-list.h \
test/test-loop-handles.c \
test/test-loop-alive.c \
+ test/test-loop-close.c \
test/test-loop-stop.c \
test/test-loop-time.c \
test/test-multiple-listen.c \
@@ -155,6 +157,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-ping-pong.c \
test/test-pipe-bind-error.c \
test/test-pipe-connect-error.c \
+ test/test-pipe-getsockname.c \
test/test-pipe-server-close.c \
test/test-platform-output.c \
test/test-poll-close.c \
@@ -166,6 +169,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-semaphore.c \
test/test-shutdown-close.c \
test/test-shutdown-eof.c \
+ test/test-shutdown-twice.c \
test/test-signal-multiple-loops.c \
test/test-signal.c \
test/test-spawn.c \
@@ -196,6 +200,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-tty.c \
test/test-udp-dgram-too-big.c \
test/test-udp-ipv6.c \
+ test/test-udp-multicast-interface.c \
test/test-udp-multicast-join.c \
test/test-udp-multicast-ttl.c \
test/test-udp-open.c \
diff --git a/deps/uv/Makefile.mingw b/deps/uv/Makefile.mingw
index 28a1e274d5..b424f906df 100644
--- a/deps/uv/Makefile.mingw
+++ b/deps/uv/Makefile.mingw
@@ -26,8 +26,10 @@ CFLAGS += -Wall \
INCLUDES = include/stdint-msvc2008.h \
include/tree.h \
include/uv-errno.h \
+ include/uv-version.h \
include/uv-win.h \
include/uv.h \
+ src/heap-inl.h \
src/queue.h \
src/uv-common.h \
src/win/atomicops-inl.h \
diff --git a/deps/uv/README.md b/deps/uv/README.md
index 5704c39e27..00b539ca14 100644
--- a/deps/uv/README.md
+++ b/deps/uv/README.md
@@ -133,7 +133,7 @@ OS X using the GCC or XCode toolchain.
Solaris 121 and later using GCC toolchain.
-## patches
+## Patches
See the [guidelines for contributing][].
diff --git a/deps/uv/android-configure b/deps/uv/android-configure
index 56625761fd..9750581206 100755
--- a/deps/uv/android-configure
+++ b/deps/uv/android-configure
@@ -3,7 +3,7 @@
export TOOLCHAIN=$PWD/android-toolchain
mkdir -p $TOOLCHAIN
$1/build/tools/make-standalone-toolchain.sh \
- --toolchain=arm-linux-androideabi-4.7 \
+ --toolchain=arm-linux-androideabi-4.8 \
--arch=arm \
--install-dir=$TOOLCHAIN \
--platform=android-9
diff --git a/deps/uv/common.gypi b/deps/uv/common.gypi
index 7adbbbdcc9..a0e0eea06f 100644
--- a/deps/uv/common.gypi
+++ b/deps/uv/common.gypi
@@ -3,7 +3,7 @@
'visibility%': 'hidden', # V8's visibility setting
'target_arch%': 'ia32', # set v8's target architecture
'host_arch%': 'ia32', # set v8's host architecture
- 'library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
+ 'uv_library%': 'static_library', # allow override to 'shared_library' for DLL/.so builds
'component%': 'static_library', # NB. these names match with what V8 expects
'msvs_multi_core_compile': '0', # we do enable multicore compiles, but not using the V8 way
'gcc_version%': 'unknown',
@@ -19,7 +19,7 @@
'msvs_settings': {
'VCCLCompilerTool': {
'target_conditions': [
- ['library=="static_library"', {
+ ['uv_library=="static_library"', {
'RuntimeLibrary': 1, # static debug
}, {
'RuntimeLibrary': 3, # DLL debug
@@ -56,7 +56,7 @@
'msvs_settings': {
'VCCLCompilerTool': {
'target_conditions': [
- ['library=="static_library"', {
+ ['uv_library=="static_library"', {
'RuntimeLibrary': 0, # static release
}, {
'RuntimeLibrary': 2, # debug release
diff --git a/deps/uv/configure.ac b/deps/uv/configure.ac
index 9aff4e9012..2b6eadfd8e 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.18], [https://github.com/joyent/libuv/issues])
+AC_INIT([libuv], [0.11.21], [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/gyp_uv.py b/deps/uv/gyp_uv.py
index 4ba69167d9..f0c59d0786 100755
--- a/deps/uv/gyp_uv.py
+++ b/deps/uv/gyp_uv.py
@@ -88,8 +88,8 @@ if __name__ == '__main__':
if not any(a.startswith('-Dtarget_arch=') for a in args):
args.append('-Dtarget_arch=%s' % host_arch())
- if not any(a.startswith('-Dlibrary=') for a in args):
- args.append('-Dlibrary=static_library')
+ if not any(a.startswith('-Duv_library=') for a in args):
+ args.append('-Duv_library=static_library')
if not any(a.startswith('-Dcomponent=') for a in args):
args.append('-Dcomponent=static_library')
diff --git a/deps/uv/include/uv-errno.h b/deps/uv/include/uv-errno.h
index 797bcab93b..466cdf2ca0 100644
--- a/deps/uv/include/uv-errno.h
+++ b/deps/uv/include/uv-errno.h
@@ -364,10 +364,34 @@
# define UV__ETIMEDOUT (-4039)
#endif
+#if defined(ETXTBSY) && !defined(_WIN32)
+# define UV__ETXTBSY (-ETXTBSY)
+#else
+# define UV__ETXTBSY (-4038)
+#endif
+
#if defined(EXDEV) && !defined(_WIN32)
# define UV__EXDEV (-EXDEV)
#else
# define UV__EXDEV (-4037)
#endif
+#if defined(EFBIG) && !defined(_WIN32)
+# define UV__EFBIG (-EFBIG)
+#else
+# define UV__EFBIG (-4036)
+#endif
+
+#if defined(ENOPROTOOPT) && !defined(_WIN32)
+# define UV__ENOPROTOOPT (-ENOPROTOOPT)
+#else
+# define UV__ENOPROTOOPT (-4035)
+#endif
+
+#if defined(ERANGE) && !defined(_WIN32)
+# define UV__ERANGE (-ERANGE)
+#else
+# define UV__ERANGE (-4034)
+#endif
+
#endif /* UV_ERRNO_H_ */
diff --git a/deps/uv/include/uv-unix.h b/deps/uv/include/uv-unix.h
index 45006092be..eea5a3f535 100644
--- a/deps/uv/include/uv-unix.h
+++ b/deps/uv/include/uv-unix.h
@@ -169,6 +169,7 @@ typedef struct {
void* wq[2]; \
uv_mutex_t wq_mutex; \
uv_async_t wq_async; \
+ uv_rwlock_t cloexec_lock; \
uv_handle_t* closing_handles; \
void* process_handles[1][2]; \
void* prepare_handles[2]; \
@@ -176,16 +177,16 @@ typedef struct {
void* idle_handles[2]; \
void* async_handles[2]; \
struct uv__async async_watcher; \
- /* RB_HEAD(uv__timers, uv_timer_s) */ \
- struct uv__timers { \
- struct uv_timer_s* rbh_root; \
- } timer_handles; \
+ struct { \
+ void* min; \
+ unsigned int nelts; \
+ } timer_heap; \
+ uint64_t timer_counter; \
uint64_t time; \
int signal_pipefd[2]; \
uv__io_t signal_io_watcher; \
uv_signal_t child_watcher; \
int emfile_fd; \
- uint64_t timer_counter; \
UV_PLATFORM_LOOP_FIELDS \
#define UV_REQ_TYPE_PRIVATE /* empty */
@@ -264,14 +265,8 @@ typedef struct {
int pending; \
#define UV_TIMER_PRIVATE_FIELDS \
- /* RB_ENTRY(uv_timer_s) tree_entry; */ \
- struct { \
- struct uv_timer_s* rbe_left; \
- struct uv_timer_s* rbe_right; \
- struct uv_timer_s* rbe_parent; \
- int rbe_color; \
- } tree_entry; \
uv_timer_cb timer_cb; \
+ void* heap_node[3]; \
uint64_t timeout; \
uint64_t repeat; \
uint64_t start_id;
@@ -294,14 +289,15 @@ typedef struct {
uv_file file; \
int flags; \
mode_t mode; \
- void* buf; \
- size_t len; \
+ unsigned int nbufs; \
+ uv_buf_t* bufs; \
off_t off; \
uv_uid_t uid; \
uv_gid_t gid; \
double atime; \
double mtime; \
struct uv__work work_req; \
+ uv_buf_t bufsml[4]; \
#define UV_WORK_PRIVATE_FIELDS \
struct uv__work work_req;
diff --git a/deps/uv/include/uv-version.h b/deps/uv/include/uv-version.h
new file mode 100644
index 0000000000..e48082fbb2
--- /dev/null
+++ b/deps/uv/include/uv-version.h
@@ -0,0 +1,38 @@
+/* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+#ifndef UV_VERSION_H
+#define UV_VERSION_H
+
+ /*
+ * Versions with an even minor version (e.g. 0.6.1 or 1.0.4) are API and ABI
+ * stable. When the minor version is odd, the API can change between patch
+ * releases. Make sure you update the -soname directives in configure.ac
+ * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
+ * not UV_VERSION_PATCH.)
+ */
+
+#define UV_VERSION_MAJOR 0
+#define UV_VERSION_MINOR 11
+#define UV_VERSION_PATCH 21
+#define UV_VERSION_IS_RELEASE 1
+
+#endif /* UV_VERSION_H */
diff --git a/deps/uv/include/uv-win.h b/deps/uv/include/uv-win.h
index e4e1f839f0..db8f861839 100644
--- a/deps/uv/include/uv-win.h
+++ b/deps/uv/include/uv-win.h
@@ -552,9 +552,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s);
WCHAR* new_pathw; \
int file_flags; \
int fd_out; \
- void* buf; \
- size_t length; \
+ unsigned int nbufs; \
+ uv_buf_t* bufs; \
int64_t offset; \
+ uv_buf_t bufsml[4]; \
}; \
struct { \
double atime; \
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index 4eeade74c4..49c2a43ef8 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -19,7 +19,7 @@
* IN THE SOFTWARE.
*/
-/* See http://nikhilm.github.com/uvbook/ for an introduction. */
+/* See https://github.com/joyent/libuv#documentation for documentation. */
#ifndef UV_H
#define UV_H
@@ -46,6 +46,7 @@ extern "C" {
#endif
#include "uv-errno.h"
+#include "uv-version.h"
#include <stddef.h>
#if defined(_MSC_VER) && _MSC_VER < 1600
@@ -94,6 +95,7 @@ extern "C" {
XX(EDESTADDRREQ, "destination address required") \
XX(EEXIST, "file already exists") \
XX(EFAULT, "bad address in system call argument") \
+ XX(EFBIG, "file too large") \
XX(EHOSTUNREACH, "host is unreachable") \
XX(EINTR, "interrupted system call") \
XX(EINVAL, "invalid argument") \
@@ -112,6 +114,7 @@ extern "C" {
XX(ENOENT, "no such file or directory") \
XX(ENOMEM, "not enough memory") \
XX(ENONET, "machine is not on the network") \
+ XX(ENOPROTOOPT, "protocol not available") \
XX(ENOSPC, "no space left on device") \
XX(ENOSYS, "function not implemented") \
XX(ENOTCONN, "socket is not connected") \
@@ -124,11 +127,13 @@ extern "C" {
XX(EPROTO, "protocol error") \
XX(EPROTONOSUPPORT, "protocol not supported") \
XX(EPROTOTYPE, "protocol wrong type for socket") \
+ XX(ERANGE, "result too large") \
XX(EROFS, "read-only file system") \
XX(ESHUTDOWN, "cannot send after transport endpoint shutdown") \
XX(ESPIPE, "invalid seek") \
XX(ESRCH, "no such process") \
XX(ETIMEDOUT, "connection timed out") \
+ XX(ETXTBSY, "text file is busy") \
XX(EXDEV, "cross-device link not permitted") \
XX(UNKNOWN, "unknown error") \
XX(EOF, "end of file") \
@@ -243,15 +248,11 @@ UV_EXTERN const char* uv_version_string(void);
/*
- * This function must be called before any other functions in libuv.
- *
* All functions besides uv_run() are non-blocking.
*
* All callbacks in libuv are made asynchronously. That is they are never
* made by the function that takes them as a parameter.
*/
-UV_EXTERN uv_loop_t* uv_loop_new(void);
-UV_EXTERN void uv_loop_delete(uv_loop_t*);
/*
* Returns the default loop.
@@ -259,6 +260,32 @@ UV_EXTERN void uv_loop_delete(uv_loop_t*);
UV_EXTERN uv_loop_t* uv_default_loop(void);
/*
+ * Initializes a uv_loop_t structure.
+ */
+UV_EXTERN int uv_loop_init(uv_loop_t* loop);
+
+/*
+ * Closes all internal loop resources. This function must only be called once
+ * the loop has finished it's execution or it will return UV_EBUSY. After this
+ * function returns the user shall free the memory allocated for the loop.
+ */
+UV_EXTERN int uv_loop_close(uv_loop_t* loop);
+
+/*
+ * Allocates and initializes a new loop.
+ * NOTE: This function is DEPRECATED (to be removed after 0.12), users should
+ * allocate the loop manually and use uv_loop_init instead.
+ */
+UV_EXTERN uv_loop_t* uv_loop_new(void);
+
+/*
+ * Cleans up a loop once it has finished executio and frees its memory.
+ * NOTE: This function is DEPRECATED (to be removed after 0.12). Users should use
+ * uv_loop_close and free the memory manually instead.
+ */
+UV_EXTERN void uv_loop_delete(uv_loop_t*);
+
+/*
* This function runs the event loop. It will act differently depending on the
* specified mode:
* - UV_RUN_DEFAULT: Runs the event loop until the reference count drops to
@@ -435,8 +462,10 @@ typedef struct {
* will be a relative path to a file contained in the directory.
* The events parameter is an ORed mask of enum uv_fs_event elements.
*/
-typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle, const char* filename,
- int events, int status);
+typedef void (*uv_fs_event_cb)(uv_fs_event_t* handle,
+ const char* filename,
+ int events,
+ int status);
typedef void (*uv_fs_poll_cb)(uv_fs_poll_t* handle,
int status,
@@ -486,8 +515,9 @@ UV_PRIVATE_REQ_TYPES
* initialized stream. req should be an uninitialized shutdown request
* struct. The cb is called after shutdown is complete.
*/
-UV_EXTERN int uv_shutdown(uv_shutdown_t* req, uv_stream_t* handle,
- uv_shutdown_cb cb);
+UV_EXTERN int uv_shutdown(uv_shutdown_t* req,
+ uv_stream_t* handle,
+ uv_shutdown_cb cb);
struct uv_shutdown_s {
UV_REQ_FIELDS
@@ -499,12 +529,12 @@ struct uv_shutdown_s {
#define UV_HANDLE_FIELDS \
/* public */ \
- uv_close_cb close_cb; \
void* data; \
/* read-only */ \
uv_loop_t* loop; \
uv_handle_type type; \
/* private */ \
+ uv_close_cb close_cb; \
void* handle_queue[2]; \
UV_HANDLE_PRIVATE_FIELDS \
@@ -590,8 +620,7 @@ UV_EXTERN uv_buf_t uv_buf_init(char* base, unsigned int len);
*
* uv_stream is an abstract class.
*
- * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t, uv_tty_t, and
- * soon uv_file_t.
+ * uv_stream_t is the parent class of uv_tcp_t, uv_pipe_t and uv_tty_t.
*/
struct uv_stream_s {
UV_HANDLE_FIELDS
@@ -625,8 +654,9 @@ UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client);
* eof; it happens when libuv requested a buffer through the alloc callback
* but then decided that it didn't need that buffer.
*/
-UV_EXTERN int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb,
- uv_read_cb read_cb);
+UV_EXTERN int uv_read_start(uv_stream_t*,
+ uv_alloc_cb alloc_cb,
+ uv_read_cb read_cb);
UV_EXTERN int uv_read_stop(uv_stream_t*);
@@ -719,11 +749,7 @@ UV_EXTERN int uv_is_writable(const uv_stream_t* handle);
* Relying too much on this API is not recommended. It is likely to change
* significantly in the future.
*
- * On windows this currently works only for uv_pipe_t instances. On unix it
- * works for tcp, pipe and tty instances. Be aware that changing the blocking
- * mode on unix sets or clears the O_NONBLOCK bit. If you are sharing a handle
- * with another process, the other process is affected by the change too,
- * which can lead to unexpected results.
+ * Currently this only works on Windows and only for uv_pipe_t handles.
*
* Also libuv currently makes no ordering guarantee when the blocking mode
* is changed after write requests have already been submitted. Therefore it is
@@ -843,7 +869,7 @@ enum uv_udp_flags {
};
/*
- * Called after a uv_udp_send() or uv_udp_send6(). status 0 indicates
+ * Called after uv_udp_send(). status 0 indicates
* success otherwise error.
*/
typedef void (*uv_udp_send_cb)(uv_udp_send_t* req, int status);
@@ -908,7 +934,7 @@ UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle);
UV_EXTERN int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock);
/*
- * Bind to a IPv4 address and port.
+ * Bind to an IP address and port.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
@@ -931,8 +957,9 @@ UV_EXTERN int uv_udp_bind(uv_udp_t* handle,
const struct sockaddr* addr,
unsigned int flags);
-UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
- int* namelen);
+UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle,
+ struct sockaddr* name,
+ int* namelen);
/*
* Set membership for a multicast address
@@ -948,8 +975,9 @@ UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name,
* 0 on success, or an error code < 0 on failure.
*/
UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle,
- const char* multicast_addr, const char* interface_addr,
- uv_membership membership);
+ const char* multicast_addr,
+ const char* interface_addr,
+ uv_membership membership);
/*
* Set IP multicast loop flag. Makes multicast packets loop back to
@@ -978,6 +1006,21 @@ UV_EXTERN int uv_udp_set_multicast_loop(uv_udp_t* handle, int on);
*/
UV_EXTERN int uv_udp_set_multicast_ttl(uv_udp_t* handle, int ttl);
+
+/*
+ * Set the multicast interface to send on
+ *
+ * Arguments:
+ * handle UDP handle. Should have been initialized with
+ * `uv_udp_init`.
+ * interface_addr interface address
+ *
+ * Returns:
+ * 0 on success, or an error code < 0 on failure.
+ */
+UV_EXTERN int uv_udp_set_multicast_interface(uv_udp_t* handle,
+ const char* interface_addr);
+
/*
* Set broadcast on or off
*
@@ -1005,16 +1048,17 @@ UV_EXTERN int uv_udp_set_broadcast(uv_udp_t* handle, int on);
UV_EXTERN int uv_udp_set_ttl(uv_udp_t* handle, int ttl);
/*
- * Send data. If the socket has not previously been bound with `uv_udp_bind`
- * or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
- * and a random port number.
+ * Send data. If the socket has not previously been bound with `uv_udp_bind,`
+ * it is bound to 0.0.0.0 (the "all interfaces" address) and a random
+ * port number.
*
* Arguments:
* req UDP request handle. Need not be initialized.
* handle UDP handle. Should have been initialized with `uv_udp_init`.
* bufs List of buffers to send.
* nbufs Number of buffers in `bufs`.
- * addr Address of the remote peer. See `uv_ip4_addr`.
+ * addr struct sockaddr_in or struct sockaddr_in6 with the address and
+ * port of the remote peer.
* send_cb Callback to invoke when the data has been sent out.
*
* Returns:
@@ -1029,8 +1073,8 @@ UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
/*
* Receive data. If the socket has not previously been bound with `uv_udp_bind`
- * or `uv_udp_bind6`, it is bound to 0.0.0.0 (the "all interfaces" address)
- * and a random port number.
+ * it is bound to 0.0.0.0 (the "all interfaces" address) and a random
+ * port number.
*
* Arguments:
* handle UDP handle. Should have been initialized with `uv_udp_init`.
@@ -1040,8 +1084,9 @@ UV_EXTERN int uv_udp_send(uv_udp_send_t* req,
* Returns:
* 0 on success, or an error code < 0 on failure.
*/
-UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb,
- uv_udp_recv_cb recv_cb);
+UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle,
+ uv_alloc_cb alloc_cb,
+ uv_udp_recv_cb recv_cb);
/*
* Stop listening for incoming datagrams.
@@ -1144,8 +1189,22 @@ UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name);
* 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);
+UV_EXTERN void uv_pipe_connect(uv_connect_t* req,
+ uv_pipe_t* handle,
+ const char* name,
+ uv_connect_cb cb);
+
+/*
+ * Get the name of the UNIX domain socket or the named pipe.
+ *
+ * A preallocated buffer must be provided. The len parameter holds the
+ * length of the buffer and it's set to the number of bytes written to the
+ * buffer on output. If the buffer is not big enough UV_ENOBUFS will be
+ * returned and len will contain the required size.
+ */
+UV_EXTERN int uv_pipe_getsockname(const uv_pipe_t* handle,
+ char* buf,
+ size_t* len);
/*
* This setting applies to Windows only.
@@ -1200,8 +1259,9 @@ UV_EXTERN int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd);
/* Initialize the poll watcher using a socket descriptor. On unix this is */
/* identical to uv_poll_init. On windows it takes a SOCKET handle. */
-UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle,
- uv_os_sock_t socket);
+UV_EXTERN int uv_poll_init_socket(uv_loop_t* loop,
+ uv_poll_t* handle,
+ uv_os_sock_t socket);
/*
* Starts polling the file descriptor. `events` is a bitmask consisting made up
@@ -1299,13 +1359,12 @@ struct uv_async_s {
* Note that uv_async_init(), unlike other libuv functions, immediately
* starts the handle. To stop the handle again, close it with uv_close().
*/
-UV_EXTERN int uv_async_init(uv_loop_t*, uv_async_t* async,
- uv_async_cb async_cb);
+UV_EXTERN int uv_async_init(uv_loop_t*,
+ uv_async_t* async,
+ uv_async_cb async_cb);
/*
* This can be called from other threads to wake up a libuv thread.
- *
- * libuv is single threaded at the moment.
*/
UV_EXTERN int uv_async_send(uv_async_t* async);
@@ -1425,7 +1484,7 @@ typedef struct uv_stdio_container_s {
typedef struct uv_process_options_s {
uv_exit_cb exit_cb; /* Called after the process exits. */
- const char* file; /* Path to program to execute. */
+ const char* file; /* Path to program to execute. */
/*
* Command line arguments. args[0] should be the path to the program. On
* Windows this uses CreateProcess which concatenates the arguments into a
@@ -1535,11 +1594,27 @@ UV_EXTERN int uv_spawn(uv_loop_t* loop,
/*
* Kills the process with the specified signal. The user must still
* call uv_close on the process.
+ *
+ * Emulates some aspects of Unix exit status on Windows, in that while the
+ * underlying process will be terminated with a status of `1`,
+ * `uv_process_t.exit_signal` will be set to signum, so the process will appear
+ * to have been killed by `signum`.
*/
UV_EXTERN int uv_process_kill(uv_process_t*, int signum);
-/* Kills the process with the specified signal. */
+/* Kills the process with the specified signal.
+ *
+ * Emulates some aspects of Unix signals on Windows:
+ * - SIGTERM, SIGKILL, and SIGINT call TerminateProcess() to unconditionally
+ * cause the target to exit with status 1. Unlike Unix, this cannot be caught
+ * or ignored (but see uv_process_kill() and uv_signal_start()).
+ * - Signal number `0` causes a check for target existence, as in Unix. Return
+ * value is 0 on existence, UV_ESRCH on non-existence.
+ *
+ * Returns 0 on success, or an error code on failure. UV_ESRCH is portably used
+ * for non-existence of target process, other errors may be system specific.
+ */
UV_EXTERN int uv_kill(int pid, int signum);
@@ -1555,8 +1630,10 @@ struct uv_work_s {
};
/* Queues a work request to execute asynchronously on the thread pool. */
-UV_EXTERN int uv_queue_work(uv_loop_t* loop, uv_work_t* req,
- uv_work_cb work_cb, uv_after_work_cb after_work_cb);
+UV_EXTERN int uv_queue_work(uv_loop_t* loop,
+ uv_work_t* req,
+ uv_work_cb work_cb,
+ uv_after_work_cb after_work_cb);
/* Cancel a pending request. Fails if the request is executing or has finished
* executing.
@@ -1615,6 +1692,36 @@ UV_EXTERN int uv_set_process_title(const char* title);
UV_EXTERN int uv_resident_set_memory(size_t* rss);
UV_EXTERN int uv_uptime(double* uptime);
+typedef struct {
+ long tv_sec;
+ long tv_usec;
+} uv_timeval_t;
+
+typedef struct {
+ uv_timeval_t ru_utime; /* user CPU time used */
+ uv_timeval_t ru_stime; /* system CPU time used */
+ uint64_t ru_maxrss; /* maximum resident set size */
+ uint64_t ru_ixrss; /* integral shared memory size */
+ uint64_t ru_idrss; /* integral unshared data size */
+ uint64_t ru_isrss; /* integral unshared stack size */
+ uint64_t ru_minflt; /* page reclaims (soft page faults) */
+ uint64_t ru_majflt; /* page faults (hard page faults) */
+ uint64_t ru_nswap; /* swaps */
+ uint64_t ru_inblock; /* block input operations */
+ uint64_t ru_oublock; /* block output operations */
+ uint64_t ru_msgsnd; /* IPC messages sent */
+ uint64_t ru_msgrcv; /* IPC messages received */
+ uint64_t ru_nsignals; /* signals received */
+ uint64_t ru_nvcsw; /* voluntary context switches */
+ uint64_t ru_nivcsw; /* involuntary context switches */
+} uv_rusage_t;
+
+/*
+ * Get information about OS resource utilization for the current process.
+ * Please note that not all uv_rusage_t struct fields will be filled on Windows.
+ */
+UV_EXTERN int uv_getrusage(uv_rusage_t* rusage);
+
/*
* This allocates cpu_infos array, and sets count. The array
* is freed using uv_free_cpu_info().
@@ -1697,13 +1804,13 @@ UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path,
int flags, int mode, uv_fs_cb cb);
UV_EXTERN int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file,
- void* buf, size_t length, int64_t offset, uv_fs_cb cb);
+ const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
UV_EXTERN int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path,
uv_fs_cb cb);
UV_EXTERN int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file,
- const void* buf, size_t length, int64_t offset, uv_fs_cb cb);
+ const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb);
UV_EXTERN int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path,
int mode, uv_fs_cb cb);
@@ -1786,7 +1893,8 @@ enum uv_fs_event {
struct uv_fs_event_s {
UV_HANDLE_FIELDS
- char* filename;
+ /* private */
+ char* path;
UV_FS_EVENT_PRIVATE_FIELDS
};
@@ -1824,6 +1932,15 @@ UV_EXTERN int uv_fs_poll_start(uv_fs_poll_t* handle,
UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
+/*
+ * Get the path being monitored by the handle. The buffer must be preallocated
+ * by the user. Returns 0 on success or an error code < 0 in case of failure.
+ * On sucess, `buf` will contain the path and `len` its length. If the buffer
+ * is not big enough UV_ENOBUFS will be returned and len will be set to the
+ * required size.
+ */
+UV_EXTERN int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len);
+
/*
* UNIX signal handling on a per-event loop basis. The implementation is not
@@ -1835,7 +1952,7 @@ UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
* signals will lead to unpredictable behavior and is strongly discouraged.
* Future versions of libuv may simply reject them.
*
- * Some signal support is available on Windows:
+ * Reception of some signals is emulated on Windows:
*
* SIGINT is normally delivered when the user presses CTRL+C. However, like
* on Unix, it is not generated when terminal raw mode is enabled.
@@ -1854,11 +1971,14 @@ UV_EXTERN int uv_fs_poll_stop(uv_fs_poll_t* handle);
* the console buffer will also trigger a SIGWINCH signal.
*
* Watchers for other signals can be successfully created, but these signals
- * are never generated. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV,
+ * are never received. These signals are: SIGILL, SIGABRT, SIGFPE, SIGSEGV,
* SIGTERM and SIGKILL.
*
* Note that calls to raise() or abort() to programmatically raise a signal are
* not detected by libuv; these will not trigger a signal watcher.
+ *
+ * See uv_process_kill() and uv_kill() for information about support for sending
+ * signals.
*/
struct uv_signal_s {
UV_HANDLE_FIELDS
@@ -1919,11 +2039,22 @@ 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,
+ const char* path,
unsigned int flags);
UV_EXTERN int uv_fs_event_stop(uv_fs_event_t* handle);
+/*
+ * Get the path being monitored by the handle. The buffer must be preallocated
+ * by the user. Returns 0 on success or an error code < 0 in case of failure.
+ * On sucess, `buf` will contain the path and `len` its length. If the buffer
+ * is not big enough UV_ENOBUFS will be returned and len will be set to the
+ * required size.
+ */
+UV_EXTERN int uv_fs_event_getpath(uv_fs_event_t* handle,
+ char* buf,
+ size_t* len);
+
/* Utility */
diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c
index 7fdaaeb17a..abde00302f 100644
--- a/deps/uv/src/fs-poll.c
+++ b/deps/uv/src/fs-poll.c
@@ -118,6 +118,31 @@ int uv_fs_poll_stop(uv_fs_poll_t* handle) {
}
+int uv_fs_poll_getpath(uv_fs_poll_t* handle, char* buf, size_t* len) {
+ struct poll_ctx* ctx;
+ size_t required_len;
+
+ if (!uv__is_active(handle)) {
+ *len = 0;
+ return UV_EINVAL;
+ }
+
+ ctx = handle->poll_ctx;
+ assert(ctx != NULL);
+
+ required_len = strlen(ctx->path) + 1;
+ if (required_len > *len) {
+ *len = required_len;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buf, ctx->path, required_len);
+ *len = required_len;
+
+ return 0;
+}
+
+
void uv__fs_poll_close(uv_fs_poll_t* handle) {
uv_fs_poll_stop(handle);
}
diff --git a/deps/uv/src/heap-inl.h b/deps/uv/src/heap-inl.h
new file mode 100644
index 0000000000..907abe65a0
--- /dev/null
+++ b/deps/uv/src/heap-inl.h
@@ -0,0 +1,238 @@
+/* Copyright (c) 2013, Ben Noordhuis <info@bnoordhuis.nl>
+ *
+ * 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_SRC_HEAP_H_
+#define UV_SRC_HEAP_H_
+
+#include <stddef.h> /* NULL */
+
+#if defined(__GNUC__)
+# define HEAP_EXPORT(declaration) __attribute__((unused)) static declaration
+#else
+# define HEAP_EXPORT(declaration) static declaration
+#endif
+
+struct heap_node {
+ struct heap_node* left;
+ struct heap_node* right;
+ struct heap_node* parent;
+};
+
+/* A binary min heap. The usual properties hold: the root is the lowest
+ * element in the set, the height of the tree is at most log2(nodes) and
+ * it's always a complete binary tree.
+ *
+ * The heap function try hard to detect corrupted tree nodes at the cost
+ * of a minor reduction in performance. Compile with -DNDEBUG to disable.
+ */
+struct heap {
+ struct heap_node* min;
+ unsigned int nelts;
+};
+
+/* Return non-zero if a < b. */
+typedef int (*heap_compare_fn)(const struct heap_node* a,
+ const struct heap_node* b);
+
+/* Public functions. */
+HEAP_EXPORT(void heap_init(struct heap* heap));
+HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap));
+HEAP_EXPORT(void heap_insert(struct heap* heap,
+ struct heap_node* newnode,
+ heap_compare_fn less_than));
+HEAP_EXPORT(void heap_remove(struct heap* heap,
+ struct heap_node* node,
+ heap_compare_fn less_than));
+HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than));
+
+/* Implementation follows. */
+
+HEAP_EXPORT(void heap_init(struct heap* heap)) {
+ heap->min = NULL;
+ heap->nelts = 0;
+}
+
+HEAP_EXPORT(struct heap_node* heap_min(const struct heap* heap)) {
+ return heap->min;
+}
+
+/* Swap parent with child. Child moves closer to the root, parent moves away. */
+static void heap_node_swap(struct heap* heap,
+ struct heap_node* parent,
+ struct heap_node* child) {
+ struct heap_node* sibling;
+ struct heap_node t;
+
+ t = *parent;
+ *parent = *child;
+ *child = t;
+
+ parent->parent = child;
+ if (child->left == child) {
+ child->left = parent;
+ sibling = child->right;
+ } else {
+ child->right = parent;
+ sibling = child->left;
+ }
+ if (sibling != NULL)
+ sibling->parent = child;
+
+ if (parent->left != NULL)
+ parent->left->parent = parent;
+ if (parent->right != NULL)
+ parent->right->parent = parent;
+
+ if (child->parent == NULL)
+ heap->min = child;
+ else if (child->parent->left == parent)
+ child->parent->left = child;
+ else
+ child->parent->right = child;
+}
+
+HEAP_EXPORT(void heap_insert(struct heap* heap,
+ struct heap_node* newnode,
+ heap_compare_fn less_than)) {
+ struct heap_node** parent;
+ struct heap_node** child;
+ unsigned int path;
+ unsigned int n;
+ unsigned int k;
+
+ newnode->left = NULL;
+ newnode->right = NULL;
+ newnode->parent = NULL;
+
+ /* Calculate the path from the root to the insertion point. This is a min
+ * heap so we always insert at the left-most free node of the bottom row.
+ */
+ path = 0;
+ for (k = 0, n = 1 + heap->nelts; n >= 2; k += 1, n /= 2)
+ path = (path << 1) | (n & 1);
+
+ /* Now traverse the heap using the path we calculated in the previous step. */
+ parent = child = &heap->min;
+ while (k > 0) {
+ parent = child;
+ if (path & 1)
+ child = &(*child)->right;
+ else
+ child = &(*child)->left;
+ path >>= 1;
+ k -= 1;
+ }
+
+ /* Insert the new node. */
+ newnode->parent = *parent;
+ *child = newnode;
+ heap->nelts += 1;
+
+ /* Walk up the tree and check at each node if the heap property holds.
+ * It's a min heap so parent < child must be true.
+ */
+ while (newnode->parent != NULL && less_than(newnode, newnode->parent))
+ heap_node_swap(heap, newnode->parent, newnode);
+}
+
+HEAP_EXPORT(void heap_remove(struct heap* heap,
+ struct heap_node* node,
+ heap_compare_fn less_than)) {
+ struct heap_node* smallest;
+ struct heap_node** max;
+ struct heap_node* child;
+ unsigned int path;
+ unsigned int k;
+ unsigned int n;
+
+ if (heap->nelts == 0)
+ return;
+
+ /* Calculate the path from the min (the root) to the max, the left-most node
+ * of the bottom row.
+ */
+ path = 0;
+ for (k = 0, n = heap->nelts; n >= 2; k += 1, n /= 2)
+ path = (path << 1) | (n & 1);
+
+ /* Now traverse the heap using the path we calculated in the previous step. */
+ max = &heap->min;
+ while (k > 0) {
+ if (path & 1)
+ max = &(*max)->right;
+ else
+ max = &(*max)->left;
+ path >>= 1;
+ k -= 1;
+ }
+
+ heap->nelts -= 1;
+
+ /* Unlink the max node. */
+ child = *max;
+ *max = NULL;
+
+ if (child == node) {
+ /* We're removing either the max or the last node in the tree. */
+ if (child == heap->min) {
+ heap->min = NULL;
+ }
+ return;
+ }
+
+ /* Replace the to be deleted node with the max node. */
+ child->left = node->left;
+ child->right = node->right;
+ child->parent = node->parent;
+
+ if (child->left != NULL) {
+ child->left->parent = child;
+ }
+
+ if (child->right != NULL) {
+ child->right->parent = child;
+ }
+
+ if (node->parent == NULL) {
+ heap->min = child;
+ } else if (node->parent->left == node) {
+ node->parent->left = child;
+ } else {
+ node->parent->right = child;
+ }
+
+ /* Walk down the subtree and check at each node if the heap property holds.
+ * It's a min heap so parent < child must be true. If the parent is bigger,
+ * swap it with the smallest child.
+ */
+ for (;;) {
+ smallest = child;
+ if (child->left != NULL && less_than(child->left, smallest))
+ smallest = child->left;
+ if (child->right != NULL && less_than(child->right, smallest))
+ smallest = child->right;
+ if (smallest == child)
+ break;
+ heap_node_swap(heap, child, smallest);
+ }
+}
+
+HEAP_EXPORT(void heap_dequeue(struct heap* heap, heap_compare_fn less_than)) {
+ heap_remove(heap, heap->min, less_than);
+}
+
+#undef HEAP_EXPORT
+
+#endif /* UV_SRC_HEAP_H_ */
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index df2a5f8042..a84304497c 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -37,6 +37,7 @@
#include <arpa/inet.h>
#include <limits.h> /* INT_MAX, PATH_MAX */
#include <sys/uio.h> /* writev */
+#include <sys/resource.h> /* getrusage */
#ifdef __linux__
# include <sys/ioctl.h>
@@ -785,3 +786,34 @@ int uv__io_active(const uv__io_t* w, unsigned int events) {
assert(0 != events);
return 0 != (w->pevents & events);
}
+
+
+int uv_getrusage(uv_rusage_t* rusage) {
+ struct rusage usage;
+
+ if (getrusage(RUSAGE_SELF, &usage))
+ return -errno;
+
+ rusage->ru_utime.tv_sec = usage.ru_utime.tv_sec;
+ rusage->ru_utime.tv_usec = usage.ru_utime.tv_usec;
+
+ rusage->ru_stime.tv_sec = usage.ru_stime.tv_sec;
+ rusage->ru_stime.tv_usec = usage.ru_stime.tv_usec;
+
+ rusage->ru_maxrss = usage.ru_maxrss;
+ rusage->ru_ixrss = usage.ru_ixrss;
+ rusage->ru_idrss = usage.ru_idrss;
+ rusage->ru_isrss = usage.ru_isrss;
+ rusage->ru_minflt = usage.ru_minflt;
+ rusage->ru_majflt = usage.ru_majflt;
+ rusage->ru_nswap = usage.ru_nswap;
+ rusage->ru_inblock = usage.ru_inblock;
+ rusage->ru_oublock = usage.ru_oublock;
+ rusage->ru_msgsnd = usage.ru_msgsnd;
+ rusage->ru_msgrcv = usage.ru_msgrcv;
+ rusage->ru_nsignals = usage.ru_nsignals;
+ rusage->ru_nvcsw = usage.ru_nvcsw;
+ rusage->ru_nivcsw = usage.ru_nivcsw;
+
+ return 0;
+}
diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c
index 1aa6539cb4..b06f992dc7 100644
--- a/deps/uv/src/unix/fs.c
+++ b/deps/uv/src/unix/fs.c
@@ -44,10 +44,34 @@
#include <utime.h>
#include <poll.h>
+#if defined(__DragonFly__) || \
+ defined(__FreeBSD__) || \
+ defined(__OpenBSD__) || \
+ defined(__NetBSD__)
+# define HAVE_PREADV 1
+#elif defined(__linux__)
+# include <linux/version.h>
+# if defined(__GLIBC_PREREQ)
+# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) && \
+ __GLIBC_PREREQ(2,10)
+# define HAVE_PREADV 1
+# else
+# define HAVE_PREADV 0
+# endif
+# else
+# define HAVE_PREADV 0
+# endif
+#else
+# define HAVE_PREADV 0
+#endif
+
#if defined(__linux__) || defined(__sun)
# include <sys/sendfile.h>
#elif defined(__APPLE__) || defined(__FreeBSD__)
# include <sys/socket.h>
+#endif
+
+#if HAVE_PREADV || defined(__APPLE__)
# include <sys/uio.h>
#endif
@@ -191,10 +215,59 @@ skip:
static ssize_t uv__fs_read(uv_fs_t* req) {
+ ssize_t result;
+
if (req->off < 0)
- return read(req->file, req->buf, req->len);
- else
- return pread(req->file, req->buf, req->len, req->off);
+ result = readv(req->file, (struct iovec*) req->bufs, req->nbufs);
+ else {
+#if HAVE_PREADV
+ result = preadv(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+#else
+# if defined(__linux__)
+ static int no_preadv;
+ if (no_preadv)
+# endif
+ {
+ off_t nread;
+ size_t index;
+
+# if defined(__linux__)
+ retry:
+# endif
+ nread = 0;
+ index = 0;
+ result = 1;
+ do {
+ if (req->bufs[index].len > 0) {
+ result = pread(req->file,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ req->off + nread);
+ if (result > 0)
+ nread += result;
+ }
+ index++;
+ } while (index < req->nbufs && result > 0);
+ if (nread > 0)
+ result = nread;
+ }
+# if defined(__linux__)
+ else {
+ result = uv__preadv(req->file,
+ (struct iovec*)req->bufs,
+ req->nbufs,
+ req->off);
+ if (result == -1 && errno == ENOSYS) {
+ no_preadv = 1;
+ goto retry;
+ }
+ }
+# endif
+#endif
+ }
+ if (req->bufs != req->bufsml)
+ free(req->bufs);
+ return result;
}
@@ -306,7 +379,7 @@ static ssize_t uv__fs_sendfile_emul(uv_fs_t* req) {
int out_fd;
char buf[8192];
- len = req->len;
+ len = req->bufsml[0].len;
in_fd = req->flags;
out_fd = req->file;
offset = req->off;
@@ -419,7 +492,7 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
ssize_t r;
off = req->off;
- r = sendfile(out_fd, in_fd, &off, req->len);
+ r = sendfile(out_fd, in_fd, &off, req->bufsml[0].len);
/* sendfile() on SunOS returns EINVAL if the target fd is not a socket but
* it still writes out data. Fortunately, we can detect it by checking if
@@ -453,11 +526,11 @@ static ssize_t uv__fs_sendfile(uv_fs_t* req) {
#if defined(__FreeBSD__)
len = 0;
- r = sendfile(in_fd, out_fd, req->off, req->len, NULL, &len, 0);
+ r = sendfile(in_fd, out_fd, req->off, req->bufsml[0].len, NULL, &len, 0);
#else
/* The darwin sendfile takes len as an input for the length to send,
* so make sure to initialize it with the caller's value. */
- len = req->len;
+ len = req->bufsml[0].len;
r = sendfile(in_fd, out_fd, req->off, &len, NULL, 0);
#endif
@@ -507,14 +580,61 @@ static ssize_t uv__fs_write(uv_fs_t* req) {
#endif
if (req->off < 0)
- r = write(req->file, req->buf, req->len);
- else
- r = pwrite(req->file, req->buf, req->len, req->off);
+ r = writev(req->file, (struct iovec*) req->bufs, req->nbufs);
+ else {
+#if HAVE_PREADV
+ r = pwritev(req->file, (struct iovec*) req->bufs, req->nbufs, req->off);
+#else
+# if defined(__linux__)
+ static int no_pwritev;
+ if (no_pwritev)
+# endif
+ {
+ off_t written;
+ size_t index;
+
+# if defined(__linux__)
+ retry:
+# endif
+ written = 0;
+ index = 0;
+ r = 0;
+ do {
+ if (req->bufs[index].len > 0) {
+ r = pwrite(req->file,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ req->off + written);
+ if (r > 0)
+ written += r;
+ }
+ index++;
+ } while (index < req->nbufs && r >= 0);
+ if (written > 0)
+ r = written;
+ }
+# if defined(__linux__)
+ else {
+ r = uv__pwritev(req->file,
+ (struct iovec*) req->bufs,
+ req->nbufs,
+ req->off);
+ if (r == -1 && errno == ENOSYS) {
+ no_pwritev = 1;
+ goto retry;
+ }
+ }
+# endif
+#endif
+ }
#if defined(__APPLE__)
pthread_mutex_unlock(&lock);
#endif
+ if (req->bufs != req->bufsml)
+ free(req->bufs);
+
return r;
}
@@ -608,6 +728,9 @@ static void uv__fs_work(struct uv__work* w) {
int retry_on_eintr;
uv_fs_t* req;
ssize_t r;
+#ifdef O_CLOEXEC
+ static int no_cloexec_support;
+#endif /* O_CLOEXEC */
req = container_of(w, uv_fs_t, work_req);
retry_on_eintr = !(req->fs_type == UV_FS_CLOSE);
@@ -634,7 +757,6 @@ static void uv__fs_work(struct uv__work* w) {
X(LSTAT, uv__fs_lstat(req->path, &req->statbuf));
X(LINK, link(req->path, req->new_path));
X(MKDIR, mkdir(req->path, req->mode));
- X(OPEN, open(req->path, req->flags, req->mode));
X(READ, uv__fs_read(req));
X(READDIR, uv__fs_readdir(req));
X(READLINK, uv__fs_readlink(req));
@@ -646,6 +768,35 @@ static void uv__fs_work(struct uv__work* w) {
X(UNLINK, unlink(req->path));
X(UTIME, uv__fs_utime(req));
X(WRITE, uv__fs_write(req));
+ case UV_FS_OPEN:
+#ifdef O_CLOEXEC
+ /* Try O_CLOEXEC before entering locks */
+ if (!no_cloexec_support) {
+ r = open(req->path, req->flags | O_CLOEXEC, req->mode);
+ if (r >= 0)
+ break;
+ if (errno != EINVAL)
+ break;
+ no_cloexec_support = 1;
+ }
+#endif /* O_CLOEXEC */
+ if (req->cb != NULL)
+ uv_rwlock_rdlock(&req->loop->cloexec_lock);
+ r = open(req->path, req->flags, req->mode);
+
+ /*
+ * In case of failure `uv__cloexec` will leave error in `errno`,
+ * so it is enough to just set `r` to `-1`.
+ */
+ if (r >= 0 && uv__cloexec(r, 1) != 0) {
+ r = uv__close(r);
+ if (r != 0 && r != -EINPROGRESS)
+ abort();
+ r = -1;
+ }
+ if (req->cb != NULL)
+ uv_rwlock_rdunlock(&req->loop->cloexec_lock);
+ break;
default: abort();
}
@@ -834,14 +985,23 @@ int uv_fs_open(uv_loop_t* loop,
int uv_fs_read(uv_loop_t* loop, uv_fs_t* req,
uv_file file,
- void* buf,
- size_t len,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(READ);
req->file = file;
- req->buf = buf;
- req->len = len;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return -ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->off = off;
POST;
}
@@ -898,7 +1058,7 @@ int uv_fs_sendfile(uv_loop_t* loop,
req->flags = in_fd; /* hack */
req->file = out_fd;
req->off = off;
- req->len = len;
+ req->bufsml[0].len = len;
POST;
}
@@ -947,14 +1107,23 @@ int uv_fs_utime(uv_loop_t* loop,
int uv_fs_write(uv_loop_t* loop,
uv_fs_t* req,
uv_file file,
- const void* buf,
- size_t len,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
int64_t off,
uv_fs_cb cb) {
INIT(WRITE);
req->file = file;
- req->buf = (void*) buf;
- req->len = len;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return -ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->off = off;
POST;
}
diff --git a/deps/uv/src/unix/fsevents.c b/deps/uv/src/unix/fsevents.c
index 7faa1562a6..f9c3a400fb 100644
--- a/deps/uv/src/unix/fsevents.c
+++ b/deps/uv/src/unix/fsevents.c
@@ -795,7 +795,7 @@ int uv__fsevents_init(uv_fs_event_t* handle) {
return err;
/* Get absolute path to file */
- handle->realpath = realpath(handle->filename, NULL);
+ handle->realpath = realpath(handle->path, NULL);
if (handle->realpath == NULL)
return -errno;
handle->realpath_len = strlen(handle->realpath);
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
index 0ea82b51a0..4a4656a562 100644
--- a/deps/uv/src/unix/internal.h
+++ b/deps/uv/src/unix/internal.h
@@ -27,6 +27,7 @@
#include <assert.h>
#include <stdlib.h> /* abort */
#include <string.h> /* strrchr */
+#include <fcntl.h> /* O_CLOEXEC, may be */
#if defined(__STRICT_ANSI__)
# define inline __inline
@@ -111,6 +112,14 @@
# define UV__POLLHUP 8
#endif
+#if !defined(O_CLOEXEC) && defined(__FreeBSD__)
+/*
+ * It may be that we are just missing `__POSIX_VISIBLE >= 200809`.
+ * Try using fixed value const and give up, if it doesn't work
+ */
+# define O_CLOEXEC 0x00100000
+#endif
+
/* handle flags */
enum {
UV_CLOSING = 0x01, /* uv_close() called but not finished. */
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
index f86f291fc0..5a25e117c9 100644
--- a/deps/uv/src/unix/kqueue.c
+++ b/deps/uv/src/unix/kqueue.c
@@ -331,7 +331,7 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
- const char* filename,
+ const char* path,
unsigned int flags) {
#if defined(__APPLE__)
struct stat statbuf;
@@ -342,13 +342,13 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return -EINVAL;
/* TODO open asynchronously - but how do we report back errors? */
- fd = open(filename, O_RDONLY);
+ fd = open(path, O_RDONLY);
if (fd == -1)
return -errno;
uv__handle_start(handle);
uv__io_init(&handle->event_watcher, uv__fs_event, fd);
- handle->filename = strdup(filename);
+ handle->path = strdup(path);
handle->cb = cb;
#if defined(__APPLE__)
@@ -388,8 +388,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
uv__io_stop(handle->loop, &handle->event_watcher, UV__POLLIN);
#endif /* defined(__APPLE__) */
- free(handle->filename);
- handle->filename = NULL;
+ free(handle->path);
+ handle->path = NULL;
uv__close(handle->event_watcher.fd);
handle->event_watcher.fd = -1;
diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c
index 4f11d88eed..97a5126f6a 100644
--- a/deps/uv/src/unix/linux-core.c
+++ b/deps/uv/src/unix/linux-core.c
@@ -107,6 +107,7 @@ void uv__platform_loop_delete(uv_loop_t* loop) {
void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
struct uv__epoll_event* events;
+ struct uv__epoll_event dummy;
uintptr_t i;
uintptr_t nfds;
@@ -114,13 +115,20 @@ void uv__platform_invalidate_fd(uv_loop_t* loop, int fd) {
events = (struct uv__epoll_event*) loop->watchers[loop->nwatchers];
nfds = (uintptr_t) loop->watchers[loop->nwatchers + 1];
- if (events == NULL)
- return;
-
- /* Invalidate events with same file descriptor */
- for (i = 0; i < nfds; i++)
- if ((int) events[i].data == fd)
- events[i].data = -1;
+ if (events != NULL)
+ /* Invalidate events with same file descriptor */
+ for (i = 0; i < nfds; i++)
+ if ((int) events[i].data == fd)
+ events[i].data = -1;
+
+ /* Remove the file descriptor from the epoll.
+ * This avoids a problem where the same file description remains open
+ * in another process, causing repeated junk epoll events.
+ *
+ * We pass in a dummy epoll_event, to work around a bug in old kernels.
+ */
+ if (loop->backend_fd >= 0)
+ uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, &dummy);
}
@@ -638,7 +646,7 @@ static int read_times(unsigned int numcpus, uv_cpu_info_t* ci) {
unsigned int n;
int r = sscanf(buf, "cpu%u ", &n);
assert(r == 1);
- (void) r; // silence build warning
+ (void) r; /* silence build warning */
for (len = sizeof("cpu0"); n /= 10; len++);
}
diff --git a/deps/uv/src/unix/linux-inotify.c b/deps/uv/src/unix/linux-inotify.c
index 7641f383c4..20bc173554 100644
--- a/deps/uv/src/unix/linux-inotify.c
+++ b/deps/uv/src/unix/linux-inotify.c
@@ -124,7 +124,7 @@ static void uv__inotify_read(uv_loop_t* loop,
const char* path;
ssize_t size;
const char *p;
- /* needs to be large enough for sizeof(inotify_event) + strlen(filename) */
+ /* needs to be large enough for sizeof(inotify_event) + strlen(path) */
char buf[4096];
while (1) {
@@ -219,7 +219,7 @@ int uv_fs_event_start(uv_fs_event_t* handle,
no_insert:
uv__handle_start(handle);
QUEUE_INSERT_TAIL(&w->watchers, &handle->watchers);
- handle->filename = w->path;
+ handle->path = w->path;
handle->cb = cb;
handle->wd = wd;
@@ -237,7 +237,7 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
assert(w != NULL);
handle->wd = -1;
- handle->filename = NULL;
+ handle->path = NULL;
uv__handle_stop(handle);
QUEUE_REMOVE(&handle->watchers);
diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c
index 06cc5943cf..c9cc44d8cd 100644
--- a/deps/uv/src/unix/linux-syscalls.c
+++ b/deps/uv/src/unix/linux-syscalls.c
@@ -199,6 +199,26 @@
# endif
#endif /* __NR_utimensat */
+#ifndef __NR_preadv
+# if defined(__x86_64__)
+# define __NR_preadv 295
+# elif defined(__i386__)
+# define __NR_preadv 333
+# elif defined(__arm__)
+# define __NR_preadv (UV_SYSCALL_BASE + 361)
+# endif
+#endif /* __NR_preadv */
+
+#ifndef __NR_pwritev
+# if defined(__x86_64__)
+# define __NR_pwritev 296
+# elif defined(__i386__)
+# define __NR_pwritev 334
+# elif defined(__arm__)
+# define __NR_pwritev (UV_SYSCALL_BASE + 362)
+# endif
+#endif /* __NR_pwritev */
+
int uv__accept4(int fd, struct sockaddr* addr, socklen_t* addrlen, int flags) {
#if defined(__i386__)
@@ -386,3 +406,19 @@ int uv__utimesat(int dirfd,
return errno = ENOSYS, -1;
#endif
}
+
+ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
+#if defined(__NR_preadv)
+ return syscall(__NR_preadv, fd, iov, iovcnt, offset);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
+
+ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset) {
+#if defined(__NR_pwritev)
+ return syscall(__NR_pwritev, fd, iov, iovcnt, offset);
+#else
+ return errno = ENOSYS, -1;
+#endif
+}
diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h
index 1ad9518548..6d9ec9f22c 100644
--- a/deps/uv/src/unix/linux-syscalls.h
+++ b/deps/uv/src/unix/linux-syscalls.h
@@ -147,5 +147,7 @@ int uv__utimesat(int dirfd,
const char* path,
const struct timespec times[2],
int flags);
+ssize_t uv__preadv(int fd, const struct iovec *iov, int iovcnt, off_t offset);
+ssize_t uv__pwritev(int fd, const struct iovec *iov, int iovcnt, off_t offset);
#endif /* UV_LINUX_SYSCALL_H_ */
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index 94a5c03819..52c9328e75 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -22,12 +22,13 @@
#include "uv.h"
#include "tree.h"
#include "internal.h"
+#include "heap-inl.h"
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static int uv__loop_init(uv_loop_t* loop, int default_loop);
-static void uv__loop_delete(uv_loop_t* loop);
+static void uv__loop_close(uv_loop_t* loop);
static uv_loop_t default_loop_struct;
static uv_loop_t* default_loop_ptr;
@@ -45,6 +46,31 @@ uv_loop_t* uv_default_loop(void) {
}
+int uv_loop_init(uv_loop_t* loop) {
+ return uv__loop_init(loop, /* default_loop? */ 0);
+}
+
+
+int uv_loop_close(uv_loop_t* loop) {
+ QUEUE* q;
+ uv_handle_t* h;
+ if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ return -EBUSY;
+ QUEUE_FOREACH(q, &loop->handle_queue) {
+ h = QUEUE_DATA(q, uv_handle_t, handle_queue);
+ if (!(h->flags & UV__HANDLE_INTERNAL))
+ return -EBUSY;
+ }
+ uv__loop_close(loop);
+#ifndef NDEBUG
+ memset(loop, -1, sizeof(*loop));
+#endif
+ if (loop == default_loop_ptr)
+ default_loop_ptr = NULL;
+ return 0;
+}
+
+
uv_loop_t* uv_loop_new(void) {
uv_loop_t* loop;
@@ -52,7 +78,7 @@ uv_loop_t* uv_loop_new(void) {
if (loop == NULL)
return NULL;
- if (uv__loop_init(loop, /* default_loop? */ 0)) {
+ if (uv_loop_init(loop)) {
free(loop);
return NULL;
}
@@ -62,13 +88,10 @@ uv_loop_t* uv_loop_new(void) {
void uv_loop_delete(uv_loop_t* loop) {
- uv__loop_delete(loop);
-#ifndef NDEBUG
- memset(loop, -1, sizeof(*loop));
-#endif
- if (loop == default_loop_ptr)
- default_loop_ptr = NULL;
- else
+ uv_loop_t* default_loop;
+ default_loop = default_loop_ptr;
+ assert(uv_loop_close(loop) == 0);
+ if (loop != default_loop)
free(loop);
}
@@ -80,7 +103,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
uv__signal_global_once_init();
memset(loop, 0, sizeof(*loop));
- RB_INIT(&loop->timer_handles);
+ heap_init((struct heap*) &loop->timer_heap);
QUEUE_INIT(&loop->wq);
QUEUE_INIT(&loop->active_reqs);
QUEUE_INIT(&loop->idle_handles);
@@ -117,6 +140,9 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
for (i = 0; i < ARRAY_SIZE(loop->process_handles); i++)
QUEUE_INIT(loop->process_handles + i);
+ if (uv_rwlock_init(&loop->cloexec_lock))
+ abort();
+
if (uv_mutex_init(&loop->wq_mutex))
abort();
@@ -130,7 +156,7 @@ static int uv__loop_init(uv_loop_t* loop, int default_loop) {
}
-static void uv__loop_delete(uv_loop_t* loop) {
+static void uv__loop_close(uv_loop_t* loop) {
uv__signal_loop_cleanup(loop);
uv__platform_loop_delete(loop);
uv__async_stop(loop, &loop->async_watcher);
@@ -151,6 +177,12 @@ static void uv__loop_delete(uv_loop_t* loop) {
uv_mutex_unlock(&loop->wq_mutex);
uv_mutex_destroy(&loop->wq_mutex);
+ /*
+ * Note that all thread pool stuff is finished at this point and
+ * it is safe to just destroy rw lock
+ */
+ uv_rwlock_destroy(&loop->cloexec_lock);
+
#if 0
assert(QUEUE_EMPTY(&loop->pending_queue));
assert(QUEUE_EMPTY(&loop->watcher_queue));
diff --git a/deps/uv/src/unix/pipe.c b/deps/uv/src/unix/pipe.c
index fd4afb6370..34c118b773 100644
--- a/deps/uv/src/unix/pipe.c
+++ b/deps/uv/src/unix/pipe.c
@@ -212,5 +212,37 @@ out:
}
+int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
+ struct sockaddr_un sa;
+ socklen_t addrlen;
+ int err;
+
+ addrlen = sizeof(sa);
+ memset(&sa, 0, addrlen);
+ err = getsockname(uv__stream_fd(handle), (struct sockaddr*) &sa, &addrlen);
+ if (err < 0) {
+ *len = 0;
+ return -errno;
+ }
+
+ if (sa.sun_path[0] == 0)
+ /* Linux abstract namespace */
+ addrlen -= offsetof(struct sockaddr_un, sun_path);
+ else
+ addrlen = strlen(sa.sun_path) + 1;
+
+
+ if (addrlen > *len) {
+ *len = addrlen;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buf, sa.sun_path, addrlen);
+ *len = addrlen;
+
+ return 0;
+}
+
+
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 6f96b754d8..55f6ac5806 100644
--- a/deps/uv/src/unix/process.c
+++ b/deps/uv/src/unix/process.c
@@ -40,6 +40,10 @@
extern char **environ;
#endif
+#ifdef __linux__
+# include <grp.h>
+#endif
+
static QUEUE* uv__process_queue(uv_loop_t* loop, int pid) {
assert(pid > 0);
@@ -330,6 +334,17 @@ static void uv__process_child_init(const uv_process_options_t* options,
_exit(127);
}
+ if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
+ /* When dropping privileges from root, the `setgroups` call will
+ * remove any extraneous groups. If we don't call this, then
+ * even though our uid has dropped, we may still have groups
+ * that enable us to do super-user things. This will fail if we
+ * aren't root, so don't bother checking the return value, this
+ * is just done as an optimistic privilege dropping function.
+ */
+ SAVE_ERRNO(setgroups(0, NULL));
+ }
+
if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) {
uv__write_int(error_fd, -errno);
perror("setgid()");
@@ -422,10 +437,13 @@ int uv_spawn(uv_loop_t* loop,
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
+ /* Acquire write lock to prevent opening new fds in worker threads */
+ uv_rwlock_wrlock(&loop->cloexec_lock);
pid = fork();
if (pid == -1) {
err = -errno;
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[0]);
uv__close(signal_pipe[1]);
goto error;
@@ -436,6 +454,8 @@ int uv_spawn(uv_loop_t* loop,
abort();
}
+ /* Release lock in parent process */
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
uv__close(signal_pipe[1]);
process->status = 0;
diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c
index 9f5d40cf4b..ad6856b4b7 100644
--- a/deps/uv/src/unix/stream.c
+++ b/deps/uv/src/unix/stream.c
@@ -301,6 +301,7 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
int err;
int ret;
int kq;
+ int old_fd;
kq = kqueue();
if (kq == -1) {
@@ -353,16 +354,20 @@ int uv__stream_try_select(uv_stream_t* stream, int* fd) {
s->fake_fd = fds[0];
s->int_fd = fds[1];
- if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
- goto fatal4;
-
+ old_fd = *fd;
s->stream = stream;
stream->select = s;
*fd = s->fake_fd;
+ if (uv_thread_create(&s->thread, uv__stream_osx_select, stream))
+ goto fatal4;
+
return 0;
fatal4:
+ s->stream = NULL;
+ stream->select = NULL;
+ *fd = old_fd;
uv__close(s->fake_fd);
uv__close(s->int_fd);
s->fake_fd = -1;
@@ -1103,6 +1108,7 @@ int uv_shutdown(uv_shutdown_t* req, uv_stream_t* stream, uv_shutdown_cb cb) {
if (!(stream->flags & UV_STREAM_WRITABLE) ||
stream->flags & UV_STREAM_SHUT ||
+ stream->flags & UV_STREAM_SHUTTING ||
stream->flags & UV_CLOSED ||
stream->flags & UV_CLOSING) {
return -ENOTCONN;
@@ -1505,7 +1511,5 @@ void uv__stream_close(uv_stream_t* handle) {
int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
- assert(0 && "implement me");
- abort();
- return 0;
+ return UV_ENOSYS;
}
diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c
index f31a23fb3c..b8a39c7017 100644
--- a/deps/uv/src/unix/sunos.c
+++ b/deps/uv/src/unix/sunos.c
@@ -372,11 +372,14 @@ static void uv__fs_event_read(uv_loop_t* loop,
assert(events != 0);
handle->fd = PORT_FIRED;
handle->cb(handle, NULL, events, 0);
+
+ if (handle->fd != PORT_DELETED) {
+ r = uv__fs_event_rearm(handle);
+ if (r != 0)
+ handle->cb(handle, NULL, 0, r);
+ }
}
while (handle->fd != PORT_DELETED);
-
- if (handle != NULL && handle->fd != PORT_DELETED)
- uv__fs_event_rearm(handle); /* FIXME(bnoordhuis) Check return code. */
}
@@ -388,10 +391,11 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
- const char* filename,
+ const char* path,
unsigned int flags) {
int portfd;
int first_run;
+ int err;
if (uv__is_active(handle))
return -EINVAL;
@@ -406,13 +410,15 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
uv__handle_start(handle);
- handle->filename = strdup(filename);
+ handle->path = strdup(path);
handle->fd = PORT_UNUSED;
handle->cb = cb;
memset(&handle->fo, 0, sizeof handle->fo);
- handle->fo.fo_name = handle->filename;
- uv__fs_event_rearm(handle); /* FIXME(bnoordhuis) Check return code. */
+ handle->fo.fo_name = handle->path;
+ err = uv__fs_event_rearm(handle);
+ if (err != 0)
+ return err;
if (first_run) {
uv__io_init(&handle->loop->fs_event_watcher, uv__fs_event_read, portfd);
@@ -434,8 +440,8 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
}
handle->fd = PORT_DELETED;
- free(handle->filename);
- handle->filename = NULL;
+ free(handle->path);
+ handle->path = NULL;
handle->fo.fo_name = NULL;
uv__handle_stop(handle);
diff --git a/deps/uv/src/unix/tcp.c b/deps/uv/src/unix/tcp.c
index 2c36dc3ffc..9c50b2d8a1 100644
--- a/deps/uv/src/unix/tcp.c
+++ b/deps/uv/src/unix/tcp.c
@@ -232,7 +232,9 @@ int uv_tcp_listen(uv_tcp_t* tcp, int backlog, uv_connection_cb cb) {
int uv__tcp_nodelay(int fd, int on) {
- return setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on));
+ if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)))
+ return -errno;
+ return 0;
}
diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c
index 240efad503..b373f4db87 100644
--- a/deps/uv/src/unix/timer.c
+++ b/deps/uv/src/unix/timer.c
@@ -20,35 +20,41 @@
#include "uv.h"
#include "internal.h"
+#include "heap-inl.h"
+
#include <assert.h>
#include <limits.h>
-static int uv__timer_cmp(const uv_timer_t* a, const uv_timer_t* b) {
+static int timer_less_than(const struct heap_node* ha,
+ const struct heap_node* hb) {
+ const uv_timer_t* a;
+ const uv_timer_t* b;
+
+ a = container_of(ha, const uv_timer_t, heap_node);
+ b = container_of(hb, const uv_timer_t, heap_node);
+
if (a->timeout < b->timeout)
- return -1;
- if (a->timeout > b->timeout)
return 1;
- /*
- * compare start_id when both has the same timeout. start_id is
- * allocated with loop->timer_counter in uv_timer_start().
+ if (b->timeout < a->timeout)
+ return 0;
+
+ /* Compare start_id when both have the same timeout. start_id is
+ * allocated with loop->timer_counter in uv_timer_start().
*/
if (a->start_id < b->start_id)
- return -1;
- if (a->start_id > b->start_id)
return 1;
+ if (b->start_id < a->start_id)
+ return 0;
+
return 0;
}
-RB_GENERATE_STATIC(uv__timers, uv_timer_s, tree_entry, uv__timer_cmp)
-
-
int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) {
uv__handle_init(loop, (uv_handle_t*)handle, UV_TIMER);
handle->timer_cb = NULL;
handle->repeat = 0;
-
return 0;
}
@@ -72,7 +78,9 @@ int uv_timer_start(uv_timer_t* handle,
/* start_id is the second index to be compared in uv__timer_cmp() */
handle->start_id = handle->loop->timer_counter++;
- RB_INSERT(uv__timers, &handle->loop->timer_handles, handle);
+ heap_insert((struct heap*) &handle->loop->timer_heap,
+ (struct heap_node*) &handle->heap_node,
+ timer_less_than);
uv__handle_start(handle);
return 0;
@@ -83,7 +91,9 @@ int uv_timer_stop(uv_timer_t* handle) {
if (!uv__is_active(handle))
return 0;
- RB_REMOVE(uv__timers, &handle->loop->timer_handles, handle);
+ heap_remove((struct heap*) &handle->loop->timer_heap,
+ (struct heap_node*) &handle->heap_node,
+ timer_less_than);
uv__handle_stop(handle);
return 0;
@@ -114,15 +124,15 @@ uint64_t uv_timer_get_repeat(const uv_timer_t* handle) {
int uv__next_timeout(const uv_loop_t* loop) {
+ const struct heap_node* heap_node;
const uv_timer_t* handle;
uint64_t diff;
- /* RB_MIN expects a non-const tree root. That's okay, it doesn't modify it. */
- handle = RB_MIN(uv__timers, (struct uv__timers*) &loop->timer_handles);
-
- if (handle == NULL)
+ heap_node = heap_min((const struct heap*) &loop->timer_heap);
+ if (heap_node == NULL)
return -1; /* block indefinitely */
+ handle = container_of(heap_node, const uv_timer_t, heap_node);
if (handle->timeout <= loop->time)
return 0;
@@ -135,9 +145,15 @@ int uv__next_timeout(const uv_loop_t* loop) {
void uv__run_timers(uv_loop_t* loop) {
+ struct heap_node* heap_node;
uv_timer_t* handle;
- while ((handle = RB_MIN(uv__timers, &loop->timer_handles))) {
+ for (;;) {
+ heap_node = heap_min((struct heap*) &loop->timer_heap);
+ if (heap_node == NULL)
+ break;
+
+ handle = container_of(heap_node, uv_timer_t, heap_node);
if (handle->timeout > loop->time)
break;
diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c
index a2b3dc3298..ae3cc8dc65 100644
--- a/deps/uv/src/unix/udp.c
+++ b/deps/uv/src/unix/udp.c
@@ -539,6 +539,31 @@ int uv_udp_set_multicast_loop(uv_udp_t* handle, int on) {
return uv__setsockopt_maybe_char(handle, IP_MULTICAST_LOOP, on);
}
+int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
+ struct in_addr addr;
+ int err;
+
+ memset(&addr, 0, sizeof addr);
+
+ if (interface_addr) {
+ err = uv_inet_pton(AF_INET, interface_addr, &addr.s_addr);
+ if (err)
+ return err;
+ } else {
+ addr.s_addr = htonl(INADDR_ANY);
+ }
+
+ if (setsockopt(handle->io_watcher.fd,
+ IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (void*) &addr,
+ sizeof addr) == -1) {
+ return -errno;
+ }
+
+ return 0;
+}
+
int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen) {
socklen_t socklen;
diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c
index e5fc507756..2a6316a878 100644
--- a/deps/uv/src/uv-common.c
+++ b/deps/uv/src/uv-common.c
@@ -444,3 +444,23 @@ int uv__getaddrinfo_translate_error(int sys_err) {
abort();
return 0; /* Pacify compiler. */
}
+
+int uv_fs_event_getpath(uv_fs_event_t* handle, char* buf, size_t* len) {
+ size_t required_len;
+
+ if (!uv__is_active(handle)) {
+ *len = 0;
+ return UV_EINVAL;
+ }
+
+ required_len = strlen(handle->path) + 1;
+ if (required_len > *len) {
+ *len = required_len;
+ return UV_ENOBUFS;
+ }
+
+ memcpy(buf, handle->path, required_len);
+ *len = required_len;
+
+ return 0;
+}
diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c
index 725872b452..02de6de305 100644
--- a/deps/uv/src/version.c
+++ b/deps/uv/src/version.c
@@ -21,20 +21,6 @@
#include "uv.h"
- /*
- * Versions with an even minor version (e.g. 0.6.1 or 1.0.4) are API and ABI
- * stable. When the minor version is odd, the API can change between patch
- * releases. Make sure you update the -soname directives in config-unix.mk
- * and uv.gyp whenever you bump UV_VERSION_MAJOR or UV_VERSION_MINOR (but
- * not UV_VERSION_PATCH.)
- */
-
-#define UV_VERSION_MAJOR 0
-#define UV_VERSION_MINOR 11
-#define UV_VERSION_PATCH 18
-#define UV_VERSION_IS_RELEASE 1
-
-
#define UV_VERSION ((UV_VERSION_MAJOR << 16) | \
(UV_VERSION_MINOR << 8) | \
(UV_VERSION_PATCH))
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index e1a77655ac..2e702768ed 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -26,7 +26,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#if !defined(__MINGW32__)
#include <crtdbg.h>
+#endif
#include "uv.h"
#include "internal.h"
@@ -42,7 +44,7 @@ static uv_once_t uv_init_guard_ = UV_ONCE_INIT;
static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT;
-#ifdef _DEBUG
+#if defined(_DEBUG) && !defined(__MINGW32__)
/* Our crt debug report handler allows us to temporarily disable asserts */
/* just for the current thread. */
@@ -89,7 +91,7 @@ static void uv_init(void) {
/* We also need to setup our debug report handler because some CRT */
/* functions (eg _get_osfhandle) raise an assert when called with invalid */
/* FDs even though they return the proper error code in the release build. */
-#ifdef _DEBUG
+#if defined(_DEBUG) && !defined(__MINGW32__)
_CrtSetReportHook(uv__crt_dbg_report_handler);
#endif
@@ -114,12 +116,14 @@ static void uv_init(void) {
}
-static void uv_loop_init(uv_loop_t* loop) {
+int uv_loop_init(uv_loop_t* loop) {
+ /* Initialize libuv itself first */
+ uv__once_init();
+
/* Create an I/O completion port */
loop->iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1);
- if (loop->iocp == NULL) {
- uv_fatal_error(GetLastError(), "CreateIoCompletionPort");
- }
+ if (loop->iocp == NULL)
+ return uv_translate_sys_error(GetLastError());
/* To prevent uninitialized memory access, loop->time must be intialized */
/* to zero before calling uv_update_time for the first time. */
@@ -152,6 +156,8 @@ static void uv_loop_init(uv_loop_t* loop) {
loop->timer_counter = 0;
loop->stop_flag = 0;
+
+ return 0;
}
@@ -175,35 +181,50 @@ uv_loop_t* uv_default_loop(void) {
}
+int uv_loop_close(uv_loop_t* loop) {
+ QUEUE* q;
+ uv_handle_t* h;
+ if (!QUEUE_EMPTY(&(loop)->active_reqs))
+ return UV_EBUSY;
+ QUEUE_FOREACH(q, &loop->handle_queue) {
+ h = QUEUE_DATA(q, uv_handle_t, handle_queue);
+ if (!(h->flags & UV__HANDLE_INTERNAL))
+ return UV_EBUSY;
+ }
+ if (loop != &uv_default_loop_) {
+ int i;
+ for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
+ SOCKET sock = loop->poll_peer_sockets[i];
+ if (sock != 0 && sock != INVALID_SOCKET)
+ closesocket(sock);
+ }
+ }
+ /* TODO: cleanup default loop*/
+ return 0;
+}
+
+
uv_loop_t* uv_loop_new(void) {
uv_loop_t* loop;
- /* Initialize libuv itself first */
- uv__once_init();
-
loop = (uv_loop_t*)malloc(sizeof(uv_loop_t));
+ if (loop == NULL) {
+ return NULL;
+ }
- if (!loop) {
- uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
+ if (uv_loop_init(loop)) {
+ free(loop);
+ return NULL;
}
- uv_loop_init(loop);
return loop;
}
void uv_loop_delete(uv_loop_t* loop) {
- if (loop != &uv_default_loop_) {
- int i;
- for (i = 0; i < ARRAY_SIZE(loop->poll_peer_sockets); i++) {
- SOCKET sock = loop->poll_peer_sockets[i];
- if (sock != 0 && sock != INVALID_SOCKET) {
- closesocket(sock);
- }
- }
-
+ assert(uv_loop_close(loop) == 0);
+ if (loop != &uv_default_loop_)
free(loop);
- }
}
diff --git a/deps/uv/src/win/fs-event.c b/deps/uv/src/win/fs-event.c
index 6132b79c82..f3de575685 100644
--- a/deps/uv/src/win/fs-event.c
+++ b/deps/uv/src/win/fs-event.c
@@ -126,38 +126,38 @@ int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle) {
int uv_fs_event_start(uv_fs_event_t* handle,
uv_fs_event_cb cb,
- const char* filename,
+ const char* path,
unsigned int flags) {
int name_size, is_path_dir;
DWORD attr, last_error;
- WCHAR* dir = NULL, *dir_to_watch, *filenamew = NULL;
+ WCHAR* dir = NULL, *dir_to_watch, *pathw = NULL;
WCHAR short_path[MAX_PATH];
if (uv__is_active(handle))
return UV_EINVAL;
handle->cb = cb;
- handle->filename = strdup(filename);
- if (!handle->filename) {
+ handle->path = strdup(path);
+ if (!handle->path) {
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);
- filenamew = (WCHAR*)malloc(name_size);
- if (!filenamew) {
+ name_size = uv_utf8_to_utf16(path, NULL, 0) * sizeof(WCHAR);
+ pathw = (WCHAR*)malloc(name_size);
+ if (!pathw) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
- if (!uv_utf8_to_utf16(filename, filenamew,
+ if (!uv_utf8_to_utf16(path, pathw,
name_size / sizeof(WCHAR))) {
return uv_translate_sys_error(GetLastError());
}
- /* Determine whether filename is a file or a directory. */
- attr = GetFileAttributesW(filenamew);
+ /* Determine whether path is a file or a directory. */
+ attr = GetFileAttributesW(pathw);
if (attr == INVALID_FILE_ATTRIBUTES) {
last_error = GetLastError();
goto error;
@@ -166,22 +166,22 @@ int uv_fs_event_start(uv_fs_event_t* handle,
is_path_dir = (attr & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
if (is_path_dir) {
- /* filename is a directory, so that's the directory that we will watch. */
- handle->dirw = filenamew;
- dir_to_watch = filenamew;
+ /* path is a directory, so that's the directory that we will watch. */
+ handle->dirw = pathw;
+ dir_to_watch = pathw;
} else {
/*
- * filename is a file. So we split filename into dir & file parts, and
+ * path is a file. So we split path into dir & file parts, and
* watch the dir directory.
*/
/* Convert to short path. */
- if (!GetShortPathNameW(filenamew, short_path, ARRAY_SIZE(short_path))) {
+ if (!GetShortPathNameW(pathw, short_path, ARRAY_SIZE(short_path))) {
last_error = GetLastError();
goto error;
}
- if (uv_split_path(filenamew, &dir, &handle->filew) != 0) {
+ if (uv_split_path(pathw, &dir, &handle->filew) != 0) {
last_error = GetLastError();
goto error;
}
@@ -192,8 +192,8 @@ int uv_fs_event_start(uv_fs_event_t* handle,
}
dir_to_watch = dir;
- free(filenamew);
- filenamew = NULL;
+ free(pathw);
+ pathw = NULL;
}
handle->dir_handle = CreateFileW(dir_to_watch,
@@ -257,9 +257,9 @@ int uv_fs_event_start(uv_fs_event_t* handle,
return 0;
error:
- if (handle->filename) {
- free(handle->filename);
- handle->filename = NULL;
+ if (handle->path) {
+ free(handle->path);
+ handle->path = NULL;
}
if (handle->filew) {
@@ -272,7 +272,7 @@ error:
handle->short_filew = NULL;
}
- free(filenamew);
+ free(pathw);
if (handle->dir_handle != INVALID_HANDLE_VALUE) {
CloseHandle(handle->dir_handle);
@@ -309,9 +309,9 @@ int uv_fs_event_stop(uv_fs_event_t* handle) {
handle->short_filew = NULL;
}
- if (handle->filename) {
- free(handle->filename);
- handle->filename = NULL;
+ if (handle->path) {
+ free(handle->path);
+ handle->path = NULL;
}
if (handle->dirw) {
diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c
index c4182758c7..d997b0ee7d 100644
--- a/deps/uv/src/win/fs.c
+++ b/deps/uv/src/win/fs.c
@@ -539,13 +539,14 @@ void fs__close(uv_fs_t* req) {
void fs__read(uv_fs_t* req) {
int fd = req->fd;
- size_t length = req->length;
int64_t offset = req->offset;
HANDLE handle;
OVERLAPPED overlapped, *overlapped_ptr;
LARGE_INTEGER offset_;
DWORD bytes;
DWORD error;
+ int result;
+ unsigned int index;
VERIFY_FD(fd, req);
@@ -556,11 +557,6 @@ void fs__read(uv_fs_t* req) {
return;
}
- if (length > INT_MAX) {
- SET_REQ_WIN32_ERROR(req, ERROR_INSUFFICIENT_BUFFER);
- return;
- }
-
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
@@ -573,7 +569,20 @@ void fs__read(uv_fs_t* req) {
overlapped_ptr = NULL;
}
- if (ReadFile(handle, req->buf, req->length, &bytes, overlapped_ptr)) {
+ index = 0;
+ bytes = 0;
+ do {
+ DWORD incremental_bytes;
+ result = ReadFile(handle,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ &incremental_bytes,
+ overlapped_ptr);
+ bytes += incremental_bytes;
+ ++index;
+ } while (result && index < req->nbufs);
+
+ if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
error = GetLastError();
@@ -588,12 +597,13 @@ void fs__read(uv_fs_t* req) {
void fs__write(uv_fs_t* req) {
int fd = req->fd;
- size_t length = req->length;
int64_t offset = req->offset;
HANDLE handle;
OVERLAPPED overlapped, *overlapped_ptr;
LARGE_INTEGER offset_;
DWORD bytes;
+ int result;
+ unsigned int index;
VERIFY_FD(fd, req);
@@ -603,11 +613,6 @@ void fs__write(uv_fs_t* req) {
return;
}
- if (length > INT_MAX) {
- SET_REQ_WIN32_ERROR(req, ERROR_INSUFFICIENT_BUFFER);
- return;
- }
-
if (offset != -1) {
memset(&overlapped, 0, sizeof overlapped);
@@ -620,7 +625,20 @@ void fs__write(uv_fs_t* req) {
overlapped_ptr = NULL;
}
- if (WriteFile(handle, req->buf, length, &bytes, overlapped_ptr)) {
+ index = 0;
+ bytes = 0;
+ do {
+ DWORD incremental_bytes;
+ result = WriteFile(handle,
+ req->bufs[index].base,
+ req->bufs[index].len,
+ &incremental_bytes,
+ overlapped_ptr);
+ bytes += incremental_bytes;
+ ++index;
+ } while (result && index < req->nbufs);
+
+ if (result || bytes > 0) {
SET_REQ_RESULT(req, bytes);
} else {
SET_REQ_WIN32_ERROR(req, GetLastError());
@@ -1087,7 +1105,7 @@ static void fs__ftruncate(uv_fs_t* req) {
static void fs__sendfile(uv_fs_t* req) {
int fd_in = req->fd, fd_out = req->fd_out;
- size_t length = req->length;
+ size_t length = req->bufsml[0].len;
int64_t offset = req->offset;
const size_t max_buf_size = 65536;
size_t buf_size = length < max_buf_size ? length : max_buf_size;
@@ -1283,23 +1301,23 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
return;
}
- // Do a pessimistic calculation of the required buffer size
+ /* Do a pessimistic calculation of the required buffer size */
needed_buf_size =
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
JUNCTION_PREFIX_LEN * sizeof(WCHAR) +
2 * (target_len + 2) * sizeof(WCHAR);
- // Allocate the buffer
+ /* Allocate the buffer */
buffer = (REPARSE_DATA_BUFFER*)malloc(needed_buf_size);
if (!buffer) {
uv_fatal_error(ERROR_OUTOFMEMORY, "malloc");
}
- // Grab a pointer to the part of the buffer where filenames go
+ /* Grab a pointer to the part of the buffer where filenames go */
path_buf = (WCHAR*)&(buffer->MountPointReparseBuffer.PathBuffer);
path_buf_len = 0;
- // Copy the substitute (internal) target path
+ /* Copy the substitute (internal) target path */
start = path_buf_len;
wcsncpy((WCHAR*)&path_buf[path_buf_len], JUNCTION_PREFIX,
@@ -1323,14 +1341,14 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
path_buf[path_buf_len++] = L'\\';
len = path_buf_len - start;
- // Set the info about the substitute name
+ /* Set the info about the substitute name */
buffer->MountPointReparseBuffer.SubstituteNameOffset = start * sizeof(WCHAR);
buffer->MountPointReparseBuffer.SubstituteNameLength = len * sizeof(WCHAR);
- // Insert null terminator
+ /* Insert null terminator */
path_buf[path_buf_len++] = L'\0';
- // Copy the print name of the target path
+ /* Copy the print name of the target path */
start = path_buf_len;
add_slash = 0;
for (i = is_long_path ? LONG_PATH_PREFIX_LEN : 0; path[i] != L'\0'; i++) {
@@ -1352,32 +1370,32 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
len++;
}
- // Set the info about the print name
+ /* Set the info about the print name */
buffer->MountPointReparseBuffer.PrintNameOffset = start * sizeof(WCHAR);
buffer->MountPointReparseBuffer.PrintNameLength = len * sizeof(WCHAR);
- // Insert another null terminator
+ /* Insert another null terminator */
path_buf[path_buf_len++] = L'\0';
- // Calculate how much buffer space was actually used
+ /* Calculate how much buffer space was actually used */
used_buf_size = FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer.PathBuffer) +
path_buf_len * sizeof(WCHAR);
used_data_size = used_buf_size -
FIELD_OFFSET(REPARSE_DATA_BUFFER, MountPointReparseBuffer);
- // Put general info in the data buffer
+ /* Put general info in the data buffer */
buffer->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
buffer->ReparseDataLength = used_data_size;
buffer->Reserved = 0;
- // Create a new directory
+ /* Create a new directory */
if (!CreateDirectoryW(new_path, NULL)) {
SET_REQ_WIN32_ERROR(req, GetLastError());
goto error;
}
created = 1;
- // Open the directory
+ /* Open the directory */
handle = CreateFileW(new_path,
GENERIC_ALL,
0,
@@ -1391,7 +1409,7 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
goto error;
}
- // Create the actual reparse point
+ /* Create the actual reparse point */
if (!DeviceIoControl(handle,
FSCTL_SET_REPARSE_POINT,
buffer,
@@ -1404,7 +1422,7 @@ static void fs__create_junction(uv_fs_t* req, const WCHAR* path,
goto error;
}
- // Clean up
+ /* Clean up */
CloseHandle(handle);
free(buffer);
@@ -1569,13 +1587,27 @@ int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file fd, uv_fs_cb cb) {
}
-int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file fd, void* buf,
- size_t length, int64_t offset, uv_fs_cb cb) {
+int uv_fs_read(uv_loop_t* loop,
+ uv_fs_t* req,
+ uv_file fd,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ int64_t offset,
+ uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_READ, cb);
req->fd = fd;
- req->buf = buf;
- req->length = length;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->offset = offset;
if (cb) {
@@ -1588,13 +1620,27 @@ int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file fd, void* buf,
}
-int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file fd, const void* buf,
- size_t length, int64_t offset, uv_fs_cb cb) {
+int uv_fs_write(uv_loop_t* loop,
+ uv_fs_t* req,
+ uv_file fd,
+ const uv_buf_t bufs[],
+ unsigned int nbufs,
+ int64_t offset,
+ uv_fs_cb cb) {
uv_fs_req_init(loop, req, UV_FS_WRITE, cb);
req->fd = fd;
- req->buf = (void*) buf;
- req->length = length;
+
+ req->nbufs = nbufs;
+ req->bufs = req->bufsml;
+ if (nbufs > ARRAY_SIZE(req->bufsml))
+ req->bufs = malloc(nbufs * sizeof(*bufs));
+
+ if (req->bufs == NULL)
+ return UV_ENOMEM;
+
+ memcpy(req->bufs, bufs, nbufs * sizeof(*bufs));
+
req->offset = offset;
if (cb) {
@@ -1922,7 +1968,7 @@ int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file fd_out,
req->fd = fd_in;
req->fd_out = fd_out;
req->offset = in_offset;
- req->length = length;
+ req->bufsml[0].len = length;
if (cb) {
QUEUE_FS_TP_JOB(loop, req);
diff --git a/deps/uv/src/win/pipe.c b/deps/uv/src/win/pipe.c
index f3d3110d31..69c5cde628 100644
--- a/deps/uv/src/win/pipe.c
+++ b/deps/uv/src/win/pipe.c
@@ -44,6 +44,10 @@ static const int64_t eof_timeout = 50; /* ms */
static const int default_pending_pipe_instances = 4;
+/* Pipe prefix */
+static char pipe_prefix[] = "\\\\?\\pipe";
+static const int pipe_prefix_len = sizeof(pipe_prefix) - 1;
+
/* IPC protocol flags. */
#define UV_IPC_RAW_DATA 0x0001
#define UV_IPC_TCP_SERVER 0x0002
@@ -70,7 +74,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-%u", ptr, GetCurrentProcessId());
+ _snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId());
}
@@ -433,7 +437,8 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
}
if (!uv_utf8_to_utf16(name, handle->name, nameSize / sizeof(WCHAR))) {
- return uv_translate_sys_error(GetLastError());
+ err = GetLastError();
+ goto error;
}
/*
@@ -1174,6 +1179,7 @@ static int uv_pipe_write_impl(uv_loop_t* loop,
NULL);
if (!result) {
+ err = GetLastError();
return err;
} else {
/* Request completed immediately. */
@@ -1745,3 +1751,111 @@ int uv_pipe_open(uv_pipe_t* pipe, uv_file file) {
}
return 0;
}
+
+
+int uv_pipe_getsockname(const uv_pipe_t* handle, char* buf, size_t* len) {
+ NTSTATUS nt_status;
+ IO_STATUS_BLOCK io_status;
+ FILE_NAME_INFORMATION tmp_name_info;
+ FILE_NAME_INFORMATION* name_info;
+ WCHAR* name_buf;
+ unsigned int addrlen;
+ unsigned int name_size;
+ unsigned int name_len;
+ int err;
+
+ name_info = NULL;
+
+ if (handle->handle == INVALID_HANDLE_VALUE) {
+ *len = 0;
+ return UV_EINVAL;
+ }
+
+ nt_status = pNtQueryInformationFile(handle->handle,
+ &io_status,
+ &tmp_name_info,
+ sizeof tmp_name_info,
+ FileNameInformation);
+ if (nt_status == STATUS_BUFFER_OVERFLOW) {
+ name_size = sizeof(*name_info) + tmp_name_info.FileNameLength;
+ name_info = malloc(name_size);
+ if (!name_info) {
+ *len = 0;
+ return UV_ENOMEM;
+ }
+
+ nt_status = pNtQueryInformationFile(handle->handle,
+ &io_status,
+ name_info,
+ name_size,
+ FileNameInformation);
+ }
+
+ if (nt_status != STATUS_SUCCESS) {
+ *len = 0;
+ err = uv_translate_sys_error(pRtlNtStatusToDosError(nt_status));
+ goto error;
+ }
+
+ if (!name_info) {
+ /* the struct on stack was used */
+ name_buf = tmp_name_info.FileName;
+ name_len = tmp_name_info.FileNameLength;
+ } else {
+ name_buf = name_info->FileName;
+ name_len = name_info->FileNameLength;
+ }
+
+ if (name_len == 0) {
+ *len = 0;
+ err = 0;
+ goto error;
+ }
+
+ name_len /= sizeof(WCHAR);
+
+ /* check how much space we need */
+ addrlen = WideCharToMultiByte(CP_UTF8,
+ 0,
+ name_buf,
+ name_len,
+ NULL,
+ 0,
+ NULL,
+ NULL);
+ if (!addrlen) {
+ *len = 0;
+ err = uv_translate_sys_error(GetLastError());
+ goto error;
+ } else if (pipe_prefix_len + addrlen + 1 > *len) {
+ /* "\\\\.\\pipe" + name + '\0' */
+ *len = pipe_prefix_len + addrlen + 1;
+ err = UV_ENOBUFS;
+ goto error;
+ }
+
+ memcpy(buf, pipe_prefix, pipe_prefix_len);
+ addrlen = WideCharToMultiByte(CP_UTF8,
+ 0,
+ name_buf,
+ name_len,
+ buf+pipe_prefix_len,
+ *len-pipe_prefix_len,
+ NULL,
+ NULL);
+ if (!addrlen) {
+ *len = 0;
+ err = uv_translate_sys_error(GetLastError());
+ goto error;
+ }
+
+ addrlen += pipe_prefix_len;
+ buf[addrlen++] = '\0';
+ *len = addrlen;
+
+ return 0;
+
+error:
+ free(name_info);
+ return err;
+}
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 813e522f75..88a141950d 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -811,6 +811,9 @@ int uv_spawn(uv_loop_t* loop,
PROCESS_INFORMATION info;
DWORD process_flags;
+ uv_process_init(loop, process);
+ process->exit_cb = options->exit_cb;
+
if (options->flags & (UV_PROCESS_SETGID | UV_PROCESS_SETUID)) {
return UV_ENOTSUP;
}
@@ -827,9 +830,6 @@ int uv_spawn(uv_loop_t* loop,
UV_PROCESS_WINDOWS_HIDE |
UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS)));
- uv_process_init(loop, process);
- process->exit_cb = options->exit_cb;
-
err = uv_utf8_to_utf16_alloc(options->file, &application);
if (err)
goto done;
diff --git a/deps/uv/src/win/stream.c b/deps/uv/src/win/stream.c
index 2eaa74e766..0abca3adcf 100644
--- a/deps/uv/src/win/stream.c
+++ b/deps/uv/src/win/stream.c
@@ -244,6 +244,9 @@ int uv_is_writable(const uv_stream_t* handle) {
int uv_stream_set_blocking(uv_stream_t* handle, int blocking) {
+ if (handle->type != UV_NAMED_PIPE)
+ return UV_EINVAL;
+
if (blocking != 0)
handle->flags |= UV_HANDLE_BLOCKING_WRITES;
else
diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c
index 8fa2146a06..f77db3b95c 100644
--- a/deps/uv/src/win/tcp.c
+++ b/deps/uv/src/win/tcp.c
@@ -271,7 +271,11 @@ static int uv_tcp_try_bind(uv_tcp_t* handle,
/* TODO: how to handle errors? This may fail if there is no ipv4 stack */
/* available, or when run on XP/2003 which have no support for dualstack */
/* sockets. For now we're silently ignoring the error. */
- setsockopt(handle->socket, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof on);
+ setsockopt(handle->socket,
+ IPPROTO_IPV6,
+ IPV6_V6ONLY,
+ (const char*)&on,
+ sizeof on);
}
#endif
@@ -575,6 +579,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) {
req->accept_socket = INVALID_SOCKET;
req->data = handle;
req->wait_handle = INVALID_HANDLE_VALUE;
+ req->event_handle = NULL;
}
}
@@ -988,9 +993,11 @@ void uv_process_tcp_write_req(uv_loop_t* loop, uv_tcp_t* handle,
if (handle->flags & UV_HANDLE_EMULATE_IOCP) {
if (req->wait_handle != INVALID_HANDLE_VALUE) {
UnregisterWait(req->wait_handle);
+ req->wait_handle = INVALID_HANDLE_VALUE;
}
if (req->event_handle) {
CloseHandle(req->event_handle);
+ req->event_handle = NULL;
}
}
diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c
index 31812e4642..282d49480e 100644
--- a/deps/uv/src/win/udp.c
+++ b/deps/uv/src/win/udp.c
@@ -585,6 +585,46 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr,
}
+int uv_udp_set_multicast_interface(uv_udp_t* handle, const char* interface_addr) {
+ struct in_addr addr;
+ int err;
+
+ memset(&addr, 0, sizeof addr);
+
+ if (handle->flags & UV_HANDLE_IPV6) {
+ return UV_ENOSYS;
+ }
+
+ /* If the socket is unbound, bind to inaddr_any. */
+ if (!(handle->flags & UV_HANDLE_BOUND)) {
+ err = uv_udp_try_bind(handle,
+ (const struct sockaddr*) &uv_addr_ip4_any_,
+ sizeof(uv_addr_ip4_any_),
+ 0);
+ if (err)
+ return uv_translate_sys_error(err);
+ }
+
+ if (interface_addr) {
+ err = uv_inet_pton(AF_INET, interface_addr, &addr.s_addr);
+ if (err)
+ return err;
+ } else {
+ addr.s_addr = htonl(INADDR_ANY);
+ }
+
+ if (setsockopt(handle->socket,
+ IPPROTO_IP,
+ IP_MULTICAST_IF,
+ (char*) &addr,
+ sizeof addr) == SOCKET_ERROR) {
+ return uv_translate_sys_error(WSAGetLastError());
+ }
+
+ return 0;
+}
+
+
int uv_udp_set_broadcast(uv_udp_t* handle, int value) {
BOOL optval = (BOOL) value;
int err;
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 266b881640..c9ca773df7 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -36,6 +36,7 @@
#include <iphlpapi.h>
#include <psapi.h>
#include <tlhelp32.h>
+#include <windows.h>
/*
@@ -988,3 +989,39 @@ void uv_free_interface_addresses(uv_interface_address_t* addresses,
int count) {
free(addresses);
}
+
+
+int uv_getrusage(uv_rusage_t *uv_rusage) {
+ FILETIME createTime, exitTime, kernelTime, userTime;
+ SYSTEMTIME kernelSystemTime, userSystemTime;
+ int ret;
+
+ ret = GetProcessTimes(GetCurrentProcess(), &createTime, &exitTime, &kernelTime, &userTime);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ ret = FileTimeToSystemTime(&kernelTime, &kernelSystemTime);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ ret = FileTimeToSystemTime(&userTime, &userSystemTime);
+ if (ret == 0) {
+ return uv_translate_sys_error(GetLastError());
+ }
+
+ memset(uv_rusage, 0, sizeof(*uv_rusage));
+
+ uv_rusage->ru_utime.tv_sec = userSystemTime.wHour * 3600 +
+ userSystemTime.wMinute * 60 +
+ userSystemTime.wSecond;
+ uv_rusage->ru_utime.tv_usec = userSystemTime.wMilliseconds * 1000;
+
+ uv_rusage->ru_stime.tv_sec = kernelSystemTime.wHour * 3600 +
+ kernelSystemTime.wMinute * 60 +
+ kernelSystemTime.wSecond;
+ uv_rusage->ru_stime.tv_usec = kernelSystemTime.wMilliseconds * 1000;
+
+ return 0;
+}
diff --git a/deps/uv/test/benchmark-async.c b/deps/uv/test/benchmark-async.c
index 33d9ab446a..defed67bf8 100644
--- a/deps/uv/test/benchmark-async.c
+++ b/deps/uv/test/benchmark-async.c
@@ -28,7 +28,7 @@
#define NUM_PINGS (1000 * 1000)
struct ctx {
- uv_loop_t* loop;
+ uv_loop_t loop;
uv_thread_t thread;
uv_async_t main_async; /* wake up main thread */
uv_async_t worker_async; /* wake up worker */
@@ -67,7 +67,8 @@ static void main_async_cb(uv_async_t* handle, int status) {
static void worker(void* arg) {
struct ctx* ctx = arg;
ASSERT(0 == uv_async_send(&ctx->main_async));
- ASSERT(0 == uv_run(ctx->loop, UV_RUN_DEFAULT));
+ ASSERT(0 == uv_run(&ctx->loop, UV_RUN_DEFAULT));
+ uv_loop_close(&ctx->loop);
}
@@ -83,9 +84,8 @@ static int test_async(int nthreads) {
for (i = 0; i < nthreads; i++) {
ctx = threads + i;
ctx->nthreads = 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_loop_init(&ctx->loop));
+ 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));
diff --git a/deps/uv/test/benchmark-multi-accept.c b/deps/uv/test/benchmark-multi-accept.c
index d71235ef3b..b1b0c1e3ce 100644
--- a/deps/uv/test/benchmark-multi-accept.c
+++ b/deps/uv/test/benchmark-multi-accept.c
@@ -249,27 +249,26 @@ static void get_listen_handle(uv_loop_t* loop, uv_stream_t* server_handle) {
static void server_cb(void *arg) {
struct server_ctx *ctx;
- uv_loop_t* loop;
+ uv_loop_t loop;
ctx = arg;
- loop = uv_loop_new();
- ASSERT(loop != NULL);
+ ASSERT(0 == uv_loop_init(&loop));
- ASSERT(0 == uv_async_init(loop, &ctx->async_handle, sv_async_cb));
+ ASSERT(0 == uv_async_init(&loop, &ctx->async_handle, sv_async_cb));
uv_unref((uv_handle_t*) &ctx->async_handle);
/* Wait until the main thread is ready. */
uv_sem_wait(&ctx->semaphore);
- get_listen_handle(loop, (uv_stream_t*) &ctx->server_handle);
+ get_listen_handle(&loop, (uv_stream_t*) &ctx->server_handle);
uv_sem_post(&ctx->semaphore);
/* Now start the actual benchmark. */
ASSERT(0 == uv_listen((uv_stream_t*) &ctx->server_handle,
128,
sv_connection_cb));
- ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+ ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT));
- uv_loop_delete(loop);
+ uv_loop_close(&loop);
}
diff --git a/deps/uv/test/run-benchmarks.c b/deps/uv/test/run-benchmarks.c
index 06732b71d3..61f062f99a 100644
--- a/deps/uv/test/run-benchmarks.c
+++ b/deps/uv/test/run-benchmarks.c
@@ -29,9 +29,6 @@
#include "benchmark-list.h"
-/* The time in milliseconds after which a single benchmark times out. */
-#define BENCHMARK_TIMEOUT 60000
-
static int maybe_run_test(int argc, char **argv);
@@ -39,7 +36,7 @@ int main(int argc, char **argv) {
platform_init(argc, argv);
switch (argc) {
- case 1: return run_tests(BENCHMARK_TIMEOUT, 1);
+ case 1: return run_tests(1);
case 2: return maybe_run_test(argc, argv);
case 3: return run_test_part(argv[1], argv[2]);
default:
@@ -60,5 +57,5 @@ static int maybe_run_test(int argc, char **argv) {
return 42;
}
- return run_test(argv[1], BENCHMARK_TIMEOUT, 1, 1);
+ return run_test(argv[1], 1, 1);
}
diff --git a/deps/uv/test/run-tests.c b/deps/uv/test/run-tests.c
index d84be6a1a5..cd50ee09f3 100644
--- a/deps/uv/test/run-tests.c
+++ b/deps/uv/test/run-tests.c
@@ -36,9 +36,6 @@
/* Actual tests and helpers are defined in test-list.h */
#include "test-list.h"
-/* The time in milliseconds after which a single test times out. */
-#define TEST_TIMEOUT 5000
-
int ipc_helper(int listen_after_write);
int ipc_helper_tcp_connection(void);
int ipc_send_recv_helper(void);
@@ -53,7 +50,7 @@ int main(int argc, char **argv) {
argv = uv_setup_args(argc, argv);
switch (argc) {
- case 1: return run_tests(TEST_TIMEOUT, 0);
+ case 1: return run_tests(0);
case 2: return maybe_run_test(argc, argv);
case 3: return run_test_part(argv[1], argv[2]);
default:
@@ -155,5 +152,16 @@ static int maybe_run_test(int argc, char **argv) {
return 1;
}
- return run_test(argv[1], TEST_TIMEOUT, 0, 1);
+#ifndef _WIN32
+ if (strcmp(argv[1], "spawn_helper8") == 0) {
+ int fd;
+ ASSERT(sizeof(fd) == read(0, &fd, sizeof(fd)));
+ ASSERT(fd > 2);
+ ASSERT(-1 == write(fd, "x", 1));
+
+ return 1;
+ }
+#endif /* !_WIN32 */
+
+ return run_test(argv[1], 0, 1);
}
diff --git a/deps/uv/test/runner.c b/deps/uv/test/runner.c
index f4d982c5b6..a934b24c6e 100644
--- a/deps/uv/test/runner.c
+++ b/deps/uv/test/runner.c
@@ -90,7 +90,7 @@ const char* fmt(double d) {
}
-int run_tests(int timeout, int benchmark_output) {
+int run_tests(int benchmark_output) {
int total;
int passed;
int failed;
@@ -130,7 +130,7 @@ int run_tests(int timeout, int benchmark_output) {
log_progress(total, passed, failed, todos, skipped, task->task_name);
}
- test_result = run_test(task->task_name, timeout, benchmark_output, current);
+ test_result = run_test(task->task_name, benchmark_output, current);
switch (test_result) {
case TEST_OK: passed++; break;
case TEST_TODO: todos++; break;
@@ -189,7 +189,6 @@ void log_tap_result(int test_count,
int run_test(const char* test,
- int timeout,
int benchmark_output,
int test_count) {
char errmsg[1024] = "no error";
@@ -279,7 +278,7 @@ int run_test(const char* test,
goto out;
}
- result = process_wait(main_proc, 1, timeout);
+ result = process_wait(main_proc, 1, task->timeout);
if (result == -1) {
FATAL("process_wait failed");
} else if (result == -2) {
diff --git a/deps/uv/test/runner.h b/deps/uv/test/runner.h
index aa7f205407..97c7312da7 100644
--- a/deps/uv/test/runner.h
+++ b/deps/uv/test/runner.h
@@ -41,6 +41,11 @@ typedef struct {
int (*main)(void);
int is_helper;
int show_output;
+
+ /*
+ * The time in milliseconds after which a single test or benchmark times out.
+ */
+ int timeout;
} task_entry_t, bench_entry_t;
@@ -51,29 +56,29 @@ typedef struct {
task_entry_t TASKS[] = {
#define TASK_LIST_END \
- { 0, 0, 0, 0, 0 } \
+ { 0, 0, 0, 0, 0, 0 } \
};
#define TEST_DECLARE(name) \
int run_test_##name(void);
#define TEST_ENTRY(name) \
- { #name, #name, &run_test_##name, 0, 0 },
+ { #name, #name, &run_test_##name, 0, 0, 5000 },
-#define TEST_OUTPUT_ENTRY(name) \
- { #name, #name, &run_test_##name, 0, 1 },
+#define TEST_ENTRY_CUSTOM(name, is_helper, show_output, timeout) \
+ { #name, #name, &run_test_##name, is_helper, show_output, timeout },
#define BENCHMARK_DECLARE(name) \
int run_benchmark_##name(void);
#define BENCHMARK_ENTRY(name) \
- { #name, #name, &run_benchmark_##name, 0, 0 },
+ { #name, #name, &run_benchmark_##name, 0, 0, 60000 },
#define HELPER_DECLARE(name) \
int run_helper_##name(void);
#define HELPER_ENTRY(task_name, name) \
- { #task_name, #name, &run_helper_##name, 1, 0 },
+ { #task_name, #name, &run_helper_##name, 1, 0, 0 },
#define TEST_HELPER HELPER_ENTRY
#define BENCHMARK_HELPER HELPER_ENTRY
@@ -97,13 +102,12 @@ extern task_entry_t TASKS[];
/*
* Run all tests.
*/
-int run_tests(int timeout, int benchmark_output);
+int run_tests(int benchmark_output);
/*
* Run a single test. Starts up any helpers.
*/
int run_test(const char* test,
- int timeout,
int benchmark_output,
int test_count);
diff --git a/deps/uv/test/task.h b/deps/uv/test/task.h
index b736c375c7..3b786a8c6e 100644
--- a/deps/uv/test/task.h
+++ b/deps/uv/test/task.h
@@ -41,8 +41,8 @@
#define TEST_PORT_2 9124
#ifdef _WIN32
-# define TEST_PIPENAME "\\\\.\\pipe\\uv-test"
-# define TEST_PIPENAME_2 "\\\\.\\pipe\\uv-test2"
+# define TEST_PIPENAME "\\\\?\\pipe\\uv-test"
+# define TEST_PIPENAME_2 "\\\\?\\pipe\\uv-test2"
#else
# define TEST_PIPENAME "/tmp/uv-test-sock"
# define TEST_PIPENAME_2 "/tmp/uv-test-sock2"
diff --git a/deps/uv/test/test-embed.c b/deps/uv/test/test-embed.c
index ac1b3b6750..909d2d5d99 100644
--- a/deps/uv/test/test-embed.c
+++ b/deps/uv/test/test-embed.c
@@ -108,15 +108,14 @@ static void embed_timer_cb(uv_timer_t* timer, int status) {
TEST_IMPL(embed) {
#if defined(HAVE_KQUEUE) || defined(HAVE_EPOLL)
- uv_loop_t* external;
+ uv_loop_t external;
- external = uv_loop_new();
- ASSERT(external != NULL);
+ ASSERT(0 == uv_loop_init(&external));
embed_timer_called = 0;
embed_closed = 0;
- uv_async_init(external, &embed_async, embed_cb);
+ uv_async_init(&external, &embed_async, embed_cb);
/* Start timer in default loop */
uv_timer_init(uv_default_loop(), &embed_timer);
@@ -127,10 +126,10 @@ TEST_IMPL(embed) {
uv_thread_create(&embed_thread, embed_thread_runner, NULL);
/* But run external loop */
- uv_run(external, UV_RUN_DEFAULT);
+ uv_run(&external, UV_RUN_DEFAULT);
uv_thread_join(&embed_thread);
- uv_loop_delete(external);
+ uv_loop_close(&external);
ASSERT(embed_timer_called == 1);
#endif
diff --git a/deps/uv/test/test-fs-event.c b/deps/uv/test/test-fs-event.c
index 3286de51f9..fec5fd6731 100644
--- a/deps/uv/test/test-fs-event.c
+++ b/deps/uv/test/test-fs-event.c
@@ -79,13 +79,15 @@ static void touch_file(uv_loop_t* loop, const char* name) {
int r;
uv_file file;
uv_fs_t req;
+ uv_buf_t buf;
r = uv_fs_open(loop, &req, name, O_RDWR, 0, NULL);
ASSERT(r >= 0);
file = r;
uv_fs_req_cleanup(&req);
- r = uv_fs_write(loop, &req, file, "foo", 4, -1, NULL);
+ buf = uv_buf_init("foo", 4);
+ r = uv_fs_write(loop, &req, file, &buf, 1, -1, NULL);
ASSERT(r >= 0);
uv_fs_req_cleanup(&req);
@@ -626,6 +628,38 @@ TEST_IMPL(fs_event_start_and_close) {
return 0;
}
+TEST_IMPL(fs_event_getpath) {
+ uv_loop_t* loop = uv_default_loop();
+ int r;
+ char buf[1024];
+ size_t len;
+
+ create_dir(loop, "watch_dir");
+
+ r = uv_fs_event_init(loop, &fs_event);
+ ASSERT(r == 0);
+ len = sizeof buf;
+ r = uv_fs_event_getpath(&fs_event, buf, &len);
+ ASSERT(r == UV_EINVAL);
+ r = uv_fs_event_start(&fs_event, fail_cb, "watch_dir", 0);
+ ASSERT(r == 0);
+ len = sizeof buf;
+ r = uv_fs_event_getpath(&fs_event, buf, &len);
+ ASSERT(r == 0);
+ ASSERT(memcmp(buf, "watch_dir", len) == 0);
+ r = uv_fs_event_stop(&fs_event);
+ ASSERT(r == 0);
+ uv_close((uv_handle_t*) &fs_event, close_cb);
+
+ uv_run(loop, UV_RUN_DEFAULT);
+
+ ASSERT(close_cb_called == 1);
+
+ remove("watch_dir/");
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
#if defined(__APPLE__)
static int fs_event_error_reported;
@@ -653,7 +687,7 @@ static void fs_event_error_report_close_cb(uv_handle_t* handle) {
TEST_IMPL(fs_event_error_reporting) {
unsigned int i;
- uv_loop_t* loops[1024];
+ uv_loop_t loops[1024];
uv_fs_event_t events[ARRAY_SIZE(loops)];
uv_loop_t* loop;
uv_fs_event_t* event;
@@ -668,11 +702,10 @@ TEST_IMPL(fs_event_error_reporting) {
* fail.
*/
for (i = 0; i < ARRAY_SIZE(loops); i++) {
- loop = uv_loop_new();
+ loop = &loops[i];
+ ASSERT(0 == uv_loop_init(loop));
event = &events[i];
- ASSERT(loop != NULL);
- loops[i] = loop;
timer_cb_called = 0;
close_cb_called = 0;
ASSERT(0 == uv_fs_event_init(loop, event));
@@ -697,7 +730,7 @@ TEST_IMPL(fs_event_error_reporting) {
/* Stop and close all events, and destroy loops */
do {
- loop = loops[i];
+ loop = &loops[i];
event = &events[i];
ASSERT(0 == uv_fs_event_stop(event));
@@ -708,9 +741,7 @@ TEST_IMPL(fs_event_error_reporting) {
uv_run(loop, UV_RUN_DEFAULT);
ASSERT(close_cb_called == 1);
- uv_loop_delete(loop);
-
- loops[i] = NULL;
+ uv_loop_close(loop);
} while (i-- != 0);
remove("watch_dir/");
diff --git a/deps/uv/test/test-fs-poll.c b/deps/uv/test/test-fs-poll.c
index 9213f04b34..27c6c3c3db 100644
--- a/deps/uv/test/test-fs-poll.c
+++ b/deps/uv/test/test-fs-poll.c
@@ -33,6 +33,11 @@ static void poll_cb(uv_fs_poll_t* handle,
const uv_stat_t* prev,
const uv_stat_t* curr);
+static void poll_cb_fail(uv_fs_poll_t* handle,
+ int status,
+ const uv_stat_t* prev,
+ const uv_stat_t* curr);
+
static uv_fs_poll_t poll_handle;
static uv_timer_t timer_handle;
static uv_loop_t* loop;
@@ -72,6 +77,14 @@ static void timer_cb(uv_timer_t* handle, int status) {
}
+static void poll_cb_fail(uv_fs_poll_t* handle,
+ int status,
+ const uv_stat_t* prev,
+ const uv_stat_t* curr) {
+ ASSERT(0 && "fail_cb called");
+}
+
+
static void poll_cb(uv_fs_poll_t* handle,
int status,
const uv_stat_t* prev,
@@ -144,3 +157,29 @@ TEST_IMPL(fs_poll) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+
+TEST_IMPL(fs_poll_getpath) {
+ char buf[1024];
+ size_t len;
+ loop = uv_default_loop();
+
+ remove(FIXTURE);
+
+ ASSERT(0 == uv_fs_poll_init(loop, &poll_handle));
+ len = sizeof buf;
+ ASSERT(UV_EINVAL == uv_fs_poll_getpath(&poll_handle, buf, &len));
+ ASSERT(0 == uv_fs_poll_start(&poll_handle, poll_cb_fail, FIXTURE, 100));
+ len = sizeof buf;
+ ASSERT(0 == uv_fs_poll_getpath(&poll_handle, buf, &len));
+ ASSERT(0 == memcmp(buf, FIXTURE, len));
+
+ uv_close((uv_handle_t*) &poll_handle, close_cb);
+
+ ASSERT(0 == uv_run(loop, UV_RUN_DEFAULT));
+
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c
index f0ff824f40..940672f8bc 100644
--- a/deps/uv/test/test-fs.c
+++ b/deps/uv/test/test-fs.c
@@ -102,7 +102,7 @@ static uv_fs_t futime_req;
static char buf[32];
static char test_buf[] = "test-buffer\n";
-
+static uv_buf_t iov;
static void check_permission(const char* filename, unsigned int mode) {
int r;
@@ -284,7 +284,8 @@ static void open_cb(uv_fs_t* req) {
ASSERT(memcmp(req->path, "test_file2\0", 11) == 0);
uv_fs_req_cleanup(req);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
read_cb);
ASSERT(r == 0);
}
@@ -345,8 +346,8 @@ static void create_cb(uv_fs_t* req) {
ASSERT(req->result >= 0);
create_cb_count++;
uv_fs_req_cleanup(req);
- r = uv_fs_write(loop, &write_req, req->result, test_buf, sizeof(test_buf),
- -1, write_cb);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, req->result, &iov, 1, -1, write_cb);
ASSERT(r == 0);
}
@@ -663,8 +664,8 @@ TEST_IMPL(fs_file_sync) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
- sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@@ -679,8 +680,8 @@ TEST_IMPL(fs_file_sync) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
- NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@@ -707,7 +708,8 @@ TEST_IMPL(fs_file_sync) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
@@ -733,6 +735,38 @@ TEST_IMPL(fs_file_sync) {
}
+TEST_IMPL(fs_file_write_null_buffer) {
+ int r;
+
+ /* Setup. */
+ unlink("test_file");
+
+ loop = uv_default_loop();
+
+ r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT,
+ S_IWUSR | S_IRUSR, NULL);
+ ASSERT(r >= 0);
+ ASSERT(open_req1.result >= 0);
+ uv_fs_req_cleanup(&open_req1);
+
+ iov = uv_buf_init(NULL, 0);
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
+ ASSERT(r == 0);
+ ASSERT(write_req.result == 0);
+ uv_fs_req_cleanup(&write_req);
+
+ r = uv_fs_close(loop, &close_req, open_req1.result, NULL);
+ ASSERT(r == 0);
+ ASSERT(close_req.result == 0);
+ uv_fs_req_cleanup(&close_req);
+
+ unlink("test_file");
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
TEST_IMPL(fs_async_dir) {
int r;
@@ -910,7 +944,8 @@ TEST_IMPL(fs_fstat) {
file = req.result;
uv_fs_req_cleanup(&req);
- r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@@ -1020,7 +1055,8 @@ TEST_IMPL(fs_chmod) {
file = req.result;
uv_fs_req_cleanup(&req);
- r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@@ -1183,7 +1219,8 @@ TEST_IMPL(fs_link) {
file = req.result;
uv_fs_req_cleanup(&req);
- r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@@ -1203,7 +1240,8 @@ TEST_IMPL(fs_link) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@@ -1223,7 +1261,8 @@ TEST_IMPL(fs_link) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@@ -1289,7 +1328,8 @@ TEST_IMPL(fs_symlink) {
file = req.result;
uv_fs_req_cleanup(&req);
- r = uv_fs_write(loop, &req, file, test_buf, sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &req, file, &iov, 1, -1, NULL);
ASSERT(r == sizeof(test_buf));
ASSERT(req.result == sizeof(test_buf));
uv_fs_req_cleanup(&req);
@@ -1326,7 +1366,8 @@ TEST_IMPL(fs_symlink) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@@ -1365,7 +1406,8 @@ TEST_IMPL(fs_symlink) {
uv_fs_req_cleanup(&req);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &req, link, buf, sizeof(buf), 0, NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &req, link, &iov, 1, 0, NULL);
ASSERT(r >= 0);
ASSERT(req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
@@ -1774,8 +1816,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
- sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@@ -1790,8 +1832,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
- sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@@ -1806,7 +1848,8 @@ TEST_IMPL(fs_file_open_append) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
printf("read = %d\n", r);
ASSERT(r == 26);
@@ -1844,8 +1887,8 @@ TEST_IMPL(fs_rename_to_existing_file) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
- sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@@ -1877,7 +1920,8 @@ TEST_IMPL(fs_rename_to_existing_file) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1,
NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
@@ -1912,8 +1956,8 @@ TEST_IMPL(fs_read_file_eof) {
ASSERT(open_req1.result >= 0);
uv_fs_req_cleanup(&open_req1);
- r = uv_fs_write(loop, &write_req, open_req1.result, test_buf,
- sizeof(test_buf), -1, NULL);
+ iov = uv_buf_init(test_buf, sizeof(test_buf));
+ r = uv_fs_write(loop, &write_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(write_req.result >= 0);
uv_fs_req_cleanup(&write_req);
@@ -1929,15 +1973,16 @@ TEST_IMPL(fs_read_file_eof) {
uv_fs_req_cleanup(&open_req1);
memset(buf, 0, sizeof(buf));
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1,
- NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1, -1, NULL);
ASSERT(r >= 0);
ASSERT(read_req.result >= 0);
ASSERT(strcmp(buf, test_buf) == 0);
uv_fs_req_cleanup(&read_req);
- r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf),
- read_req.result, NULL);
+ iov = uv_buf_init(buf, sizeof(buf));
+ r = uv_fs_read(loop, &read_req, open_req1.result, &iov, 1,
+ read_req.result, NULL);
ASSERT(r == 0);
ASSERT(read_req.result == 0);
uv_fs_req_cleanup(&read_req);
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index c3e15783b5..0252acc354 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -25,6 +25,7 @@ TEST_DECLARE (close_order)
TEST_DECLARE (run_once)
TEST_DECLARE (run_nowait)
TEST_DECLARE (loop_alive)
+TEST_DECLARE (loop_close)
TEST_DECLARE (loop_stop)
TEST_DECLARE (loop_update_time)
TEST_DECLARE (barrier_1)
@@ -81,6 +82,7 @@ TEST_DECLARE (tcp_bind6_localhost_ok)
TEST_DECLARE (udp_send_and_recv)
TEST_DECLARE (udp_multicast_join)
TEST_DECLARE (udp_multicast_ttl)
+TEST_DECLARE (udp_multicast_interface)
TEST_DECLARE (udp_dgram_too_big)
TEST_DECLARE (udp_dual_stack)
TEST_DECLARE (udp_ipv6_only)
@@ -92,12 +94,15 @@ TEST_DECLARE (pipe_bind_error_inval)
TEST_DECLARE (pipe_listen_without_bind)
TEST_DECLARE (pipe_connect_bad_name)
TEST_DECLARE (pipe_connect_to_file)
+TEST_DECLARE (pipe_getsockname)
+TEST_DECLARE (pipe_getsockname_abstract)
TEST_DECLARE (pipe_server_close)
TEST_DECLARE (connection_fail)
TEST_DECLARE (connection_fail_doesnt_auto_close)
TEST_DECLARE (shutdown_close_tcp)
TEST_DECLARE (shutdown_close_pipe)
TEST_DECLARE (shutdown_eof)
+TEST_DECLARE (shutdown_twice)
TEST_DECLARE (callback_stack)
TEST_DECLARE (error_message)
TEST_DECLARE (timer)
@@ -171,12 +176,14 @@ TEST_DECLARE (spawn_stdout_to_file)
TEST_DECLARE (spawn_stdout_and_stderr_to_file)
TEST_DECLARE (spawn_auto_unref)
TEST_DECLARE (fs_poll)
+TEST_DECLARE (fs_poll_getpath)
TEST_DECLARE (kill)
TEST_DECLARE (fs_file_noent)
TEST_DECLARE (fs_file_nametoolong)
TEST_DECLARE (fs_file_loop)
TEST_DECLARE (fs_file_async)
TEST_DECLARE (fs_file_sync)
+TEST_DECLARE (fs_file_write_null_buffer)
TEST_DECLARE (fs_async_dir)
TEST_DECLARE (fs_async_sendfile)
TEST_DECLARE (fs_fstat)
@@ -202,6 +209,7 @@ 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_event_error_reporting)
+TEST_DECLARE (fs_event_getpath)
TEST_DECLARE (fs_readdir_empty_dir)
TEST_DECLARE (fs_readdir_file)
TEST_DECLARE (fs_open_dir)
@@ -233,10 +241,12 @@ TEST_DECLARE (fs_stat_root)
#else
TEST_DECLARE (emfile)
TEST_DECLARE (close_fd)
+TEST_DECLARE (spawn_fs_open)
TEST_DECLARE (spawn_setuid_setgid)
TEST_DECLARE (we_get_signal)
TEST_DECLARE (we_get_signals)
TEST_DECLARE (signal_multiple_loops)
+TEST_DECLARE (closed_fd_events)
#endif
#ifdef __APPLE__
TEST_DECLARE (osx_select)
@@ -248,7 +258,7 @@ HELPER_DECLARE (pipe_echo_server)
TASK_LIST_START
- TEST_OUTPUT_ENTRY (platform_output)
+ TEST_ENTRY_CUSTOM (platform_output, 0, 1, 5000)
#if 0
TEST_ENTRY (callback_order)
@@ -257,6 +267,7 @@ TASK_LIST_START
TEST_ENTRY (run_once)
TEST_ENTRY (run_nowait)
TEST_ENTRY (loop_alive)
+ TEST_ENTRY (loop_close)
TEST_ENTRY (loop_stop)
TEST_ENTRY (loop_update_time)
TEST_ENTRY (barrier_1)
@@ -349,6 +360,8 @@ TASK_LIST_START
TEST_ENTRY (pipe_bind_error_addrnotavail)
TEST_ENTRY (pipe_bind_error_inval)
TEST_ENTRY (pipe_listen_without_bind)
+ TEST_ENTRY (pipe_getsockname)
+ TEST_ENTRY (pipe_getsockname_abstract)
TEST_ENTRY (connection_fail)
TEST_ENTRY (connection_fail_doesnt_auto_close)
@@ -361,6 +374,9 @@ TASK_LIST_START
TEST_ENTRY (shutdown_eof)
TEST_HELPER (shutdown_eof, tcp4_echo_server)
+ TEST_ENTRY (shutdown_twice)
+ TEST_HELPER (shutdown_twice, tcp4_echo_server)
+
TEST_ENTRY (callback_stack)
TEST_HELPER (callback_stack, tcp4_echo_server)
@@ -432,7 +448,8 @@ TASK_LIST_START
TEST_ENTRY (hrtime)
- TEST_ENTRY (getaddrinfo_fail)
+ TEST_ENTRY_CUSTOM (getaddrinfo_fail, 0, 0, 10000)
+
TEST_ENTRY (getaddrinfo_basic)
TEST_ENTRY (getaddrinfo_concurrent)
@@ -460,6 +477,7 @@ TASK_LIST_START
TEST_ENTRY (spawn_stdout_and_stderr_to_file)
TEST_ENTRY (spawn_auto_unref)
TEST_ENTRY (fs_poll)
+ TEST_ENTRY (fs_poll_getpath)
TEST_ENTRY (kill)
#ifdef _WIN32
@@ -472,10 +490,12 @@ TASK_LIST_START
#else
TEST_ENTRY (emfile)
TEST_ENTRY (close_fd)
+ TEST_ENTRY (spawn_fs_open)
TEST_ENTRY (spawn_setuid_setgid)
TEST_ENTRY (we_get_signal)
TEST_ENTRY (we_get_signals)
TEST_ENTRY (signal_multiple_loops)
+ TEST_ENTRY (closed_fd_events)
#endif
#ifdef __APPLE__
@@ -487,6 +507,7 @@ TASK_LIST_START
TEST_ENTRY (fs_file_loop)
TEST_ENTRY (fs_file_async)
TEST_ENTRY (fs_file_sync)
+ TEST_ENTRY (fs_file_write_null_buffer)
TEST_ENTRY (fs_async_dir)
TEST_ENTRY (fs_async_sendfile)
TEST_ENTRY (fs_fstat)
@@ -511,6 +532,7 @@ TASK_LIST_START
TEST_ENTRY (fs_event_close_in_callback)
TEST_ENTRY (fs_event_start_and_close)
TEST_ENTRY (fs_event_error_reporting)
+ TEST_ENTRY (fs_event_getpath)
TEST_ENTRY (fs_readdir_empty_dir)
TEST_ENTRY (fs_readdir_file)
TEST_ENTRY (fs_open_dir)
diff --git a/deps/uv/test/test-loop-close.c b/deps/uv/test/test-loop-close.c
new file mode 100644
index 0000000000..fa053469b8
--- /dev/null
+++ b/deps/uv/test/test-loop-close.c
@@ -0,0 +1,54 @@
+/* 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 uv_timer_t timer_handle;
+
+static void timer_cb(uv_timer_t* handle, int status) {
+ ASSERT(handle);
+ ASSERT(status == 0);
+ uv_stop(handle->loop);
+}
+
+
+TEST_IMPL(loop_close) {
+ int r;
+ uv_loop_t loop;
+
+ ASSERT(0 == uv_loop_init(&loop));
+
+ uv_timer_init(&loop, &timer_handle);
+ uv_timer_start(&timer_handle, timer_cb, 100, 100);
+
+ ASSERT(UV_EBUSY == uv_loop_close(&loop));
+
+ uv_run(&loop, UV_RUN_DEFAULT);
+
+ uv_close((uv_handle_t*) &timer_handle, NULL);
+ r = uv_run(&loop, UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(0 == uv_loop_close(&loop));
+
+ return 0;
+}
diff --git a/deps/uv/test/test-pipe-getsockname.c b/deps/uv/test/test-pipe-getsockname.c
new file mode 100644
index 0000000000..396f72577d
--- /dev/null
+++ b/deps/uv/test/test-pipe-getsockname.c
@@ -0,0 +1,122 @@
+/* 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"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(__linux__)
+ #include <sys/socket.h>
+ #include <sys/un.h>
+#endif
+
+#ifndef _WIN32
+# include <unistd.h> /* close */
+#endif
+
+
+static int close_cb_called = 0;
+
+
+static void close_cb(uv_handle_t* handle) {
+ ASSERT(handle != NULL);
+ close_cb_called++;
+}
+
+
+TEST_IMPL(pipe_getsockname) {
+ uv_pipe_t server;
+ char buf[1024];
+ size_t len;
+ int r;
+
+ r = uv_pipe_init(uv_default_loop(), &server, 0);
+ ASSERT(r == 0);
+ r = uv_pipe_bind(&server, TEST_PIPENAME);
+ ASSERT(r == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&server, buf, &len);
+ ASSERT(r == 0);
+
+ ASSERT(memcmp(buf, TEST_PIPENAME, len) == 0);
+
+ uv_close((uv_handle_t*)&server, close_cb);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+
+
+TEST_IMPL(pipe_getsockname_abstract) {
+#if defined(__linux__)
+ uv_pipe_t server;
+ char buf[1024];
+ size_t len;
+ int r;
+ int sock;
+ struct sockaddr_un sun;
+ socklen_t sun_len;
+ char abstract_pipe[] = "\0test-pipe";
+
+ sock = socket(AF_LOCAL, SOCK_STREAM, 0);
+ ASSERT(sock != -1);
+
+ sun_len = sizeof sun;
+ memset(&sun, 0, sun_len);
+ sun.sun_family = AF_UNIX;
+ memcpy(sun.sun_path, abstract_pipe, sizeof abstract_pipe);
+
+ r = bind(sock, (struct sockaddr*)&sun, sun_len);
+ ASSERT(r == 0);
+
+ r = uv_pipe_init(uv_default_loop(), &server, 0);
+ ASSERT(r == 0);
+ r = uv_pipe_open(&server, sock);
+ ASSERT(r == 0);
+
+ len = sizeof buf;
+ r = uv_pipe_getsockname(&server, buf, &len);
+ ASSERT(r == 0);
+
+ ASSERT(memcmp(buf, abstract_pipe, sizeof abstract_pipe) == 0);
+
+ uv_close((uv_handle_t*)&server, close_cb);
+
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ close(sock);
+
+ ASSERT(close_cb_called == 1);
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+#else
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+#endif
+}
+
diff --git a/deps/uv/test/test-platform-output.c b/deps/uv/test/test-platform-output.c
index d2104f40a1..931311985b 100644
--- a/deps/uv/test/test-platform-output.c
+++ b/deps/uv/test/test-platform-output.c
@@ -28,6 +28,7 @@ TEST_IMPL(platform_output) {
char buffer[512];
size_t rss;
double uptime;
+ uv_rusage_t rusage;
uv_cpu_info_t* cpus;
uv_interface_address_t* interfaces;
int count;
@@ -47,6 +48,20 @@ TEST_IMPL(platform_output) {
ASSERT(uptime > 0);
printf("uv_uptime: %f\n", uptime);
+ err = uv_getrusage(&rusage);
+ ASSERT(err == 0);
+ ASSERT(rusage.ru_utime.tv_sec >= 0);
+ ASSERT(rusage.ru_utime.tv_usec >= 0);
+ ASSERT(rusage.ru_stime.tv_sec >= 0);
+ ASSERT(rusage.ru_stime.tv_usec >= 0);
+ printf("uv_getrusage:\n");
+ printf(" user: %llu sec %llu microsec\n",
+ (unsigned long long) rusage.ru_utime.tv_sec,
+ (unsigned long long) rusage.ru_utime.tv_usec);
+ printf(" system: %llu sec %llu microsec\n",
+ (unsigned long long) rusage.ru_stime.tv_sec,
+ (unsigned long long) rusage.ru_stime.tv_usec);
+
err = uv_cpu_info(&cpus, &count);
ASSERT(err == 0);
diff --git a/deps/uv/test/test-shutdown-twice.c b/deps/uv/test/test-shutdown-twice.c
new file mode 100644
index 0000000000..75c0543549
--- /dev/null
+++ b/deps/uv/test/test-shutdown-twice.c
@@ -0,0 +1,84 @@
+/* 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.
+ */
+
+/*
+ * This is a regression test for issue #1113 (calling uv_shutdown twice will
+ * leave a ghost request in the system)
+ */
+
+#include "uv.h"
+#include "task.h"
+
+static uv_shutdown_t req1;
+static uv_shutdown_t req2;
+
+static int shutdown_cb_called = 0;
+
+static void close_cb(uv_handle_t* handle) {
+
+}
+
+static void shutdown_cb(uv_shutdown_t* req, int status) {
+ ASSERT(req == &req1);
+ ASSERT(status == 0);
+ shutdown_cb_called++;
+ uv_close((uv_handle_t*) req->handle, close_cb);
+}
+
+static void connect_cb(uv_connect_t* req, int status) {
+ int r;
+
+ ASSERT(status == 0);
+
+ r = uv_shutdown(&req1, req->handle, shutdown_cb);
+ ASSERT(r == 0);
+ r = uv_shutdown(&req2, req->handle, shutdown_cb);
+ ASSERT(r != 0);
+
+}
+
+TEST_IMPL(shutdown_twice) {
+ struct sockaddr_in addr;
+ uv_loop_t* loop;
+ int r;
+ uv_tcp_t h;
+
+ uv_connect_t connect_req;
+
+ ASSERT(0 == uv_ip4_addr("127.0.0.1", TEST_PORT, &addr));
+ loop = uv_default_loop();
+
+ r = uv_tcp_init(loop, &h);
+
+ r = uv_tcp_connect(&connect_req,
+ &h,
+ (const struct sockaddr*) &addr,
+ connect_cb);
+ ASSERT(r == 0);
+
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+ ASSERT(r == 0);
+
+ ASSERT(shutdown_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/test/test-signal-multiple-loops.c b/deps/uv/test/test-signal-multiple-loops.c
index e80154e3e8..f8fef36ee0 100644
--- a/deps/uv/test/test-signal-multiple-loops.c
+++ b/deps/uv/test/test-signal-multiple-loops.c
@@ -84,28 +84,27 @@ static void signal_handling_worker(void* context) {
uv_signal_t signal1a;
uv_signal_t signal1b;
uv_signal_t signal2;
- uv_loop_t* loop;
+ uv_loop_t loop;
int r;
action = (enum signal_action) (uintptr_t) context;
- loop = uv_loop_new();
- ASSERT(loop != NULL);
+ ASSERT(0 == uv_loop_init(&loop));
/* Setup the signal watchers and start them. */
if (action == ONLY_SIGUSR1 || action == SIGUSR1_AND_SIGUSR2) {
- r = uv_signal_init(loop, &signal1a);
+ r = uv_signal_init(&loop, &signal1a);
ASSERT(r == 0);
r = uv_signal_start(&signal1a, signal1_cb, SIGUSR1);
ASSERT(r == 0);
- r = uv_signal_init(loop, &signal1b);
+ r = uv_signal_init(&loop, &signal1b);
ASSERT(r == 0);
r = uv_signal_start(&signal1b, signal1_cb, SIGUSR1);
ASSERT(r == 0);
}
if (action == ONLY_SIGUSR2 || action == SIGUSR1_AND_SIGUSR2) {
- r = uv_signal_init(loop, &signal2);
+ r = uv_signal_init(&loop, &signal2);
ASSERT(r == 0);
r = uv_signal_start(&signal2, signal2_cb, SIGUSR2);
ASSERT(r == 0);
@@ -117,7 +116,7 @@ static void signal_handling_worker(void* context) {
/* Wait for all signals. The signal callbacks stop the watcher, so uv_run
* will return when all signal watchers caught a signal.
*/
- r = uv_run(loop, UV_RUN_DEFAULT);
+ r = uv_run(&loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
/* Restart the signal watchers. */
@@ -136,7 +135,7 @@ static void signal_handling_worker(void* context) {
/* Wait for signals once more. */
uv_sem_post(&sem);
- r = uv_run(loop, UV_RUN_DEFAULT);
+ r = uv_run(&loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
/* Close the watchers. */
@@ -150,10 +149,10 @@ static void signal_handling_worker(void* context) {
}
/* Wait for the signal watchers to close. */
- r = uv_run(loop, UV_RUN_DEFAULT);
+ r = uv_run(&loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
- uv_loop_delete(loop);
+ uv_loop_close(&loop);
}
@@ -166,12 +165,13 @@ static void loop_creating_worker(void* context) {
(void) context;
do {
- uv_loop_t* loop;
+ uv_loop_t *loop;
uv_signal_t signal;
int r;
- loop = uv_loop_new();
+ loop = malloc(sizeof(*loop));
ASSERT(loop != NULL);
+ ASSERT(0 == uv_loop_init(loop));
r = uv_signal_init(loop, &signal);
ASSERT(r == 0);
@@ -184,7 +184,7 @@ static void loop_creating_worker(void* context) {
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
- uv_loop_delete(loop);
+ uv_loop_close(loop);
increment_counter(&loop_creation_counter);
} while (!stop);
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
index 5f71fce2c0..84dd200175 100644
--- a/deps/uv/test/test-spawn.c
+++ b/deps/uv/test/test-spawn.c
@@ -40,6 +40,7 @@ static char exepath[1024];
static size_t exepath_size = 1024;
static char* args[3];
static int no_term_signal;
+static int timer_counter;
#define OUTPUT_SIZE 1024
static char output[OUTPUT_SIZE];
@@ -118,6 +119,12 @@ static void on_read(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
}
+static void on_read_once(uv_stream_t* tcp, ssize_t nread, const uv_buf_t* buf) {
+ uv_read_stop(tcp);
+ on_read(tcp, nread, buf);
+}
+
+
static void write_cb(uv_write_t* req, int status) {
ASSERT(status == 0);
uv_close((uv_handle_t*)req->handle, close_cb);
@@ -145,6 +152,11 @@ static void timer_cb(uv_timer_t* handle, int status) {
}
+static void timer_counter_cb(uv_timer_t* handle, int status) {
+ ++timer_counter;
+}
+
+
TEST_IMPL(spawn_fails) {
int r;
@@ -218,6 +230,7 @@ TEST_IMPL(spawn_stdout_to_file) {
uv_file file;
uv_fs_t fs_req;
uv_stdio_container_t stdio[2];
+ uv_buf_t buf;
/* Setup. */
unlink("stdout_file");
@@ -246,8 +259,8 @@ TEST_IMPL(spawn_stdout_to_file) {
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 1);
- r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
- 0, NULL);
+ buf = uv_buf_init(output, sizeof(output));
+ r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 12);
uv_fs_req_cleanup(&fs_req);
@@ -271,6 +284,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
uv_file file;
uv_fs_t fs_req;
uv_stdio_container_t stdio[3];
+ uv_buf_t buf;
/* Setup. */
unlink("stdout_file");
@@ -278,7 +292,7 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
init_process_options("spawn_helper6", exit_cb);
r = uv_fs_open(uv_default_loop(), &fs_req, "stdout_file", O_CREAT | O_RDWR,
- S_IREAD | S_IWRITE, NULL);
+ S_IRUSR | S_IWUSR, NULL);
ASSERT(r != -1);
uv_fs_req_cleanup(&fs_req);
@@ -301,8 +315,8 @@ TEST_IMPL(spawn_stdout_and_stderr_to_file) {
ASSERT(exit_cb_called == 1);
ASSERT(close_cb_called == 1);
- r = uv_fs_read(uv_default_loop(), &fs_req, file, output, sizeof(output),
- 0, NULL);
+ buf = uv_buf_init(output, sizeof(output));
+ r = uv_fs_read(uv_default_loop(), &fs_req, file, &buf, 1, 0, NULL);
ASSERT(r == 27);
uv_fs_req_cleanup(&fs_req);
@@ -1049,3 +1063,102 @@ TEST_IMPL(spawn_auto_unref) {
MAKE_VALGRIND_HAPPY();
return 0;
}
+
+
+#ifndef _WIN32
+TEST_IMPL(spawn_fs_open) {
+ int fd;
+ uv_fs_t fs_req;
+ uv_pipe_t in;
+ uv_write_t write_req;
+ uv_buf_t buf;
+ uv_stdio_container_t stdio[1];
+
+ fd = uv_fs_open(uv_default_loop(), &fs_req, "/dev/null", O_RDWR, 0, NULL);
+ ASSERT(fd >= 0);
+
+ init_process_options("spawn_helper8", exit_cb);
+
+ ASSERT(0 == uv_pipe_init(uv_default_loop(), &in, 0));
+
+ options.stdio = stdio;
+ options.stdio[0].flags = UV_CREATE_PIPE | UV_READABLE_PIPE;
+ options.stdio[0].data.stream = (uv_stream_t*) &in;
+ options.stdio_count = 1;
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
+
+ buf = uv_buf_init((char*) &fd, sizeof(fd));
+ ASSERT(0 == uv_write(&write_req, (uv_stream_t*) &in, &buf, 1, write_cb));
+
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT));
+ ASSERT(0 == uv_fs_close(uv_default_loop(), &fs_req, fd, NULL));
+
+ ASSERT(exit_cb_called == 1);
+ ASSERT(close_cb_called == 2); /* One for `in`, one for process */
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif /* !_WIN32 */
+
+
+#ifndef _WIN32
+TEST_IMPL(closed_fd_events) {
+ uv_stdio_container_t stdio[3];
+ uv_pipe_t pipe_handle;
+ int fd[2];
+
+ /* create a pipe and share it with a child process */
+ ASSERT(0 == pipe(fd));
+ ASSERT(0 == fcntl(fd[0], F_SETFL, O_NONBLOCK));
+
+ /* spawn_helper4 blocks indefinitely. */
+ init_process_options("spawn_helper4", exit_cb);
+ options.stdio_count = 3;
+ options.stdio = stdio;
+ options.stdio[0].flags = UV_INHERIT_FD;
+ options.stdio[0].data.fd = fd[0];
+ options.stdio[1].flags = UV_IGNORE;
+ options.stdio[2].flags = UV_IGNORE;
+
+ ASSERT(0 == uv_spawn(uv_default_loop(), &process, &options));
+ uv_unref((uv_handle_t*) &process);
+
+ /* read from the pipe with uv */
+ ASSERT(0 == uv_pipe_init(uv_default_loop(), &pipe_handle, 0));
+ ASSERT(0 == uv_pipe_open(&pipe_handle, fd[0]));
+ fd[0] = -1;
+
+ ASSERT(0 == uv_read_start((uv_stream_t*) &pipe_handle, on_alloc, on_read_once));
+
+ ASSERT(1 == write(fd[1], "", 1));
+
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+
+ /* should have received just one byte */
+ ASSERT(output_used == 1);
+
+ /* close the pipe and see if we still get events */
+ uv_close((uv_handle_t*) &pipe_handle, close_cb);
+
+ ASSERT(1 == write(fd[1], "", 1));
+
+ ASSERT(0 == uv_timer_init(uv_default_loop(), &timer));
+ ASSERT(0 == uv_timer_start(&timer, timer_counter_cb, 10, 0));
+
+ /* see if any spurious events interrupt the timer */
+ if (1 == uv_run(uv_default_loop(), UV_RUN_ONCE))
+ /* have to run again to really trigger the timer */
+ ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_ONCE));
+
+ ASSERT(timer_counter == 1);
+
+ /* cleanup */
+ ASSERT(0 == uv_process_kill(&process, /* SIGTERM */ 15));
+ ASSERT(0 == close(fd[1]));
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
+#endif /* !_WIN32 */
diff --git a/deps/uv/test/test-thread.c b/deps/uv/test/test-thread.c
index c396baa100..7f3321aa06 100644
--- a/deps/uv/test/test-thread.c
+++ b/deps/uv/test/test-thread.c
@@ -112,8 +112,9 @@ static void do_work(void* arg) {
int r;
struct test_thread* thread = arg;
- loop = uv_loop_new();
+ loop = malloc(sizeof *loop);
ASSERT(loop != NULL);
+ ASSERT(0 == uv_loop_init(loop));
for (i = 0; i < ARRAY_SIZE(getaddrinfo_reqs); i++) {
struct getaddrinfo_req* req = getaddrinfo_reqs + i;
@@ -132,7 +133,8 @@ static void do_work(void* arg) {
r = uv_run(loop, UV_RUN_DEFAULT);
ASSERT(r == 0);
- uv_loop_delete(loop);
+ ASSERT(0 == uv_loop_close(loop));
+ free(loop);
thread->thread_called = 1;
}
diff --git a/deps/uv/test/test-threadpool-cancel.c b/deps/uv/test/test-threadpool-cancel.c
index 1443773cc2..c3186ea5df 100644
--- a/deps/uv/test/test-threadpool-cancel.c
+++ b/deps/uv/test/test-threadpool-cancel.c
@@ -86,7 +86,7 @@ static void saturate_threadpool(void) {
* the thread pool is saturated. As with any timing dependent test,
* this is obviously not ideal.
*/
- if (uv_cond_timedwait(&signal_cond, &signal_mutex, 350 * 1e6)) {
+ if (uv_cond_timedwait(&signal_cond, &signal_mutex, (uint64_t)(350 * 1e6))) {
ASSERT(0 == uv_cancel((uv_req_t*) req));
break;
}
diff --git a/deps/uv/test/test-udp-multicast-interface.c b/deps/uv/test/test-udp-multicast-interface.c
new file mode 100644
index 0000000000..643df31802
--- /dev/null
+++ b/deps/uv/test/test-udp-multicast-interface.c
@@ -0,0 +1,96 @@
+/* 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"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define CHECK_HANDLE(handle) \
+ ASSERT((uv_udp_t*)(handle) == &server || (uv_udp_t*)(handle) == &client)
+
+static uv_udp_t server;
+static uv_udp_t client;
+
+static int sv_send_cb_called;
+static int close_cb_called;
+
+
+static void close_cb(uv_handle_t* handle) {
+ CHECK_HANDLE(handle);
+ close_cb_called++;
+}
+
+
+static void sv_send_cb(uv_udp_send_t* req, int status) {
+ ASSERT(req != NULL);
+ ASSERT(status == 0);
+ CHECK_HANDLE(req->handle);
+
+ sv_send_cb_called++;
+
+ uv_close((uv_handle_t*) req->handle, close_cb);
+}
+
+
+TEST_IMPL(udp_multicast_interface) {
+ int r;
+ uv_udp_send_t req;
+ uv_buf_t buf;
+ struct sockaddr_in addr;
+ struct sockaddr_in baddr;
+
+ ASSERT(0 == uv_ip4_addr("239.255.0.1", TEST_PORT, &addr));
+
+ r = uv_udp_init(uv_default_loop(), &server);
+ ASSERT(r == 0);
+
+ ASSERT(0 == uv_ip4_addr("0.0.0.0", 0, &baddr));
+ r = uv_udp_bind(&server, (const struct sockaddr*)&baddr, 0);
+ ASSERT(r == 0);
+
+ r = uv_udp_set_multicast_interface(&server, "0.0.0.0");
+ ASSERT(r == 0);
+
+ /* server sends "PING" */
+ buf = uv_buf_init("PING", 4);
+ r = uv_udp_send(&req,
+ &server,
+ &buf,
+ 1,
+ (const struct sockaddr*)&addr,
+ sv_send_cb);
+ ASSERT(r == 0);
+
+ ASSERT(close_cb_called == 0);
+ ASSERT(sv_send_cb_called == 0);
+
+ /* run the loop till all events are processed */
+ uv_run(uv_default_loop(), UV_RUN_DEFAULT);
+
+ ASSERT(sv_send_cb_called == 1);
+ ASSERT(close_cb_called == 1);
+
+ MAKE_VALGRIND_HAPPY();
+ return 0;
+}
diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp
index 50e19357de..d84755aab2 100644
--- a/deps/uv/uv.gyp
+++ b/deps/uv/uv.gyp
@@ -31,7 +31,7 @@
'targets': [
{
'target_name': 'libuv',
- 'type': '<(library)',
+ 'type': '<(uv_library)',
'include_dirs': [
'include',
'src/',
@@ -61,7 +61,9 @@
'include/uv.h',
'include/tree.h',
'include/uv-errno.h',
+ 'include/uv-version.h',
'src/fs-poll.c',
+ 'src/heap-inl.h',
'src/inet.c',
'src/queue.h',
'src/uv-common.c',
@@ -167,10 +169,10 @@
],
},
'conditions': [
- ['library=="shared_library"', {
+ ['uv_library=="shared_library"', {
'cflags': [ '-fPIC' ],
}],
- ['library=="shared_library" and OS!="mac"', {
+ ['uv_library=="shared_library" and OS!="mac"', {
'link_settings': {
# Must correspond with UV_VERSION_MAJOR and UV_VERSION_MINOR
# in src/version.c
@@ -265,7 +267,7 @@
[ 'OS in "mac freebsd dragonflybsd openbsd netbsd".split()', {
'sources': [ 'src/unix/kqueue.c' ],
}],
- ['library=="shared_library"', {
+ ['uv_library=="shared_library"', {
'defines': [ 'BUILDING_UV_SHARED=1' ]
}],
# FIXME(bnoordhuis or tjfontaine) Unify this, it's extremely ugly.
@@ -324,6 +326,7 @@
'test/test-list.h',
'test/test-loop-handles.c',
'test/test-loop-alive.c',
+ 'test/test-loop-close.c',
'test/test-loop-stop.c',
'test/test-loop-time.c',
'test/test-walk-handles.c',
@@ -334,6 +337,7 @@
'test/test-ping-pong.c',
'test/test-pipe-bind-error.c',
'test/test-pipe-connect-error.c',
+ 'test/test-pipe-getsockname.c',
'test/test-pipe-server-close.c',
'test/test-platform-output.c',
'test/test-poll.c',
@@ -345,6 +349,7 @@
'test/test-semaphore.c',
'test/test-shutdown-close.c',
'test/test-shutdown-eof.c',
+ 'test/test-shutdown-twice.c',
'test/test-signal.c',
'test/test-signal-multiple-loops.c',
'test/test-spawn.c',
@@ -387,6 +392,7 @@
'test/test-udp-multicast-ttl.c',
'test/test-ip4-addr.c',
'test/test-ip6-addr.c',
+ 'test/test-udp-multicast-interface.c',
],
'conditions': [
[ 'OS=="win"', {
diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat
index 8545b2635b..df6eda0178 100644
--- a/deps/uv/vcbuild.bat
+++ b/deps/uv/vcbuild.bat
@@ -33,7 +33,7 @@ if /i "%1"=="noprojgen" set noprojgen=1&goto arg-ok
if /i "%1"=="nobuild" set nobuild=1&goto arg-ok
if /i "%1"=="x86" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
if /i "%1"=="ia32" set target_arch=ia32&set platform=WIN32&set vs_toolset=x86&goto arg-ok
-if /i "%1"=="x64" set target_arch=x64&set platform=amd64&set vs_toolset=x64&goto arg-ok
+if /i "%1"=="x64" set target_arch=x64&set platform=x64&set vs_toolset=x64&goto arg-ok
if /i "%1"=="shared" set library=shared_library&goto arg-ok
if /i "%1"=="static" set library=static_library&goto arg-ok
:arg-ok
@@ -41,6 +41,9 @@ shift
goto next-arg
:args-done
+if defined WindowsSDKDir goto select-target
+if defined VCINSTALLDIR goto select-target
+
@rem Look for Visual Studio 2013
if not defined VS120COMNTOOLS goto vc-set-2012
if not exist "%VS120COMNTOOLS%\..\..\vc\vcvarsall.bat" goto vc-set-2012
@@ -99,7 +102,7 @@ exit /b 1
:have_gyp
if not defined PYTHON set PYTHON="python"
-%PYTHON% gyp_uv.py -Dtarget_arch=%target_arch% -Dlibrary=%library%
+%PYTHON% gyp_uv.py -Dtarget_arch=%target_arch% -Duv_library=%library%
if errorlevel 1 goto create-msvs-files-failed
if not exist uv.sln goto create-msvs-files-failed
echo Project files generated.
@@ -109,10 +112,8 @@ echo Project files generated.
if defined nobuild goto run
@rem Check if VS build env is available
-if not defined VCINSTALLDIR goto msbuild-not-found
-goto msbuild-found
-
-:msbuild-not-found
+if defined VCINSTALLDIR goto msbuild-found
+if defined WindowsSDKDir goto msbuild-found
echo Build skipped. To build, this file needs to run from VS cmd prompt.
goto run