From fdeb5ba3043bbd173bd5b7308e98dde723f66d5c Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Mon, 7 Nov 2011 19:24:25 -0800 Subject: [PATCH] Upgrade libuv to f1859eb841be2fe48512bc10e64556383f408b01 --- .../ia32/mac/src/rt/libuv/run-tests.target.mk | 3 + mk/libuv/ia32/mac/src/rt/libuv/uv.target.mk | 1 + .../src/rt/libuv/run-benchmarks.target.mk | 4 +- .../unix/src/rt/libuv/run-tests.target.mk | 7 +- mk/libuv/ia32/unix/src/rt/libuv/uv.target.mk | 4 +- .../ia32/win/src/rt/libuv/run-tests.target.mk | 3 + mk/libuv/ia32/win/src/rt/libuv/uv.target.mk | 1 + .../mac/src/rt/libuv/run-tests.target.mk | 3 + mk/libuv/x86_64/mac/src/rt/libuv/uv.target.mk | 1 + .../src/rt/libuv/run-benchmarks.target.mk | 4 +- .../unix/src/rt/libuv/run-tests.target.mk | 7 +- .../x86_64/unix/src/rt/libuv/uv.target.mk | 4 +- .../win/src/rt/libuv/run-tests.target.mk | 3 + mk/libuv/x86_64/win/src/rt/libuv/uv.target.mk | 1 + src/etc/gyp-uv | 6 +- src/rt/libuv/build/gcc_version.py | 20 + src/rt/libuv/common.gypi | 16 +- src/rt/libuv/config-unix.mk | 1 + src/rt/libuv/include/uv-private/uv-unix.h | 14 + src/rt/libuv/include/uv-private/uv-win.h | 5 + src/rt/libuv/include/uv.h | 384 +++++++++++------- .../libuv/src/ares/config_win32/ares_config.h | 3 - src/rt/libuv/src/unix/core.c | 43 +- src/rt/libuv/src/unix/cygwin.c | 3 +- src/rt/libuv/src/unix/dl.c | 57 +++ src/rt/libuv/src/unix/error.c | 17 +- src/rt/libuv/src/unix/ev/ev_epoll.c | 2 +- src/rt/libuv/src/unix/kqueue.c | 9 +- src/rt/libuv/src/unix/linux.c | 24 +- src/rt/libuv/src/unix/pipe.c | 5 +- src/rt/libuv/src/unix/process.c | 11 + src/rt/libuv/src/unix/stream.c | 37 +- src/rt/libuv/src/unix/sunos.c | 90 +++- src/rt/libuv/src/unix/tcp.c | 5 + src/rt/libuv/src/unix/tty.c | 1 - src/rt/libuv/src/uv-common.c | 21 +- src/rt/libuv/src/uv-common.h | 3 + src/rt/libuv/src/win/core.c | 19 +- src/rt/libuv/src/win/dl.c | 63 +++ src/rt/libuv/src/win/error.c | 9 +- src/rt/libuv/src/win/fs-event.c | 9 +- src/rt/libuv/src/win/fs.c | 11 +- src/rt/libuv/src/win/internal.h | 61 +-- src/rt/libuv/src/win/pipe.c | 24 +- src/rt/libuv/src/win/process.c | 97 +++-- src/rt/libuv/src/win/tcp.c | 252 ++++++++++-- src/rt/libuv/src/win/winsock.h | 4 + src/rt/libuv/test/benchmark-pound.c | 7 +- src/rt/libuv/test/benchmark-pump.c | 3 +- src/rt/libuv/test/run-tests.c | 21 +- src/rt/libuv/test/test-fs-event.c | 39 +- src/rt/libuv/test/test-fs.c | 68 ++++ src/rt/libuv/test/test-ipc.c | 60 ++- src/rt/libuv/test/test-list.h | 24 +- src/rt/libuv/test/test-multiple-listen.c | 102 +++++ src/rt/libuv/test/test-ping-pong.c | 3 +- src/rt/libuv/test/test-pipe-bind-error.c | 2 +- src/rt/libuv/test/test-pipe-connect-error.c | 68 ++++ src/rt/libuv/test/test-spawn.c | 44 +- src/rt/libuv/test/test-stdio-over-pipes.c | 3 + .../test-tcp-write-to-half-open-connection.c | 139 +++++++ src/rt/libuv/uv.gyp | 19 +- 62 files changed, 1619 insertions(+), 355 deletions(-) create mode 100644 src/rt/libuv/build/gcc_version.py create mode 100644 src/rt/libuv/src/unix/dl.c create mode 100644 src/rt/libuv/src/win/dl.c create mode 100644 src/rt/libuv/test/test-multiple-listen.c create mode 100644 src/rt/libuv/test/test-pipe-connect-error.c create mode 100644 src/rt/libuv/test/test-tcp-write-to-half-open-connection.c diff --git a/mk/libuv/ia32/mac/src/rt/libuv/run-tests.target.mk b/mk/libuv/ia32/mac/src/rt/libuv/run-tests.target.mk index f3ef6c3eae3a..6c607bb37868 100644 --- a/mk/libuv/ia32/mac/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/ia32/mac/src/rt/libuv/run-tests.target.mk @@ -50,9 +50,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -64,6 +66,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ diff --git a/mk/libuv/ia32/mac/src/rt/libuv/uv.target.mk b/mk/libuv/ia32/mac/src/rt/libuv/uv.target.mk index 75ade3733e0c..5fe962a4c1c5 100644 --- a/mk/libuv/ia32/mac/src/rt/libuv/uv.target.mk +++ b/mk/libuv/ia32/mac/src/rt/libuv/uv.target.mk @@ -89,6 +89,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/tty.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/stream.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/cares.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/unix/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/process.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/eio/eio.o \ diff --git a/mk/libuv/ia32/unix/src/rt/libuv/run-benchmarks.target.mk b/mk/libuv/ia32/unix/src/rt/libuv/run-benchmarks.target.mk index 68135b0eaba2..e3a114bb50a5 100644 --- a/mk/libuv/ia32/unix/src/rt/libuv/run-benchmarks.target.mk +++ b/mk/libuv/ia32/unix/src/rt/libuv/run-benchmarks.target.mk @@ -8,7 +8,7 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_STACKSIZE=262144' # Flags passed to all source files. -CFLAGS_Default := +CFLAGS_Default := -pthread # Flags passed to only C files. CFLAGS_C_Default := @@ -61,7 +61,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD # End of this set of suffix rules ### Rules for final target. -LDFLAGS_Default := -pthread +LDFLAGS_Default := LIBS := -lrt diff --git a/mk/libuv/ia32/unix/src/rt/libuv/run-tests.target.mk b/mk/libuv/ia32/unix/src/rt/libuv/run-tests.target.mk index de3b45c6f211..4fc85cca20ce 100644 --- a/mk/libuv/ia32/unix/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/ia32/unix/src/rt/libuv/run-tests.target.mk @@ -8,7 +8,7 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_STACKSIZE=262144' # Flags passed to all source files. -CFLAGS_Default := +CFLAGS_Default := -pthread # Flags passed to only C files. CFLAGS_C_Default := @@ -40,9 +40,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -54,6 +56,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ @@ -92,7 +95,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD # End of this set of suffix rules ### Rules for final target. -LDFLAGS_Default := -pthread +LDFLAGS_Default := LIBS := -lrt diff --git a/mk/libuv/ia32/unix/src/rt/libuv/uv.target.mk b/mk/libuv/ia32/unix/src/rt/libuv/uv.target.mk index 4a9b2b5b888d..fa9767329bd0 100644 --- a/mk/libuv/ia32/unix/src/rt/libuv/uv.target.mk +++ b/mk/libuv/ia32/unix/src/rt/libuv/uv.target.mk @@ -11,7 +11,8 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_CONFIG_H="config_linux.h"' # Flags passed to all source files. -CFLAGS_Default := -g \ +CFLAGS_Default := -pthread \ + -g \ --std=gnu89 \ -pedantic \ -Wall \ @@ -84,6 +85,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/tty.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/stream.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/cares.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/unix/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/process.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/eio/eio.o \ diff --git a/mk/libuv/ia32/win/src/rt/libuv/run-tests.target.mk b/mk/libuv/ia32/win/src/rt/libuv/run-tests.target.mk index 860b29f06406..85403f2be506 100644 --- a/mk/libuv/ia32/win/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/ia32/win/src/rt/libuv/run-tests.target.mk @@ -37,9 +37,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -51,6 +53,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ diff --git a/mk/libuv/ia32/win/src/rt/libuv/uv.target.mk b/mk/libuv/ia32/win/src/rt/libuv/uv.target.mk index 17c78fb6ff67..1291a8220432 100644 --- a/mk/libuv/ia32/win/src/rt/libuv/uv.target.mk +++ b/mk/libuv/ia32/win/src/rt/libuv/uv.target.mk @@ -71,6 +71,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/async.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/cares.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/core.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/win/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/fs.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/fs-event.o \ diff --git a/mk/libuv/x86_64/mac/src/rt/libuv/run-tests.target.mk b/mk/libuv/x86_64/mac/src/rt/libuv/run-tests.target.mk index 4222c11b9752..ab3921dd98b3 100644 --- a/mk/libuv/x86_64/mac/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/x86_64/mac/src/rt/libuv/run-tests.target.mk @@ -50,9 +50,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -64,6 +66,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ diff --git a/mk/libuv/x86_64/mac/src/rt/libuv/uv.target.mk b/mk/libuv/x86_64/mac/src/rt/libuv/uv.target.mk index 88ee3f2c9152..a751e1d37e80 100644 --- a/mk/libuv/x86_64/mac/src/rt/libuv/uv.target.mk +++ b/mk/libuv/x86_64/mac/src/rt/libuv/uv.target.mk @@ -89,6 +89,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/tty.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/stream.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/cares.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/unix/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/process.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/eio/eio.o \ diff --git a/mk/libuv/x86_64/unix/src/rt/libuv/run-benchmarks.target.mk b/mk/libuv/x86_64/unix/src/rt/libuv/run-benchmarks.target.mk index 68135b0eaba2..e3a114bb50a5 100644 --- a/mk/libuv/x86_64/unix/src/rt/libuv/run-benchmarks.target.mk +++ b/mk/libuv/x86_64/unix/src/rt/libuv/run-benchmarks.target.mk @@ -8,7 +8,7 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_STACKSIZE=262144' # Flags passed to all source files. -CFLAGS_Default := +CFLAGS_Default := -pthread # Flags passed to only C files. CFLAGS_C_Default := @@ -61,7 +61,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD # End of this set of suffix rules ### Rules for final target. -LDFLAGS_Default := -pthread +LDFLAGS_Default := LIBS := -lrt diff --git a/mk/libuv/x86_64/unix/src/rt/libuv/run-tests.target.mk b/mk/libuv/x86_64/unix/src/rt/libuv/run-tests.target.mk index de3b45c6f211..4fc85cca20ce 100644 --- a/mk/libuv/x86_64/unix/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/x86_64/unix/src/rt/libuv/run-tests.target.mk @@ -8,7 +8,7 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_STACKSIZE=262144' # Flags passed to all source files. -CFLAGS_Default := +CFLAGS_Default := -pthread # Flags passed to only C files. CFLAGS_C_Default := @@ -40,9 +40,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -54,6 +56,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ @@ -92,7 +95,7 @@ $(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.c FORCE_DO_CMD # End of this set of suffix rules ### Rules for final target. -LDFLAGS_Default := -pthread +LDFLAGS_Default := LIBS := -lrt diff --git a/mk/libuv/x86_64/unix/src/rt/libuv/uv.target.mk b/mk/libuv/x86_64/unix/src/rt/libuv/uv.target.mk index 4a9b2b5b888d..fa9767329bd0 100644 --- a/mk/libuv/x86_64/unix/src/rt/libuv/uv.target.mk +++ b/mk/libuv/x86_64/unix/src/rt/libuv/uv.target.mk @@ -11,7 +11,8 @@ DEFS_Default := '-D_LARGEFILE_SOURCE' \ '-DEIO_CONFIG_H="config_linux.h"' # Flags passed to all source files. -CFLAGS_Default := -g \ +CFLAGS_Default := -pthread \ + -g \ --std=gnu89 \ -pedantic \ -Wall \ @@ -84,6 +85,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/tty.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/stream.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/cares.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/unix/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/process.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/unix/eio/eio.o \ diff --git a/mk/libuv/x86_64/win/src/rt/libuv/run-tests.target.mk b/mk/libuv/x86_64/win/src/rt/libuv/run-tests.target.mk index 860b29f06406..85403f2be506 100644 --- a/mk/libuv/x86_64/win/src/rt/libuv/run-tests.target.mk +++ b/mk/libuv/x86_64/win/src/rt/libuv/run-tests.target.mk @@ -37,9 +37,11 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-idle.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ipc.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-loop-handles.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-multiple-listen.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pass-always.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ping-pong.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-bind-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-pipe-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-ref.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-shutdown-eof.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-spawn.o \ @@ -51,6 +53,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/test/blackhole-server.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-connect6-error.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-error.o \ + $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-write-to-half-open-connection.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-tcp-writealot.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-threadpool.o \ $(obj).target/$(TARGET)/src/rt/libuv/test/test-timer-again.o \ diff --git a/mk/libuv/x86_64/win/src/rt/libuv/uv.target.mk b/mk/libuv/x86_64/win/src/rt/libuv/uv.target.mk index 17c78fb6ff67..1291a8220432 100644 --- a/mk/libuv/x86_64/win/src/rt/libuv/uv.target.mk +++ b/mk/libuv/x86_64/win/src/rt/libuv/uv.target.mk @@ -71,6 +71,7 @@ OBJS := $(obj).target/$(TARGET)/src/rt/libuv/src/uv-common.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/async.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/cares.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/core.o \ + $(obj).target/$(TARGET)/src/rt/libuv/src/win/dl.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/error.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/fs.o \ $(obj).target/$(TARGET)/src/rt/libuv/src/win/fs-event.o \ diff --git a/src/etc/gyp-uv b/src/etc/gyp-uv index 5de63976edfe..9224a1d40ec2 100755 --- a/src/etc/gyp-uv +++ b/src/etc/gyp-uv @@ -40,17 +40,17 @@ do # Comment out the gyp auto regeneration for os in mac unix win; do - sed -i "" \ + sed -i \ -e 's/^\(Makefile: $(srcdir)\/src\/rt\/libuv\/uv\.gyp\)/#\1/' \ mk/libuv/$ARCH/$os/Makefile - sed -i "" \ + sed -i \ -e 's/^\( $(call do_cmd,regen_makefile)\)/#\1/' \ mk/libuv/$ARCH/$os/Makefile done done # On Mac, GYP hardcodes a -arch i386 into the output. Fix that. -sed -i "" \ +sed -i \ -e 's/-arch i386/-arch x86_64/' \ mk/libuv/x86_64/mac/src/rt/libuv/*.mk diff --git a/src/rt/libuv/build/gcc_version.py b/src/rt/libuv/build/gcc_version.py new file mode 100644 index 000000000000..da019e866114 --- /dev/null +++ b/src/rt/libuv/build/gcc_version.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python + +import os +import re +import subprocess +import sys + + +def DoMain(*args): + cc = os.environ.get('CC', 'gcc') + stdin, stderr = os.pipe() + subprocess.call([cc, '-v'], stderr=stderr) + output = os.read(stdin, 4096) + match = re.search("\ngcc version (\d+\.\d+\.\d+)", output) + if match: + print(match.group(1)) + + +if __name__ == '__main__': + DoMain(*sys.argv) diff --git a/src/rt/libuv/common.gypi b/src/rt/libuv/common.gypi index 373c3aa98077..e0eb76d267bd 100644 --- a/src/rt/libuv/common.gypi +++ b/src/rt/libuv/common.gypi @@ -114,9 +114,11 @@ ], }], [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { - 'cflags': [ '-Wall', '-pthread', ], + 'variables': { + 'gcc_version%': ')', + }, + 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], - 'ldflags': [ '-pthread', ], 'conditions': [ [ 'host_arch != target_arch and target_arch=="ia32"', { 'cflags': [ '-m32' ], @@ -125,7 +127,14 @@ [ 'OS=="linux"', { 'cflags': [ '-ansi' ], }], - [ 'visibility=="hidden"', { + [ 'OS=="solaris"', { + 'cflags': [ '-pthreads' ], + 'ldflags': [ '-pthreads' ], + }, { + 'cflags': [ '-pthread' ], + 'ldflags': [ '-pthread' ], + }], + [ 'visibility=="hidden" and gcc_version >= "4.0.0"', { 'cflags': [ '-fvisibility=hidden' ], }], ], @@ -143,7 +152,6 @@ 'GCC_INLINES_ARE_PRIVATE_EXTERN': 'YES', 'GCC_SYMBOLS_PRIVATE_EXTERN': 'YES', # -fvisibility=hidden 'GCC_THREADSAFE_STATICS': 'NO', # -fno-threadsafe-statics - 'GCC_VERSION': '4.2', 'GCC_WARN_ABOUT_MISSING_NEWLINE': 'YES', # -Wnewline-eof 'MACOSX_DEPLOYMENT_TARGET': '10.4', # -mmacosx-version-min=10.4 'PREBINDING': 'NO', # No -Wl,-prebind diff --git a/src/rt/libuv/config-unix.mk b/src/rt/libuv/config-unix.mk index 53bcbd4c9848..9524061b1c50 100644 --- a/src/rt/libuv/config-unix.mk +++ b/src/rt/libuv/config-unix.mk @@ -28,6 +28,7 @@ CPPFLAGS += -D_LARGEFILE_SOURCE CPPFLAGS += -D_FILE_OFFSET_BITS=64 OBJS += src/unix/core.o +OBJS += src/unix/dl.o OBJS += src/unix/fs.o OBJS += src/unix/cares.o OBJS += src/unix/udp.o diff --git a/src/rt/libuv/include/uv-private/uv-unix.h b/src/rt/libuv/include/uv-private/uv-unix.h index 0db14e9c7f06..b07781f4068b 100644 --- a/src/rt/libuv/include/uv-private/uv-unix.h +++ b/src/rt/libuv/include/uv-private/uv-unix.h @@ -43,6 +43,10 @@ typedef struct { typedef int uv_file; +/* Platform-specific definitions for uv_dlopen support. */ +typedef void* uv_lib_t; +#define UV_DYNAMIC /* empty */ + #define UV_LOOP_PRIVATE_FIELDS \ ares_channel channel; \ /* \ @@ -195,6 +199,16 @@ typedef int uv_file; uv_fs_event_cb cb; \ int fflags; \ +#elif defined(__sun) + +#include +#include + +#define UV_FS_EVENT_PRIVATE_FIELDS \ + ev_io event_watcher; \ + uv_fs_event_cb cb; \ + file_obj_t fo; \ + #else /* Stub for platforms where the file watcher isn't implemented yet. */ diff --git a/src/rt/libuv/include/uv-private/uv-win.h b/src/rt/libuv/include/uv-private/uv-win.h index ed132d3ad4f6..5d461090f159 100644 --- a/src/rt/libuv/include/uv-private/uv-win.h +++ b/src/rt/libuv/include/uv-private/uv-win.h @@ -137,6 +137,10 @@ typedef struct uv_buf_t { typedef int uv_file; +/* Platform-specific definitions for uv_dlopen support. */ +typedef HMODULE uv_lib_t; +#define UV_DYNAMIC FAR WINAPI + RB_HEAD(uv_timer_tree_s, uv_timer_s); #define UV_LOOP_PRIVATE_FIELDS \ @@ -243,6 +247,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); #define uv_tcp_server_fields \ uv_tcp_accept_t* accept_reqs; \ + unsigned int processed_accepts; \ uv_tcp_accept_t* pending_accepts; \ LPFN_ACCEPTEX func_acceptex; diff --git a/src/rt/libuv/include/uv.h b/src/rt/libuv/include/uv.h index 7bee299185ab..88afed448d9a 100644 --- a/src/rt/libuv/include/uv.h +++ b/src/rt/libuv/include/uv.h @@ -27,10 +27,29 @@ extern "C" { #endif +#ifdef _WIN32 + /* Windows - set up dll import/export decorators. */ +# if defined(BUILDING_UV_SHARED) + /* Building shared library. Export everything from c-ares as well. */ +# define UV_EXTERN __declspec(dllexport) +# define CARES_BUILDING_LIBRARY 1 +# elif defined(USING_UV_SHARED) + /* Using shared library. Use shared c-ares as well. */ +# define UV_EXTERN __declspec(dllimport) +# else + /* Building static library. Build c-ares statically as well. */ +# define UV_EXTERN /* nothing */ +# define CARES_STATICLIB 1 +# endif +#else + /* Unix. TODO: symbol hiding */ +# define UV_EXTERN /* nothing */ +#endif + + #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 1 -#define CARES_STATICLIB 1 #include /* int64_t */ #include /* size_t */ @@ -52,7 +71,8 @@ typedef enum { UV_UNKNOWN = -1, UV_OK = 0, UV_EOF, - UV_EACCESS, + UV_EADDRINFO, + UV_EACCES, UV_EAGAIN, UV_EADDRINUSE, UV_EADDRNOTAVAIL, @@ -77,6 +97,7 @@ typedef enum { UV_ENOBUFS, UV_ENOMEM, UV_ENOTDIR, + UV_EISDIR, UV_ENONET, UV_ENOPROTOOPT, UV_ENOTCONN, @@ -170,30 +191,30 @@ typedef struct uv_work_s uv_work_t; * All callbacks in libuv are made asynchronously. That is they are never * made by the function that takes them as a parameter. */ -uv_loop_t* uv_loop_new(); -void uv_loop_delete(uv_loop_t*); +UV_EXTERN uv_loop_t* uv_loop_new(void); +UV_EXTERN void uv_loop_delete(uv_loop_t*); /* * Returns the default loop. */ -uv_loop_t* uv_default_loop(); +UV_EXTERN uv_loop_t* uv_default_loop(void); /* * This function starts the event loop. It blocks until the reference count * of the loop drops to zero. */ -int uv_run(uv_loop_t*); +UV_EXTERN int uv_run (uv_loop_t*); /* * Manually modify the event loop's reference count. Useful if the user wants * to have a handle or timeout that doesn't keep the loop alive. */ -void uv_ref(uv_loop_t*); -void uv_unref(uv_loop_t*); +UV_EXTERN void uv_ref(uv_loop_t*); +UV_EXTERN void uv_unref(uv_loop_t*); -void uv_update_time(uv_loop_t*); -int64_t uv_now(uv_loop_t*); +UV_EXTERN void uv_update_time(uv_loop_t*); +UV_EXTERN int64_t uv_now(uv_loop_t*); /* @@ -260,9 +281,9 @@ struct uv_err_s { * On error the user should then call uv_last_error() to determine * the error code. */ -uv_err_t uv_last_error(uv_loop_t*); -char* uv_strerror(uv_err_t err); -const char* uv_err_name(uv_err_t err); +UV_EXTERN uv_err_t uv_last_error(uv_loop_t*); +UV_EXTERN const char* uv_strerror(uv_err_t err); +UV_EXTERN const char* uv_err_name(uv_err_t err); #define UV_REQ_FIELDS \ @@ -291,7 +312,8 @@ UV_PRIVATE_REQ_TYPES * initialized stream. req should be an uninitalized shutdown request * struct. The cb is a called after shutdown is complete. */ -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 @@ -320,7 +342,7 @@ struct uv_handle_s { * Returns 1 if the prepare/check/idle handle has been started, 0 otherwise. * For other handle types this always returns 1. */ -int uv_is_active(uv_handle_t* handle); +UV_EXTERN int uv_is_active(uv_handle_t* handle); /* * Request handle to be closed. close_cb will be called asynchronously after @@ -330,7 +352,7 @@ int uv_is_active(uv_handle_t* handle); * close_cb will still be deferred to the next iteration of the event loop. * It gives you a chance to free up any resources associated with the handle. */ -void uv_close(uv_handle_t* handle, uv_close_cb close_cb); +UV_EXTERN void uv_close(uv_handle_t* handle, uv_close_cb close_cb); /* @@ -339,7 +361,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb); * base and len members of the uv_buf_t struct. The user is responsible for * freeing base after the uv_buf_t is done. Return struct passed by value. */ -uv_buf_t uv_buf_init(char* base, size_t len); +UV_EXTERN uv_buf_t uv_buf_init(char* base, size_t len); #define UV_STREAM_FIELDS \ @@ -364,7 +386,7 @@ struct uv_stream_s { UV_STREAM_FIELDS }; -int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); +UV_EXTERN int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); /* * This call is used in conjunction with uv_listen() to accept incoming @@ -377,7 +399,7 @@ int uv_listen(uv_stream_t* stream, int backlog, uv_connection_cb cb); * once, it may fail. It is suggested to only call uv_accept once per * uv_connection_cb call. */ -int uv_accept(uv_stream_t* server, uv_stream_t* client); +UV_EXTERN int uv_accept(uv_stream_t* server, uv_stream_t* client); /* * Read data from an incoming stream. The callback will be made several @@ -389,15 +411,17 @@ 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. */ -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); -int uv_read_stop(uv_stream_t*); +UV_EXTERN int uv_read_stop(uv_stream_t*); /* * Extended read methods for receiving handles over a pipe. The pipe must be * initialized with ipc == 1. */ -int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb); +UV_EXTERN int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, + uv_read2_cb read_cb); /* @@ -418,11 +442,11 @@ int uv_read2_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read2_cb read_cb); * uv_write(req, stream, b, 2); * */ -int uv_write(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, - uv_write_cb cb); +UV_EXTERN int uv_write(uv_write_t* req, uv_stream_t* handle, + uv_buf_t bufs[], int bufcnt, uv_write_cb cb); -int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], int bufcnt, - uv_stream_t* send_handle, uv_write_cb cb); +UV_EXTERN int uv_write2(uv_write_t* req, uv_stream_t* handle, uv_buf_t bufs[], + int bufcnt, uv_stream_t* send_handle, uv_write_cb cb); /* uv_write_t is a subclass of uv_req_t */ struct uv_write_s { @@ -446,21 +470,34 @@ struct uv_tcp_s { UV_TCP_PRIVATE_FIELDS }; -int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); +UV_EXTERN int uv_tcp_init(uv_loop_t*, uv_tcp_t* handle); /* Enable/disable Nagle's algorithm. */ -int uv_tcp_nodelay(uv_tcp_t* handle, int enable); +UV_EXTERN int uv_tcp_nodelay(uv_tcp_t* handle, int enable); /* Enable/disable TCP keep-alive. * * `ms` is the initial delay in seconds, ignored when `enable` is zero. */ -int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay); +UV_EXTERN int uv_tcp_keepalive(uv_tcp_t* handle, int enable, + unsigned int delay); -int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in); -int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6); -int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, int* namelen); -int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen); +/* + * This setting applies to Windows only. + * Enable/disable simultaneous asynchronous accept requests that are + * queued by the operating system when listening for new tcp connections. + * This setting is used to tune a tcp server for the desired performance. + * Having simultaneous accepts can significantly improve the rate of + * accepting connections (which is why it is enabled by default). + */ +UV_EXTERN int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable); + +UV_EXTERN int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in); +UV_EXTERN int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6); +UV_EXTERN int uv_tcp_getsockname(uv_tcp_t* handle, struct sockaddr* name, + int* namelen); +UV_EXTERN int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, + int* namelen); /* * uv_tcp_connect, uv_tcp_connect6 @@ -468,9 +505,9 @@ int uv_tcp_getpeername(uv_tcp_t* handle, struct sockaddr* name, int* namelen); * initialized TCP handle and an uninitialized uv_connect_t*. The callback * will be made when the connection is estabished. */ -int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, +UV_EXTERN int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in address, uv_connect_cb cb); -int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, +UV_EXTERN int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, uv_connect_cb cb); /* uv_connect_t is a subclass of uv_req_t */ @@ -537,7 +574,7 @@ struct uv_udp_send_s { * Initialize a new UDP handle. The actual socket is created lazily. * Returns 0 on success. */ -int uv_udp_init(uv_loop_t*, uv_udp_t* handle); +UV_EXTERN int uv_udp_init(uv_loop_t*, uv_udp_t* handle); /* * Bind to a IPv4 address and port. @@ -550,7 +587,8 @@ int uv_udp_init(uv_loop_t*, uv_udp_t* handle); * Returns: * 0 on success, -1 on error. */ -int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags); +UV_EXTERN int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, + unsigned flags); /* * Bind to a IPv6 address and port. @@ -563,14 +601,17 @@ int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, unsigned flags); * Returns: * 0 on success, -1 on error. */ -int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned flags); -int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen); +UV_EXTERN int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, + unsigned flags); +UV_EXTERN int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, + int* namelen); /* * Set membership for a multicast address * * Arguments: - * handle UDP handle. Should have been initialized with `uv_udp_init`. + * handle UDP handle. Should have been initialized with + * `uv_udp_init`. * multicast_addr multicast address to set membership for * interface_addr interface address * membership Should be UV_JOIN_GROUP or UV_LEAVE_GROUP @@ -578,8 +619,9 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, int* namelen); * Returns: * 0 on success, -1 on error. */ -int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, - const char* interface_addr, uv_membership membership); +UV_EXTERN int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, const char* interface_addr, + uv_membership membership); /* * Send data. If the socket has not previously been bound with `uv_udp_bind` @@ -597,8 +639,9 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, * Returns: * 0 on success, -1 on error. */ -int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], - int bufcnt, struct sockaddr_in addr, uv_udp_send_cb send_cb); +UV_EXTERN int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, + uv_buf_t bufs[], int bufcnt, struct sockaddr_in addr, + uv_udp_send_cb send_cb); /* * Send data. If the socket has not previously been bound with `uv_udp_bind6`, @@ -615,8 +658,9 @@ int uv_udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], * Returns: * 0 on success, -1 on error. */ -int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], - int bufcnt, struct sockaddr_in6 addr, uv_udp_send_cb send_cb); +UV_EXTERN int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, + uv_buf_t bufs[], int bufcnt, struct sockaddr_in6 addr, + uv_udp_send_cb send_cb); /* * Receive data. If the socket has not previously been bound with `uv_udp_bind` @@ -631,7 +675,7 @@ int uv_udp_send6(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], * Returns: * 0 on success, -1 on error. */ -int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, +UV_EXTERN int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, uv_udp_recv_cb recv_cb); /* @@ -643,7 +687,7 @@ int uv_udp_recv_start(uv_udp_t* handle, uv_alloc_cb alloc_cb, * Returns: * 0 on success, -1 on error. */ -int uv_udp_recv_stop(uv_udp_t* handle); +UV_EXTERN int uv_udp_recv_stop(uv_udp_t* handle); /* @@ -668,23 +712,23 @@ struct uv_tty_s { * * TTY streams which are not readable have blocking writes. */ -int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); +UV_EXTERN int uv_tty_init(uv_loop_t*, uv_tty_t*, uv_file fd, int readable); /* * Set mode. 0 for normal, 1 for raw. */ -int uv_tty_set_mode(uv_tty_t*, int mode); +UV_EXTERN int uv_tty_set_mode(uv_tty_t*, int mode); /* * To be called when the program exits. Resets TTY settings to default * values for the next process to take over. */ -void uv_tty_reset_mode(); +UV_EXTERN void uv_tty_reset_mode(); /* * Gets the current Window size. On success zero is returned. */ -int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); +UV_EXTERN int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); /* * Used to detect what type of stream should be used with a given file @@ -692,7 +736,7 @@ int uv_tty_get_winsize(uv_tty_t*, int* width, int* height); * type of the stdio streams. * For isatty() functionality use this function and test for UV_TTY. */ -uv_handle_type uv_guess_handle(uv_file file); +UV_EXTERN uv_handle_type uv_guess_handle(uv_file file); /* * uv_pipe_t is a subclass of uv_stream_t @@ -711,16 +755,16 @@ struct uv_pipe_s { * Initialize a pipe. The last argument is a boolean to indicate if * this pipe will be used for handle passing between processes. */ -int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); +UV_EXTERN int uv_pipe_init(uv_loop_t*, uv_pipe_t* handle, int ipc); /* * Opens an existing file descriptor or HANDLE as a pipe. */ -void uv_pipe_open(uv_pipe_t*, uv_file file); +UV_EXTERN void uv_pipe_open(uv_pipe_t*, uv_file file); -int uv_pipe_bind(uv_pipe_t* handle, const char* name); +UV_EXTERN int uv_pipe_bind(uv_pipe_t* handle, const char* name); -int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, +UV_EXTERN void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb); @@ -736,11 +780,11 @@ struct uv_prepare_s { UV_PREPARE_PRIVATE_FIELDS }; -int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); +UV_EXTERN int uv_prepare_init(uv_loop_t*, uv_prepare_t* prepare); -int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); +UV_EXTERN int uv_prepare_start(uv_prepare_t* prepare, uv_prepare_cb cb); -int uv_prepare_stop(uv_prepare_t* prepare); +UV_EXTERN int uv_prepare_stop(uv_prepare_t* prepare); /* @@ -754,11 +798,11 @@ struct uv_check_s { UV_CHECK_PRIVATE_FIELDS }; -int uv_check_init(uv_loop_t*, uv_check_t* check); +UV_EXTERN int uv_check_init(uv_loop_t*, uv_check_t* check); -int uv_check_start(uv_check_t* check, uv_check_cb cb); +UV_EXTERN int uv_check_start(uv_check_t* check, uv_check_cb cb); -int uv_check_stop(uv_check_t* check); +UV_EXTERN int uv_check_stop(uv_check_t* check); /* @@ -774,11 +818,11 @@ struct uv_idle_s { UV_IDLE_PRIVATE_FIELDS }; -int uv_idle_init(uv_loop_t*, uv_idle_t* idle); +UV_EXTERN int uv_idle_init(uv_loop_t*, uv_idle_t* idle); -int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); +UV_EXTERN int uv_idle_start(uv_idle_t* idle, uv_idle_cb cb); -int uv_idle_stop(uv_idle_t* idle); +UV_EXTERN int uv_idle_stop(uv_idle_t* idle); /* @@ -796,14 +840,15 @@ struct uv_async_s { UV_ASYNC_PRIVATE_FIELDS }; -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. */ -int uv_async_send(uv_async_t* async); +UV_EXTERN int uv_async_send(uv_async_t* async); /* @@ -817,19 +862,19 @@ struct uv_timer_s { UV_TIMER_PRIVATE_FIELDS }; -int uv_timer_init(uv_loop_t*, uv_timer_t* timer); +UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* timer); -int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, int64_t timeout, - int64_t repeat); +UV_EXTERN int uv_timer_start(uv_timer_t* timer, uv_timer_cb cb, + int64_t timeout, int64_t repeat); -int uv_timer_stop(uv_timer_t* timer); +UV_EXTERN int uv_timer_stop(uv_timer_t* timer); /* * Stop the timer, and if it is repeating restart it using the repeat value * as the timeout. If the timer has never been started before it returns -1 and * sets the error to UV_EINVAL. */ -int uv_timer_again(uv_timer_t* timer); +UV_EXTERN int uv_timer_again(uv_timer_t* timer); /* * Set the repeat value. Note that if the repeat value is set from a timer @@ -837,19 +882,17 @@ int uv_timer_again(uv_timer_t* timer); * before, it will have been stopped. If it was repeating, then the old repeat * value will have been used to schedule the next timeout. */ -void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat); +UV_EXTERN void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat); -int64_t uv_timer_get_repeat(uv_timer_t* timer); +UV_EXTERN int64_t uv_timer_get_repeat(uv_timer_t* timer); /* c-ares integration initialize and terminate */ -int uv_ares_init_options(uv_loop_t*, - ares_channel *channelptr, - struct ares_options *options, - int optmask); +UV_EXTERN int uv_ares_init_options(uv_loop_t*, + ares_channel *channelptr, struct ares_options *options, int optmask); /* TODO remove the loop argument from this function? */ -void uv_ares_destroy(uv_loop_t*, ares_channel channel); +UV_EXTERN void uv_ares_destroy(uv_loop_t*, ares_channel channel); /* @@ -877,14 +920,11 @@ struct uv_getaddrinfo_s { * * On error NXDOMAIN the status code will be non-zero and UV_ENOENT returned. */ - int uv_getaddrinfo(uv_loop_t*, - uv_getaddrinfo_t* handle, - uv_getaddrinfo_cb getaddrinfo_cb, - const char* node, - const char* service, - const struct addrinfo* hints); +UV_EXTERN int uv_getaddrinfo(uv_loop_t*, uv_getaddrinfo_t* handle, + uv_getaddrinfo_cb getaddrinfo_cb, const char* node, const char* service, + const struct addrinfo* hints); -void uv_freeaddrinfo(struct addrinfo* ai); +UV_EXTERN void uv_freeaddrinfo(struct addrinfo* ai); /* uv_spawn() options */ typedef struct uv_process_options_s { @@ -934,13 +974,18 @@ struct uv_process_s { }; /* Initializes uv_process_t and starts the process. */ -int uv_spawn(uv_loop_t*, uv_process_t*, uv_process_options_t options); +UV_EXTERN int uv_spawn(uv_loop_t*, uv_process_t*, + uv_process_options_t options); /* * Kills the process with the specified signal. The user must still * call uv_close on the process. */ -int uv_process_kill(uv_process_t*, int signum); +UV_EXTERN int uv_process_kill(uv_process_t*, int signum); + + +/* Kills the process with the specified signal. */ +UV_EXTERN uv_err_t uv_kill(int pid, int signum); /* @@ -955,8 +1000,8 @@ struct uv_work_s { }; /* Queues a work request to execute asynchronously on the thread pool. */ -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); @@ -1018,58 +1063,66 @@ struct uv_fs_s { UV_FS_PRIVATE_FIELDS }; -void uv_fs_req_cleanup(uv_fs_t* req); +UV_EXTERN void uv_fs_req_cleanup(uv_fs_t* req); -int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); +UV_EXTERN int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, +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, off_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, + void* buf, size_t length, off_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); -int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb); - -int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); - -int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, void* buf, - size_t length, off_t offset, uv_fs_cb cb); - -int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, +UV_EXTERN int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, + const char* path, int flags, uv_fs_cb cb); -int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, +UV_EXTERN int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); - -int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); -int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); - -int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); - -int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, - off_t offset, uv_fs_cb cb); - -int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, - uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb); - -int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, +UV_EXTERN int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); -int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, - double mtime, uv_fs_cb cb); +UV_EXTERN int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, + uv_fs_cb cb); -int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, - double mtime, uv_fs_cb cb); +UV_EXTERN int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, + off_t offset, uv_fs_cb cb); -int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); +UV_EXTERN int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, + uv_file in_fd, off_t in_offset, size_t length, uv_fs_cb cb); -int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, + int mode, uv_fs_cb cb); + +UV_EXTERN int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, + double atime, double mtime, uv_fs_cb cb); + +UV_EXTERN int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, + double atime, double mtime, uv_fs_cb cb); + +UV_EXTERN int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, + uv_fs_cb cb); + +UV_EXTERN int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); /* @@ -1078,20 +1131,20 @@ int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, */ #define UV_FS_SYMLINK_DIR 0x0001 -int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); -int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, +UV_EXTERN int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); -int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, - uv_fs_cb cb); +UV_EXTERN int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, + int mode, uv_fs_cb cb); -int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, int uid, - int gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, + int uid, int gid, uv_fs_cb cb); -int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, int uid, - int gid, uv_fs_cb cb); +UV_EXTERN int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, + int uid, int gid, uv_fs_cb cb); enum uv_fs_event { @@ -1112,32 +1165,52 @@ struct uv_fs_event_s { * See: http://en.wikipedia.org/wiki/Load_(computing) * (Returns [0,0,0] for windows and cygwin) */ -void uv_loadavg(double avg[3]); +UV_EXTERN void uv_loadavg(double avg[3]); + /* -* If filename is a directory then we will watch for all events in that -* directory. If filename is a file - we will only get events from that -* file. Subdirectories are not watched. -*/ -int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, - const char* filename, uv_fs_event_cb cb); + * Flags to be passed to uv_fs_event_init. + */ +enum uv_fs_event_flags { + /* + * By default, if the fs event watcher is given a directory name, we will + * watch for all events in that directory. This flags overrides this behavior + * and makes fs_event report only changes to the directory entry itself. This + * flag does not affect individual files watched. + * This flag is currently not implemented yet on any backend. + */ + UV_FS_EVENT_WATCH_ENTRY = 1, + + /* + * By default uv_fs_event will try to use a kernel interface such as inotify + * or kqueue to detect events. This may not work on remote filesystems such + * as NFS mounts. This flag makes fs_event fall back to calling stat() on a + * regular interval. + * This flag is currently not implemented yet on any backend. + */ + UV_FS_EVENT_STAT = 2 +}; + + +UV_EXTERN int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, + const char* filename, uv_fs_event_cb cb, int flags); /* Utility */ /* Convert string ip addresses to binary structures */ -struct sockaddr_in uv_ip4_addr(const char* ip, int port); -struct sockaddr_in6 uv_ip6_addr(const char* ip, int port); +UV_EXTERN struct sockaddr_in uv_ip4_addr(const char* ip, int port); +UV_EXTERN struct sockaddr_in6 uv_ip6_addr(const char* ip, int port); /* Convert binary addresses to strings */ -int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size); -int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size); +UV_EXTERN int uv_ip4_name(struct sockaddr_in* src, char* dst, size_t size); +UV_EXTERN int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size); /* Gets the executable path */ -int uv_exepath(char* buffer, size_t* size); +UV_EXTERN int uv_exepath(char* buffer, size_t* size); /* Gets memory info in bytes */ -uint64_t uv_get_free_memory(void); -uint64_t uv_get_total_memory(void); +UV_EXTERN uint64_t uv_get_free_memory(void); +UV_EXTERN uint64_t uv_get_total_memory(void); /* * Returns the current high-resolution real time. This is expressed in @@ -1148,7 +1221,20 @@ uint64_t uv_get_total_memory(void); * Note not every platform can support nanosecond resolution; however, this * value will always be in nanoseconds. */ -extern uint64_t uv_hrtime(void); +UV_EXTERN extern uint64_t uv_hrtime(void); + + +/* + * Opens a shared library. The filename is in utf-8. On success, -1 is + * and the variable pointed by library receives a handle to the library. + */ +UV_EXTERN uv_err_t uv_dlopen(const char* filename, uv_lib_t* library); +UV_EXTERN uv_err_t uv_dlclose(uv_lib_t library); + +/* + * Retrieves a data pointer from a dynamic library. + */ +UV_EXTERN uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr); /* the presence of these unions force similar struct layout */ diff --git a/src/rt/libuv/src/ares/config_win32/ares_config.h b/src/rt/libuv/src/ares/config_win32/ares_config.h index 4c9c9f6786a0..6ded638093f8 100644 --- a/src/rt/libuv/src/ares/config_win32/ares_config.h +++ b/src/rt/libuv/src/ares/config_win32/ares_config.h @@ -4,9 +4,6 @@ /* when building c-ares library */ #define CARES_BUILDING_LIBRARY 1 -/* when not building a shared library */ -#define CARES_STATICLIB 1 - /* Copyright (C) 2004 - 2008 by Daniel Stenberg et al * * Permission to use, copy, modify, and distribute this software and its diff --git a/src/rt/libuv/src/unix/core.c b/src/rt/libuv/src/unix/core.c index 27e949e90b28..19d5b9150186 100644 --- a/src/rt/libuv/src/unix/core.c +++ b/src/rt/libuv/src/unix/core.c @@ -38,18 +38,22 @@ #include /* PATH_MAX */ #include /* writev */ +#ifdef __linux__ +# include +#endif + #ifdef __sun # include # include #endif -#if defined(__APPLE__) -#include /* _NSGetExecutablePath */ +#ifdef __APPLE__ +# include /* _NSGetExecutablePath */ #endif -#if defined(__FreeBSD__) -#include -#include +#ifdef __FreeBSD__ +# include +# include #endif static uv_loop_t default_loop_struct; @@ -154,7 +158,7 @@ void uv_close(uv_handle_t* handle, uv_close_cb close_cb) { } -uv_loop_t* uv_loop_new() { +uv_loop_t* uv_loop_new(void) { uv_loop_t* loop = calloc(1, sizeof(uv_loop_t)); loop->ev = ev_loop_new(0); ev_set_userdata(loop->ev, loop); @@ -169,7 +173,7 @@ void uv_loop_delete(uv_loop_t* loop) { } -uv_loop_t* uv_default_loop() { +uv_loop_t* uv_default_loop(void) { if (!default_loop_ptr) { default_loop_ptr = &default_loop_struct; #if HAVE_KQUEUE @@ -593,9 +597,17 @@ static int uv_getaddrinfo_done(eio_req* req) { free(handle->service); free(handle->hostname); - if (handle->retcode != 0) { - /* TODO how to display gai error strings? */ - uv__set_sys_error(handle->loop, handle->retcode); + if (handle->retcode == 0) { + /* OK */ +#if EAI_NODATA /* FreeBSD deprecated EAI_NODATA */ + } else if (handle->retcode == EAI_NONAME || handle->retcode == EAI_NODATA) { +#else + } else if (handle->retcode == EAI_NONAME) { +#endif + uv__set_sys_error(handle->loop, ENOENT); /* FIXME compatibility hack */ + } else { + handle->loop->last_err.code = UV_EADDRINFO; + handle->loop->last_err.sys_errno_ = handle->retcode; } handle->cb(handle, handle->retcode, res); @@ -734,6 +746,9 @@ int uv__close(int fd) { int uv__nonblock(int fd, int set) { +#if FIONBIO + return ioctl(fd, FIONBIO, &set); +#else int flags; if ((flags = fcntl(fd, F_GETFL)) == -1) { @@ -751,10 +766,17 @@ int uv__nonblock(int fd, int set) { } return 0; +#endif } int uv__cloexec(int fd, int set) { +#if __linux__ + /* Linux knows only FD_CLOEXEC so we can safely omit the fcntl(F_GETFD) + * syscall. CHECKME: That's probably true for other Unices as well. + */ + return fcntl(fd, F_SETFD, set ? FD_CLOEXEC : 0); +#else int flags; if ((flags = fcntl(fd, F_GETFD)) == -1) { @@ -772,6 +794,7 @@ int uv__cloexec(int fd, int set) { } return 0; +#endif } diff --git a/src/rt/libuv/src/unix/cygwin.c b/src/rt/libuv/src/unix/cygwin.c index 2f0680a4b76a..024e7d5bf9bc 100644 --- a/src/rt/libuv/src/unix/cygwin.c +++ b/src/rt/libuv/src/unix/cygwin.c @@ -69,7 +69,8 @@ uint64_t uv_get_total_memory(void) { int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, - uv_fs_event_cb cb) { + uv_fs_event_cb cb, + int flags) { uv__set_sys_error(loop, ENOSYS); return -1; } diff --git a/src/rt/libuv/src/unix/dl.c b/src/rt/libuv/src/unix/dl.c new file mode 100644 index 000000000000..6c4ddff89e6a --- /dev/null +++ b/src/rt/libuv/src/unix/dl.c @@ -0,0 +1,57 @@ +/* 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 "internal.h" + +#include +#include + + +uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { + void* handle = dlopen(filename, RTLD_LAZY); + if (handle == NULL) { + return uv__new_sys_error(errno); + } + + *library = handle; + return uv_ok_; +} + + +uv_err_t uv_dlclose(uv_lib_t library) { + if (dlclose(library) != 0) { + return uv__new_sys_error(errno); + } + + return uv_ok_; +} + + +uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) { + void* address = dlsym(library, name); + if (address == NULL) { + return uv__new_sys_error(errno); + } + + *ptr = (void*) address; + return uv_ok_; +} diff --git a/src/rt/libuv/src/unix/error.c b/src/rt/libuv/src/unix/error.c index 374e6eb29b04..ac8bdd72cc8c 100644 --- a/src/rt/libuv/src/unix/error.c +++ b/src/rt/libuv/src/unix/error.c @@ -59,8 +59,10 @@ void uv_fatal_error(const int errorno, const char* syscall) { static int uv__translate_lib_error(int code) { switch (code) { case UV_ENOSYS: return ENOSYS; + case UV_ENOTSOCK: return ENOTSOCK; case UV_ENOENT: return ENOENT; - case UV_EACCESS: return EACCES; + case UV_EACCES: return EACCES; + case UV_EAFNOSUPPORT: return EAFNOSUPPORT; case UV_EBADF: return EBADF; case UV_EPIPE: return EPIPE; case UV_EAGAIN: return EAGAIN; @@ -73,8 +75,10 @@ static int uv__translate_lib_error(int code) { case UV_EADDRINUSE: return EADDRINUSE; case UV_EADDRNOTAVAIL: return EADDRNOTAVAIL; case UV_ENOTDIR: return ENOTDIR; + case UV_EISDIR: return EISDIR; case UV_ENOTCONN: return ENOTCONN; case UV_EEXIST: return EEXIST; + case UV_EHOSTUNREACH: return EHOSTUNREACH; default: return -1; } @@ -87,8 +91,10 @@ uv_err_code uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case 0: return UV_OK; case ENOSYS: return UV_ENOSYS; + case ENOTSOCK: return UV_ENOTSOCK; case ENOENT: return UV_ENOENT; - case EACCES: return UV_EACCESS; + case EACCES: return UV_EACCES; + case EAFNOSUPPORT: return UV_EAFNOSUPPORT; case EBADF: return UV_EBADF; case EPIPE: return UV_EPIPE; case EAGAIN: return UV_EAGAIN; @@ -101,8 +107,10 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case EADDRINUSE: return UV_EADDRINUSE; case EADDRNOTAVAIL: return UV_EADDRNOTAVAIL; case ENOTDIR: return UV_ENOTDIR; + case EISDIR: return UV_EISDIR; case ENOTCONN: return UV_ENOTCONN; case EEXIST: return UV_EEXIST; + case EHOSTUNREACH: return UV_EHOSTUNREACH; case EAI_NONAME: return UV_ENOENT; default: return UV_UNKNOWN; } @@ -116,7 +124,7 @@ uv_err_code uv_translate_sys_error(int sys_errno) { * a) rely on what the system provides us * b) reverse-map the error codes */ -char* uv_strerror(uv_err_t err) { +const char* uv_strerror(uv_err_t err) { int errorno; if (err.sys_errno_) @@ -124,6 +132,9 @@ char* uv_strerror(uv_err_t err) { else errorno = uv__translate_lib_error(err.code); + if (err.code == UV_EADDRINFO) + return gai_strerror(errorno); + if (errorno == -1) return "Unknown error"; else diff --git a/src/rt/libuv/src/unix/ev/ev_epoll.c b/src/rt/libuv/src/unix/ev/ev_epoll.c index 5deb65211181..e8101e562f1f 100644 --- a/src/rt/libuv/src/unix/ev/ev_epoll.c +++ b/src/rt/libuv/src/unix/ev/ev_epoll.c @@ -225,7 +225,7 @@ epoll_init (EV_P_ int flags) #ifdef EPOLL_CLOEXEC backend_fd = epoll_create1 (EPOLL_CLOEXEC); - if (backend_fd <= 0) + if (backend_fd < 0) #endif backend_fd = epoll_create (256); diff --git a/src/rt/libuv/src/unix/kqueue.c b/src/rt/libuv/src/unix/kqueue.c index c2cb7194aab5..00180cd41d36 100644 --- a/src/rt/libuv/src/unix/kqueue.c +++ b/src/rt/libuv/src/unix/kqueue.c @@ -86,9 +86,13 @@ void uv__kqueue_hack(EV_P_ int fflags, ev_io *w) { int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, - uv_fs_event_cb cb) { + uv_fs_event_cb cb, + int flags) { int fd; + /* We don't support any flags yet. */ + assert(!flags); + if (cb == NULL) { uv__set_sys_error(loop, EINVAL); return -1; @@ -122,7 +126,8 @@ void uv__fs_event_destroy(uv_fs_event_t* handle) { int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, - uv_fs_event_cb cb) { + uv_fs_event_cb cb, + int flags) { uv__set_sys_error(loop, ENOSYS); return -1; } diff --git a/src/rt/libuv/src/unix/linux.c b/src/rt/libuv/src/unix/linux.c index e7ca1840f200..f91839f7f920 100644 --- a/src/rt/libuv/src/unix/linux.c +++ b/src/rt/libuv/src/unix/linux.c @@ -156,10 +156,14 @@ static void uv__inotify_read(EV_P_ ev_io* w, int revents) { int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, - uv_fs_event_cb cb) { - int flags; + uv_fs_event_cb cb, + int flags) { + int events; int fd; + /* We don't support any flags yet. */ + assert(!flags); + /* * TODO share a single inotify fd across the event loop? * We'll run into fs.inotify.max_user_instances if we @@ -170,15 +174,15 @@ int uv_fs_event_init(uv_loop_t* loop, return -1; } - flags = IN_ATTRIB - | IN_CREATE - | IN_MODIFY - | IN_DELETE - | IN_DELETE_SELF - | IN_MOVED_FROM - | IN_MOVED_TO; + events = IN_ATTRIB + | IN_CREATE + | IN_MODIFY + | IN_DELETE + | IN_DELETE_SELF + | IN_MOVED_FROM + | IN_MOVED_TO; - if (inotify_add_watch(fd, filename, flags) == -1) { + if (inotify_add_watch(fd, filename, events) == -1) { uv__set_sys_error(loop, errno); uv__close(fd); return -1; diff --git a/src/rt/libuv/src/unix/pipe.c b/src/rt/libuv/src/unix/pipe.c index dabdcd6cff81..87959a6e5da9 100644 --- a/src/rt/libuv/src/unix/pipe.c +++ b/src/rt/libuv/src/unix/pipe.c @@ -177,7 +177,7 @@ void uv_pipe_open(uv_pipe_t* handle, uv_file fd) { } -int uv_pipe_connect(uv_connect_t* req, +void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { @@ -209,7 +209,7 @@ int uv_pipe_connect(uv_connect_t* req, while (r == -1 && errno == EINTR); if (r == -1) { - uv__set_sys_error(handle->loop, errno); + status = errno; uv__close(sockfd); goto out; } @@ -237,7 +237,6 @@ out: * return 0 and let the callback handle errors. */ errno = saved_errno; - return 0; } diff --git a/src/rt/libuv/src/unix/process.c b/src/rt/libuv/src/unix/process.c index a76864500c09..555be5a6e56f 100644 --- a/src/rt/libuv/src/unix/process.c +++ b/src/rt/libuv/src/unix/process.c @@ -300,3 +300,14 @@ int uv_process_kill(uv_process_t* process, int signum) { return 0; } } + + +uv_err_t uv_kill(int pid, int signum) { + int r = kill(pid, signum); + + if (r) { + return uv__new_sys_error(errno); + } else { + return uv_ok_; + } +} diff --git a/src/rt/libuv/src/unix/stream.c b/src/rt/libuv/src/unix/stream.c index 2e5bde0143c9..3cdeaa8cf7b2 100644 --- a/src/rt/libuv/src/unix/stream.c +++ b/src/rt/libuv/src/unix/stream.c @@ -62,6 +62,7 @@ void uv__stream_init(uv_loop_t* loop, stream->accepted_fd = -1; stream->fd = -1; stream->delayed_error = 0; + stream->blocking = 0; ngx_queue_init(&stream->write_queue); ngx_queue_init(&stream->write_completed_queue); stream->write_queue_size = 0; @@ -340,9 +341,9 @@ static void uv__write(uv_stream_t* stream) { int iovcnt; ssize_t n; - assert(stream->fd >= 0); +start: - /* TODO: should probably while(1) here until EAGAIN */ + assert(stream->fd >= 0); /* Get the request at the head of the queue. */ req = uv_write_queue_head(stream); @@ -353,14 +354,16 @@ static void uv__write(uv_stream_t* stream) { assert(req->handle == stream); - /* Cast to iovec. We had to have our own uv_buf_t instead of iovec + /* + * Cast to iovec. We had to have our own uv_buf_t instead of iovec * because Windows's WSABUF is not an iovec. */ assert(sizeof(uv_buf_t) == sizeof(struct iovec)); iov = (struct iovec*) &(req->bufs[req->write_index]); iovcnt = req->bufcnt - req->write_index; - /* Now do the actual writev. Note that we've been updating the pointers + /* + * Now do the actual writev. Note that we've been updating the pointers * inside the iov each time we write. So there is no need to offset it. */ @@ -409,6 +412,9 @@ static void uv__write(uv_stream_t* stream) { stream->write_queue_size -= uv__write_req_size(req); uv__write_req_finish(req); return; + } else if (stream->blocking) { + /* If this is a blocking stream, try again. */ + goto start; } } else { /* Successful write */ @@ -426,8 +432,17 @@ static void uv__write(uv_stream_t* stream) { stream->write_queue_size -= n; n = 0; - /* There is more to write. Break and ensure the watcher is pending. */ - break; + /* There is more to write. */ + if (stream->blocking) { + /* + * If we're blocking then we should not be enabling the write + * watcher - instead we need to try again. + */ + goto start; + } else { + /* Break loop and ensure the watcher is pending. */ + break; + } } else { /* Finished writing the buf at index req->write_index. */ @@ -453,6 +468,9 @@ static void uv__write(uv_stream_t* stream) { /* Either we've counted n down to zero or we've got EAGAIN. */ assert(n == 0 || n == -1); + /* Only non-blocking streams should use the write_watcher. */ + assert(!stream->blocking); + /* We're not done. */ ev_io_start(stream->loop->ev, &stream->write_watcher); } @@ -862,6 +880,13 @@ int uv_write2(uv_write_t* req, uv_stream_t* stream, uv_buf_t bufs[], int bufcnt, if (empty_queue) { uv__write(stream); } else { + /* + * blocking streams should never have anything in the queue. + * if this assert fires then somehow the blocking stream isn't being + * sufficently flushed in uv__write. + */ + assert(!stream->blocking); + ev_io_start(stream->loop->ev, &stream->write_watcher); } diff --git a/src/rt/libuv/src/unix/sunos.c b/src/rt/libuv/src/unix/sunos.c index c0bfe32e0397..f53122079865 100644 --- a/src/rt/libuv/src/unix/sunos.c +++ b/src/rt/libuv/src/unix/sunos.c @@ -23,13 +23,17 @@ #include #include +#include +#include #include #include -#include #include +#include +#include #include #include +#include uint64_t uv_hrtime() { @@ -81,15 +85,91 @@ void uv_loadavg(double avg[3]) { } +static void uv__fs_event_rearm(uv_fs_event_t *handle) { + if (port_associate(handle->fd, + PORT_SOURCE_FILE, + (uintptr_t) &handle->fo, + FILE_ATTRIB | FILE_MODIFIED, + NULL) == -1) { + uv__set_sys_error(handle->loop, errno); + } +} + + +static void uv__fs_event_read(EV_P_ ev_io* w, int revents) { + uv_fs_event_t *handle; + timespec_t timeout; + port_event_t pe; + int events; + int r; + + handle = container_of(w, uv_fs_event_t, event_watcher); + + do { + /* TODO use port_getn() */ + do { + memset(&timeout, 0, sizeof timeout); + r = port_get(handle->fd, &pe, &timeout); + } + while (r == -1 && errno == EINTR); + + if (r == -1 && errno == ETIME) + break; + + assert((r == 0) && "unexpected port_get() error"); + + events = 0; + if (pe.portev_events & (FILE_ATTRIB | FILE_MODIFIED)) + events |= UV_CHANGE; + if (pe.portev_events & ~(FILE_ATTRIB | FILE_MODIFIED)) + events |= UV_RENAME; + assert(events != 0); + + handle->cb(handle, NULL, events, 0); + } + while (handle->fd != -1); + + if (handle->fd != -1) + uv__fs_event_rearm(handle); +} + + int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, const char* filename, - uv_fs_event_cb cb) { - uv__set_sys_error(loop, ENOSYS); - return -1; + uv_fs_event_cb cb, + int flags) { + int portfd; + + /* We don't support any flags yet. */ + assert(!flags); + + if ((portfd = port_create()) == -1) { + uv__set_sys_error(loop, errno); + return -1; + } + + uv__handle_init(loop, (uv_handle_t*)handle, UV_FS_EVENT); + handle->filename = strdup(filename); + handle->fd = portfd; + handle->cb = cb; + + memset(&handle->fo, 0, sizeof handle->fo); + handle->fo.fo_name = handle->filename; + uv__fs_event_rearm(handle); + + ev_io_init(&handle->event_watcher, uv__fs_event_read, portfd, EV_READ); + ev_io_start(loop->ev, &handle->event_watcher); + + return 0; } void uv__fs_event_destroy(uv_fs_event_t* handle) { - assert(0 && "implement me"); + ev_io_stop(handle->loop->ev, &handle->event_watcher); + uv__close(handle->fd); + handle->fd = -1; + free(handle->filename); + handle->filename = NULL; + handle->fo.fo_name = NULL; } diff --git a/src/rt/libuv/src/unix/tcp.c b/src/rt/libuv/src/unix/tcp.c index 67ed217196d0..ee94ab3ed84e 100644 --- a/src/rt/libuv/src/unix/tcp.c +++ b/src/rt/libuv/src/unix/tcp.c @@ -319,3 +319,8 @@ int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { return 0; } + + +int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { + return 0; +} diff --git a/src/rt/libuv/src/unix/tty.c b/src/rt/libuv/src/unix/tty.c index 32ac2c71c7d5..de77f5c46abb 100644 --- a/src/rt/libuv/src/unix/tty.c +++ b/src/rt/libuv/src/unix/tty.c @@ -41,7 +41,6 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { uv__stream_open((uv_stream_t*)tty, fd, UV_READABLE); } else { /* Note: writable tty we set to blocking mode. */ - uv__nonblock(fd, 0); uv__stream_open((uv_stream_t*)tty, fd, UV_WRITABLE); tty->blocking = 1; } diff --git a/src/rt/libuv/src/uv-common.c b/src/rt/libuv/src/uv-common.c index b42c761e13f1..599d6257890e 100644 --- a/src/rt/libuv/src/uv-common.c +++ b/src/rt/libuv/src/uv-common.c @@ -48,12 +48,16 @@ uv_buf_t uv_buf_init(char* base, size_t len) { } +const uv_err_t uv_ok_ = { UV_OK, 0 }; + + const char* uv_err_name(uv_err_t err) { switch (err.code) { case UV_UNKNOWN: return "UNKNOWN"; case UV_OK: return "OK"; case UV_EOF: return "EOF"; - case UV_EACCESS: return "EACCESS"; + case UV_EADDRINFO: return "EADDRINFO"; + case UV_EACCES: return "EACCES"; case UV_EAGAIN: return "EAGAIN"; case UV_EADDRINUSE: return "EADDRINUSE"; case UV_EADDRNOTAVAIL: return "EADDRNOTAVAIL"; @@ -71,6 +75,7 @@ const char* uv_err_name(uv_err_t err) { case UV_EINVAL: return "EINVAL"; case UV_EISCONN: return "EISCONN"; case UV_EMFILE: return "EMFILE"; + case UV_EMSGSIZE: return "EMSGSIZE"; case UV_ENETDOWN: return "ENETDOWN"; case UV_ENETUNREACH: return "ENETUNREACH"; case UV_ENFILE: return "ENFILE"; @@ -89,6 +94,12 @@ const char* uv_err_name(uv_err_t err) { case UV_EPROTONOSUPPORT: return "EPROTONOSUPPORT"; case UV_EPROTOTYPE: return "EPROTOTYPE"; case UV_ETIMEDOUT: return "ETIMEDOUT"; + case UV_ECHARSET: return "ECHARSET"; + case UV_EAIFAMNOSUPPORT: return "EAIFAMNOSUPPORT"; + case UV_EAINONAME: return "EAINONAME"; + case UV_EAISERVICE: return "EAISERVICE"; + case UV_EAISOCKTYPE: return "EAISOCKTYPE"; + case UV_ESHUTDOWN: return "ESHUTDOWN"; case UV_EEXIST: return "EEXIST"; default: assert(0); @@ -115,6 +126,14 @@ void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code) { } +uv_err_t uv__new_sys_error(int sys_error) { + uv_err_t error; + error.code = uv_translate_sys_error(sys_error); + error.sys_errno_ = sys_error; + return error; +} + + uv_err_t uv_last_error(uv_loop_t* loop) { return loop->last_err; } diff --git a/src/rt/libuv/src/uv-common.h b/src/rt/libuv/src/uv-common.h index ff81e0dc0a86..eecb1304386e 100644 --- a/src/rt/libuv/src/uv-common.h +++ b/src/rt/libuv/src/uv-common.h @@ -48,10 +48,13 @@ void uv_add_ares_handle(uv_loop_t* loop, uv_ares_task_t* handle); int uv_ares_handles_empty(uv_loop_t* loop); +extern const uv_err_t uv_ok_; + uv_err_code uv_translate_sys_error(int sys_errno); void uv__set_error(uv_loop_t* loop, uv_err_code code, int sys_error); void uv__set_sys_error(uv_loop_t* loop, int sys_error); void uv__set_artificial_error(uv_loop_t* loop, uv_err_code code); +uv_err_t uv__new_sys_error(int sys_error); int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr); int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr); diff --git a/src/rt/libuv/src/win/core.c b/src/rt/libuv/src/win/core.c index ecdc5fb05193..4914fb4190de 100644 --- a/src/rt/libuv/src/win/core.c +++ b/src/rt/libuv/src/win/core.c @@ -40,6 +40,10 @@ static uv_once_t uv_default_loop_init_guard_ = UV_ONCE_INIT; static void uv_init(void) { + /* Tell Windows that we will handle critical errors. */ + SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | + SEM_NOOPENFILEERRORBOX); + /* Initialize winsock */ uv_winsock_init(); @@ -95,12 +99,23 @@ static void uv_default_loop_init(void) { } -uv_loop_t* uv_default_loop() { +uv_loop_t* uv_default_loop(void) { uv_once(&uv_default_loop_init_guard_, uv_default_loop_init); return &uv_default_loop_; } +uv_loop_t* uv_loop_new(void) { + assert(0 && "implement me"); + return NULL; +} + + +void uv_loop_delete(uv_loop_t* loop) { + assert(0 && "implement me"); +} + + void uv_ref(uv_loop_t* loop) { loop->refs++; } @@ -147,7 +162,7 @@ static void uv_poll_ex(uv_loop_t* loop, int block) { BOOL success; DWORD timeout; uv_req_t* req; - OVERLAPPED_ENTRY overlappeds[64]; + OVERLAPPED_ENTRY overlappeds[128]; ULONG count; ULONG i; diff --git a/src/rt/libuv/src/win/dl.c b/src/rt/libuv/src/win/dl.c new file mode 100644 index 000000000000..37cdc131a1a9 --- /dev/null +++ b/src/rt/libuv/src/win/dl.c @@ -0,0 +1,63 @@ +/* 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 "internal.h" + + +uv_err_t uv_dlopen(const char* filename, uv_lib_t* library) { + wchar_t filename_w[32768]; + HMODULE handle; + + if (!uv_utf8_to_utf16(filename, + filename_w, + sizeof(filename_w) / sizeof(wchar_t))) { + return uv__new_sys_error(GetLastError()); + } + + handle = LoadLibraryW(filename_w); + if (handle == NULL) { + return uv__new_sys_error(GetLastError()); + } + + *library = handle; + return uv_ok_; +} + + +uv_err_t uv_dlclose(uv_lib_t library) { + if (!FreeLibrary(library)) { + return uv__new_sys_error(GetLastError()); + } + + return uv_ok_; +} + + +uv_err_t uv_dlsym(uv_lib_t library, const char* name, void** ptr) { + FARPROC proc = GetProcAddress(library, name); + if (proc == NULL) { + return uv__new_sys_error(GetLastError()); + } + + *ptr = (void*) proc; + return uv_ok_; +} diff --git a/src/rt/libuv/src/win/error.c b/src/rt/libuv/src/win/error.c index a060b2b962b5..1317ce5b6cc7 100644 --- a/src/rt/libuv/src/win/error.c +++ b/src/rt/libuv/src/win/error.c @@ -30,9 +30,6 @@ #include "internal.h" -const uv_err_t uv_ok_ = { UV_OK, ERROR_SUCCESS }; - - /* * Display an error message and abort the event loop. */ @@ -70,7 +67,7 @@ void uv_fatal_error(const int errorno, const char* syscall) { /* TODO: thread safety */ static char* last_err_str_ = NULL; -char* uv_strerror(uv_err_t err) { +const char* uv_strerror(uv_err_t err) { if (last_err_str_ != NULL) { LocalFree(last_err_str_); } @@ -93,8 +90,8 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_SUCCESS: return UV_OK; case ERROR_FILE_NOT_FOUND: return UV_ENOENT; case ERROR_PATH_NOT_FOUND: return UV_ENOENT; - case ERROR_NOACCESS: return UV_EACCESS; - case WSAEACCES: return UV_EACCESS; + case ERROR_NOACCESS: return UV_EACCES; + case WSAEACCES: return UV_EACCES; case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; case WSAEADDRINUSE: return UV_EADDRINUSE; case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL; diff --git a/src/rt/libuv/src/win/fs-event.c b/src/rt/libuv/src/win/fs-event.c index a416df2f5044..b2f6583a408b 100644 --- a/src/rt/libuv/src/win/fs-event.c +++ b/src/rt/libuv/src/win/fs-event.c @@ -133,12 +133,15 @@ static int uv_split_path(const wchar_t* filename, wchar_t** dir, int uv_fs_event_init(uv_loop_t* loop, uv_fs_event_t* handle, - const char* filename, uv_fs_event_cb cb) { + const char* filename, uv_fs_event_cb cb, int flags) { int name_size; DWORD attr, last_error; wchar_t* dir = NULL, *dir_to_watch, *filenamew; wchar_t short_path[MAX_PATH]; + /* We don't support any flags yet. */ + assert(!flags); + uv_fs_event_init_handle(loop, handle, filename, cb); /* Convert name to UTF16. */ @@ -353,7 +356,9 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, offset = file_info->NextEntryOffset; } while(offset); } else { - handle->cb(handle, NULL, UV_CHANGE, 0); + if (!(handle->flags & UV_HANDLE_CLOSING)) { + handle->cb(handle, NULL, UV_CHANGE, 0); + } } } else { uv__set_sys_error(loop, GET_REQ_ERROR(req)); diff --git a/src/rt/libuv/src/win/fs.c b/src/rt/libuv/src/win/fs.c index a2c572d64f0d..09ff145ce27a 100644 --- a/src/rt/libuv/src/win/fs.c +++ b/src/rt/libuv/src/win/fs.c @@ -173,19 +173,24 @@ void fs__open(uv_fs_t* req, const wchar_t* path, int flags, int mode) { /* convert flags and mode to CreateFile parameters */ switch (flags & (_O_RDONLY | _O_WRONLY | _O_RDWR)) { case _O_RDONLY: - access = GENERIC_READ; + access = FILE_GENERIC_READ; break; case _O_WRONLY: - access = GENERIC_WRITE; + access = FILE_GENERIC_WRITE; break; case _O_RDWR: - access = GENERIC_READ | GENERIC_WRITE; + access = FILE_GENERIC_READ | FILE_GENERIC_WRITE; break; default: result = -1; goto end; } + if (flags & _O_APPEND) { + access &= ~FILE_WRITE_DATA; + access |= FILE_APPEND_DATA; + } + /* * Here is where we deviate significantly from what CRT's _open() * does. We indiscriminately use all the sharing modes, to match diff --git a/src/rt/libuv/src/win/internal.h b/src/rt/libuv/src/win/internal.h index 55e02df57e1a..deb8972c5a87 100644 --- a/src/rt/libuv/src/win/internal.h +++ b/src/rt/libuv/src/win/internal.h @@ -44,30 +44,35 @@ void uv_process_timers(uv_loop_t* loop); */ /* Private uv_handle flags */ -#define UV_HANDLE_CLOSING 0x000001 -#define UV_HANDLE_CLOSED 0x000002 -#define UV_HANDLE_BOUND 0x000004 -#define UV_HANDLE_LISTENING 0x000008 -#define UV_HANDLE_CONNECTION 0x000010 -#define UV_HANDLE_CONNECTED 0x000020 -#define UV_HANDLE_READING 0x000040 -#define UV_HANDLE_ACTIVE 0x000040 -#define UV_HANDLE_EOF 0x000080 -#define UV_HANDLE_SHUTTING 0x000100 -#define UV_HANDLE_SHUT 0x000200 -#define UV_HANDLE_ENDGAME_QUEUED 0x000400 -#define UV_HANDLE_BIND_ERROR 0x001000 -#define UV_HANDLE_IPV6 0x002000 -#define UV_HANDLE_PIPESERVER 0x004000 -#define UV_HANDLE_READ_PENDING 0x008000 -#define UV_HANDLE_UV_ALLOCED 0x010000 -#define UV_HANDLE_SYNC_BYPASS_IOCP 0x020000 -#define UV_HANDLE_ZERO_READ 0x040000 -#define UV_HANDLE_TTY_RAW 0x080000 -#define UV_HANDLE_EMULATE_IOCP 0x100000 -#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x200000 -#define UV_HANDLE_TTY_SAVED_POSITION 0x400000 -#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x800000 +#define UV_HANDLE_CLOSING 0x00000001 +#define UV_HANDLE_CLOSED 0x00000002 +#define UV_HANDLE_BOUND 0x00000004 +#define UV_HANDLE_LISTENING 0x00000008 +#define UV_HANDLE_CONNECTION 0x00000010 +#define UV_HANDLE_CONNECTED 0x00000020 +#define UV_HANDLE_READING 0x00000040 +#define UV_HANDLE_ACTIVE 0x00000040 +#define UV_HANDLE_EOF 0x00000080 +#define UV_HANDLE_SHUTTING 0x00000100 +#define UV_HANDLE_SHUT 0x00000200 +#define UV_HANDLE_ENDGAME_QUEUED 0x00000400 +#define UV_HANDLE_BIND_ERROR 0x00001000 +#define UV_HANDLE_IPV6 0x00002000 +#define UV_HANDLE_PIPESERVER 0x00004000 +#define UV_HANDLE_READ_PENDING 0x00008000 +#define UV_HANDLE_UV_ALLOCED 0x00010000 +#define UV_HANDLE_SYNC_BYPASS_IOCP 0x00020000 +#define UV_HANDLE_ZERO_READ 0x00040000 +#define UV_HANDLE_TTY_RAW 0x00080000 +#define UV_HANDLE_EMULATE_IOCP 0x00100000 +#define UV_HANDLE_NON_OVERLAPPED_PIPE 0x00200000 +#define UV_HANDLE_TTY_SAVED_POSITION 0x00400000 +#define UV_HANDLE_TTY_SAVED_ATTRIBUTES 0x00800000 +#define UV_HANDLE_SHARED_TCP_SERVER 0x01000000 +#define UV_HANDLE_TCP_NODELAY 0x02000000 +#define UV_HANDLE_TCP_KEEPALIVE 0x04000000 +#define UV_HANDLE_TCP_SINGLE_ACCEPT 0x08000000 +#define UV_HANDLE_TCP_ACCEPT_STATE_CHANGING 0x10000000 void uv_want_endgame(uv_loop_t* loop, uv_handle_t* handle); void uv_process_endgames(uv_loop_t* loop); @@ -140,6 +145,9 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle); int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info); +int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, + LPWSAPROTOCOL_INFOW protocol_info); + /* * UDP @@ -278,11 +286,6 @@ void uv_fs_event_endgame(uv_loop_t* loop, uv_fs_event_t* handle); int uv_parent_pid(); -/* - * Error handling - */ -extern const uv_err_t uv_ok_; - void uv_fatal_error(const int errorno, const char* syscall); uv_err_code uv_translate_sys_error(int sys_errno); diff --git a/src/rt/libuv/src/win/pipe.c b/src/rt/libuv/src/win/pipe.c index 65d1f11cd1c1..bd187da5f5d9 100644 --- a/src/rt/libuv/src/win/pipe.c +++ b/src/rt/libuv/src/win/pipe.c @@ -362,7 +362,7 @@ int uv_pipe_bind(uv_pipe_t* handle, const char* name) { if (errno == ERROR_ACCESS_DENIED) { uv__set_error(loop, UV_EADDRINUSE, errno); } else if (errno == ERROR_PATH_NOT_FOUND || errno == ERROR_INVALID_NAME) { - uv__set_error(loop, UV_EACCESS, errno); + uv__set_error(loop, UV_EACCES, errno); } else { uv__set_sys_error(loop, errno); } @@ -443,7 +443,7 @@ static DWORD WINAPI pipe_connect_thread_proc(void* parameter) { } -int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, +void uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, const char* name, uv_connect_cb cb) { uv_loop_t* loop = handle->loop; int errno, nameSize; @@ -488,7 +488,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, handle->reqs_pending++; - return 0; + return; } errno = GetLastError(); @@ -505,7 +505,7 @@ int uv_pipe_connect(uv_connect_t* req, uv_pipe_t* handle, SET_REQ_SUCCESS(req); uv_insert_pending_req(loop, (uv_req_t*) req); handle->reqs_pending++; - return 0; + return; error: if (handle->name) { @@ -516,8 +516,12 @@ error: if (pipeHandle != INVALID_HANDLE_VALUE) { CloseHandle(pipeHandle); } - uv__set_sys_error(loop, errno); - return -1; + + /* Make this req pending reporting an error. */ + SET_REQ_ERROR(req, errno); + uv_insert_pending_req(loop, (uv_req_t*) req); + handle->reqs_pending++; + return; } @@ -956,7 +960,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, return -1; } - if (send_handle && send_handle->type != UV_TCP) { + /* Only TCP server handles are supported for sharing. */ + if (send_handle && (send_handle->type != UV_TCP || + send_handle->flags & UV_HANDLE_CONNECTION)) { uv__set_artificial_error(loop, UV_ENOTSUP); return -1; } @@ -989,9 +995,9 @@ static int uv_pipe_write_impl(uv_loop_t* loop, uv_write_t* req, /* Use the IPC framing protocol. */ if (send_handle) { tcp_send_handle = (uv_tcp_t*)send_handle; - if (WSADuplicateSocketW(tcp_send_handle->socket, handle->ipc_pid, + + if (uv_tcp_duplicate_socket(tcp_send_handle, handle->ipc_pid, &ipc_frame.socket_info)) { - uv__set_sys_error(loop, WSAGetLastError()); return -1; } ipc_frame.header.flags |= UV_IPC_UV_STREAM; diff --git a/src/rt/libuv/src/win/process.c b/src/rt/libuv/src/win/process.c index 0e70984013aa..fd8018febcb0 100644 --- a/src/rt/libuv/src/win/process.c +++ b/src/rt/libuv/src/win/process.c @@ -26,8 +26,11 @@ #include #include #include +#include #include +#define SIGKILL 9 + typedef struct env_var { const char* narrow; const wchar_t* wide; @@ -265,6 +268,8 @@ static wchar_t* search_path(const wchar_t *file, wchar_t* result = NULL; wchar_t *file_name_start; wchar_t *dot; + const wchar_t *dir_start, *dir_end, *dir_path; + int dir_len; int name_has_ext; int file_len = wcslen(file); @@ -302,8 +307,7 @@ static wchar_t* search_path(const wchar_t *file, name_has_ext); } else { - const wchar_t *dir_start, - *dir_end = path; + dir_end = path; /* The file is really only a name; look in cwd first, then scan path */ result = path_search_walk_ext(L"", 0, @@ -335,7 +339,20 @@ static wchar_t* search_path(const wchar_t *file, continue; } - result = path_search_walk_ext(dir_start, dir_end - dir_start, + dir_path = dir_start; + dir_len = dir_end - dir_start; + + /* Adjust if the path is quoted. */ + if (dir_path[0] == '"' || dir_path[0] == '\'') { + ++dir_path; + --dir_len; + } + + if (dir_path[dir_len - 1] == '"' || dir_path[dir_len - 1] == '\'') { + --dir_len; + } + + result = path_search_walk_ext(dir_path, dir_len, file, file_len, cwd, cwd_len, name_has_ext); @@ -1052,35 +1069,65 @@ done: } -int uv_process_kill(uv_process_t* process, int signum) { +static uv_err_t uv__kill(HANDLE process_handle, int signum) { DWORD status; + uv_err_t err; + + if (signum == SIGTERM || signum == SIGKILL || signum == SIGINT) { + /* Kill the process. On Windows, killed processes normally return 1. */ + if (TerminateProcess(process_handle, 1)) { + err = uv_ok_; + } else { + err = uv__new_sys_error(GetLastError()); + } + } else if (signum == 0) { + /* Health check: is the process still alive? */ + if (GetExitCodeProcess(process_handle, &status) && + status == STILL_ACTIVE) { + err = uv_ok_; + } else { + err = uv__new_sys_error(GetLastError()); + } + } else { + err.code = UV_ENOSYS; + } + + return err; +} + + +int uv_process_kill(uv_process_t* process, int signum) { + uv_err_t err; if (process->process_handle == INVALID_HANDLE_VALUE) { uv__set_artificial_error(process->loop, UV_EINVAL); return -1; } - if (signum) { - /* Kill the process. On Windows, killed processes normally return 1. */ - if (TerminateProcess(process->process_handle, 1)) { - process->exit_signal = signum; - return 0; - } - else { - uv__set_sys_error(process->loop, GetLastError()); - return -1; - } - } - else { - /* Health check: is the process still alive? */ - if (GetExitCodeProcess(process->process_handle, &status) && status == STILL_ACTIVE) { - return 0; - } - else { - uv__set_artificial_error(process->loop, UV_EINVAL); - return -1; - } + err = uv__kill(process->process_handle, signum); + + if (err.code != UV_OK) { + uv__set_error(process->loop, err.code, err.sys_errno_); + return -1; } - assert(0 && "unreachable"); + process->exit_signal = signum; + + return 0; +} + + +uv_err_t uv_kill(int pid, int signum) { + uv_err_t err; + HANDLE process_handle = OpenProcess(PROCESS_TERMINATE | + PROCESS_QUERY_INFORMATION, FALSE, pid); + + if (process_handle == INVALID_HANDLE_VALUE) { + return uv__new_sys_error(GetLastError()); + } + + err = uv__kill(process_handle, signum); + CloseHandle(process_handle); + + return err; } diff --git a/src/rt/libuv/src/win/tcp.c b/src/rt/libuv/src/win/tcp.c index 0ff6890bcf79..f57c825d15eb 100644 --- a/src/rt/libuv/src/win/tcp.c +++ b/src/rt/libuv/src/win/tcp.c @@ -46,6 +46,42 @@ static char uv_zero_[] = ""; static unsigned int active_tcp_streams = 0; +static int uv__tcp_nodelay(uv_tcp_t* handle, SOCKET socket, int enable) { + if (setsockopt(socket, + IPPROTO_TCP, + TCP_NODELAY, + (const char*)&enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + return 0; +} + + +static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsigned int delay) { + if (setsockopt(socket, + SOL_SOCKET, + SO_KEEPALIVE, + (const char*)&enable, + sizeof enable) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + + if (enable && setsockopt(socket, + IPPROTO_TCP, + TCP_KEEPALIVE, + (const char*)&delay, + sizeof delay) == -1) { + uv__set_sys_error(handle->loop, errno); + return -1; + } + + return 0; +} + + static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, SOCKET socket, int imported) { DWORD yes = 1; @@ -89,6 +125,17 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, } } + if ((handle->flags & UV_HANDLE_TCP_NODELAY) && + uv__tcp_nodelay(handle, socket, 1)) { + return -1; + } + + /* TODO: Use stored delay. */ + if ((handle->flags & UV_HANDLE_TCP_KEEPALIVE) && + uv__tcp_keepalive(handle, socket, 1, 60)) { + return -1; + } + handle->socket = socket; return 0; @@ -105,6 +152,7 @@ int uv_tcp_init(uv_loop_t* loop, uv_tcp_t* handle) { handle->reqs_pending = 0; handle->func_acceptex = NULL; handle->func_connectex = NULL; + handle->processed_accepts = 0; loop->counters.tcp_init++; @@ -392,7 +440,7 @@ static void uv_tcp_queue_read(uv_loop_t* loop, uv_tcp_t* handle) { int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { uv_loop_t* loop = handle->loop; - unsigned int i; + unsigned int i, simultaneous_accepts; uv_tcp_accept_t* req; assert(backlog > 0); @@ -402,13 +450,6 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { return -1; } - if (handle->flags & UV_HANDLE_LISTENING || - handle->flags & UV_HANDLE_READING) { - /* Already listening. */ - uv__set_sys_error(loop, WSAEALREADY); - return -1; - } - if (!(handle->flags & UV_HANDLE_BOUND) && uv_tcp_bind(handle, uv_addr_ip4_any_) < 0) return -1; @@ -420,7 +461,8 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { } } - if (listen(handle->socket, backlog) == SOCKET_ERROR) { + if (!(handle->flags & UV_HANDLE_SHARED_TCP_SERVER) && + listen(handle->socket, backlog) == SOCKET_ERROR) { uv__set_sys_error(loop, WSAGetLastError()); return -1; } @@ -428,31 +470,35 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { handle->flags |= UV_HANDLE_LISTENING; handle->connection_cb = cb; - assert(!handle->accept_reqs); - handle->accept_reqs = (uv_tcp_accept_t*) - malloc(uv_simultaneous_server_accepts * sizeof(uv_tcp_accept_t)); - if (!handle->accept_reqs) { - uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); - } + simultaneous_accepts = handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT ? 1 + : uv_simultaneous_server_accepts; - for (i = 0; i < uv_simultaneous_server_accepts; i++) { - req = &handle->accept_reqs[i]; - uv_req_init(loop, (uv_req_t*)req); - req->type = UV_ACCEPT; - req->accept_socket = INVALID_SOCKET; - req->data = handle; - - req->wait_handle = INVALID_HANDLE_VALUE; - if (handle->flags & UV_HANDLE_EMULATE_IOCP) { - req->event_handle = CreateEvent(NULL, 0, 0, NULL); - if (!req->event_handle) { - uv_fatal_error(GetLastError(), "CreateEvent"); - } - } else { - req->event_handle = NULL; + if(!handle->accept_reqs) { + handle->accept_reqs = (uv_tcp_accept_t*) + malloc(simultaneous_accepts * sizeof(uv_tcp_accept_t)); + if (!handle->accept_reqs) { + uv_fatal_error(ERROR_OUTOFMEMORY, "malloc"); } - uv_tcp_queue_accept(handle, req); + for (i = 0; i < simultaneous_accepts; i++) { + req = &handle->accept_reqs[i]; + uv_req_init(loop, (uv_req_t*)req); + req->type = UV_ACCEPT; + req->accept_socket = INVALID_SOCKET; + req->data = handle; + + req->wait_handle = INVALID_HANDLE_VALUE; + if (handle->flags & UV_HANDLE_EMULATE_IOCP) { + req->event_handle = CreateEvent(NULL, 0, 0, NULL); + if (!req->event_handle) { + uv_fatal_error(GetLastError(), "CreateEvent"); + } + } else { + req->event_handle = NULL; + } + + uv_tcp_queue_accept(handle, req); + } } return 0; @@ -491,7 +537,26 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { req->accept_socket = INVALID_SOCKET; if (!(server->flags & UV_HANDLE_CLOSING)) { - uv_tcp_queue_accept(server, req); + /* Check if we're in a middle of changing the number of pending accepts. */ + if (!(server->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING)) { + uv_tcp_queue_accept(server, req); + } else { + /* We better be switching to a single pending accept. */ + assert(server->flags & UV_HANDLE_TCP_SINGLE_ACCEPT); + + server->processed_accepts++; + + if (server->processed_accepts >= uv_simultaneous_server_accepts) { + server->processed_accepts = 0; + /* + * All previously queued accept requests are now processed. + * We now switch to queueing just a single accept. + */ + uv_tcp_queue_accept(server, &server->accept_reqs[0]); + server->flags &= ~UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; + server->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; + } + } } active_tcp_streams++; @@ -759,9 +824,19 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, /* An error occurred doing the read. */ if ((handle->flags & UV_HANDLE_READING)) { handle->flags &= ~UV_HANDLE_READING; - uv__set_sys_error(loop, GET_REQ_SOCK_ERROR(req)); buf = (handle->flags & UV_HANDLE_ZERO_READ) ? uv_buf_init(NULL, 0) : handle->read_buffer; + + err = GET_REQ_SOCK_ERROR(req); + + if (err == WSAECONNABORTED) { + /* Treat WSAECONNABORTED as connection closed. */ + handle->flags |= UV_HANDLE_EOF; + uv__set_error(loop, UV_EOF, ERROR_SUCCESS); + } else { + uv__set_sys_error(loop, err); + } + handle->read_cb((uv_stream_t*)handle, -1, buf); } } else { @@ -822,8 +897,14 @@ void uv_process_tcp_read_req(uv_loop_t* loop, uv_tcp_t* handle, uv__set_sys_error(loop, WSAEWOULDBLOCK); handle->read_cb((uv_stream_t*)handle, 0, buf); } else { - /* Ouch! serious error. */ - uv__set_sys_error(loop, err); + if (err == WSAECONNABORTED) { + /* Treat WSAECONNABORTED as connection closed. */ + handle->flags |= UV_HANDLE_EOF; + uv__set_error(loop, UV_EOF, ERROR_SUCCESS); + } else { + /* Ouch! serious error. */ + uv__set_sys_error(loop, err); + } handle->flags &= ~UV_HANDLE_READING; handle->read_cb((uv_stream_t*)handle, -1, buf); } @@ -953,18 +1034,111 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info) { } tcp->flags |= UV_HANDLE_BOUND; + tcp->flags |= UV_HANDLE_SHARED_TCP_SERVER; return uv_tcp_set_socket(tcp->loop, tcp, socket, 1); } int uv_tcp_nodelay(uv_tcp_t* handle, int enable) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; + if (handle->socket != INVALID_SOCKET && + uv__tcp_nodelay(handle, handle->socket, enable)) { + return -1; + } + + if (enable) { + handle->flags |= UV_HANDLE_TCP_NODELAY; + } else { + handle->flags &= ~UV_HANDLE_TCP_NODELAY; + } + + return 0; } int uv_tcp_keepalive(uv_tcp_t* handle, int enable, unsigned int delay) { - uv__set_artificial_error(handle->loop, UV_ENOSYS); - return -1; + if (handle->socket != INVALID_SOCKET && + uv__tcp_keepalive(handle, handle->socket, enable, delay)) { + return -1; + } + + if (enable) { + handle->flags |= UV_HANDLE_TCP_KEEPALIVE; + } else { + handle->flags &= ~UV_HANDLE_TCP_KEEPALIVE; + } + + /* TODO: Store delay if handle->socket isn't created yet. */ + + return 0; } + + + +int uv_tcp_duplicate_socket(uv_tcp_t* handle, int pid, + LPWSAPROTOCOL_INFOW protocol_info) { + assert(!(handle->flags & UV_HANDLE_CONNECTION)); + + /* + * We're about to share the socket with another process. Because + * this is a listening socket, we assume that the other process will + * be accepting conections on it. So, before sharing the socket + * with another process, we call listen here in the parent process. + * This needs to be modified if the socket is shared with + * another process for anything other than accepting connections. + */ + + if (!(handle->flags & UV_HANDLE_LISTENING)) { + if (!(handle->flags & UV_HANDLE_BOUND)) { + uv__set_artificial_error(handle->loop, UV_EINVAL); + return -1; + } + if (listen(handle->socket, SOMAXCONN) == SOCKET_ERROR) { + uv__set_sys_error(handle->loop, WSAGetLastError()); + return -1; + } + + handle->flags |= UV_HANDLE_SHARED_TCP_SERVER; + } + + if (WSADuplicateSocketW(handle->socket, pid, protocol_info)) { + uv__set_sys_error(handle->loop, WSAGetLastError()); + return -1; + } + + return 0; +} + + +int uv_tcp_simultaneous_accepts(uv_tcp_t* handle, int enable) { + if (handle->flags & UV_HANDLE_CONNECTION) { + uv__set_artificial_error(handle->loop, UV_EINVAL); + return -1; + } + + /* Check if we're already in the desired mode. */ + if ((enable && !(handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) || + (!enable && handle->flags & UV_HANDLE_TCP_SINGLE_ACCEPT)) { + return 0; + } + + /* Don't allow switching from single pending accept to many. */ + if (enable) { + uv__set_artificial_error(handle->loop, UV_ENOTSUP); + return -1; + } + + /* Check if we're in a middle of changing the number of pending accepts. */ + if (handle->flags & UV_HANDLE_TCP_ACCEPT_STATE_CHANGING) { + return 0; + } + + handle->flags |= UV_HANDLE_TCP_SINGLE_ACCEPT; + + /* Flip the changing flag if we have already queueed multiple accepts. */ + if (handle->flags & UV_HANDLE_LISTENING) { + handle->flags |= UV_HANDLE_TCP_ACCEPT_STATE_CHANGING; + } + + return 0; +} \ No newline at end of file diff --git a/src/rt/libuv/src/win/winsock.h b/src/rt/libuv/src/win/winsock.h index beee032137cf..433ce4767012 100644 --- a/src/rt/libuv/src/win/winsock.h +++ b/src/rt/libuv/src/win/winsock.h @@ -37,6 +37,10 @@ # define SO_UPDATE_CONNECT_CONTEXT 0x7010 #endif +#ifndef TCP_KEEPALIVE +# define TCP_KEEPALIVE 3 +#endif + #ifndef IPV6_V6ONLY #define IPV6_V6ONLY 27 #endif diff --git a/src/rt/libuv/test/benchmark-pound.c b/src/rt/libuv/test/benchmark-pound.c index af7ce247dab4..92a536db77f5 100644 --- a/src/rt/libuv/test/benchmark-pound.c +++ b/src/rt/libuv/test/benchmark-pound.c @@ -225,12 +225,7 @@ static void pipe_make_connect(conn_rec* p) { r = uv_pipe_init(loop, (uv_pipe_t*)&p->stream, 0); ASSERT(r == 0); - r = uv_pipe_connect(&((pipe_conn_rec*)p)->conn_req, (uv_pipe_t*)&p->stream, TEST_PIPENAME, connect_cb); - if (r) { - fprintf(stderr, "uv_tcp_connect error %s\n", - uv_err_name(uv_last_error(loop))); - ASSERT(0); - } + uv_pipe_connect(&((pipe_conn_rec*)p)->conn_req, (uv_pipe_t*)&p->stream, TEST_PIPENAME, connect_cb); #if DEBUG printf("make connect %d\n", p->i); diff --git a/src/rt/libuv/test/benchmark-pump.c b/src/rt/libuv/test/benchmark-pump.c index 27e8abe0c821..52f295727c44 100644 --- a/src/rt/libuv/test/benchmark-pump.c +++ b/src/rt/libuv/test/benchmark-pump.c @@ -257,8 +257,7 @@ static void maybe_connect_some() { ASSERT(r == 0); req = (uv_connect_t*) req_alloc(); - r = uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb); - ASSERT(r == 0); + uv_pipe_connect(req, pipe, TEST_PIPENAME, connect_cb); } } } diff --git a/src/rt/libuv/test/run-tests.c b/src/rt/libuv/test/run-tests.c index 7fb48d14b68a..1d8b0bcf5062 100644 --- a/src/rt/libuv/test/run-tests.c +++ b/src/rt/libuv/test/run-tests.c @@ -112,7 +112,7 @@ static void ipc_on_connection(uv_stream_t* server, int status) { } -static int ipc_helper() { +static int ipc_helper(int listen_after_write) { /* * This is launched from test-ipc.c. stdin is a duplex channel that we * over which a handle will be transmitted. In this initial version only @@ -135,14 +135,21 @@ static int ipc_helper() { r = uv_tcp_bind(&tcp_server, uv_ip4_addr("0.0.0.0", TEST_PORT)); ASSERT(r == 0); - r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); - ASSERT(r == 0); + if (!listen_after_write) { + r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); + ASSERT(r == 0); + } buf = uv_buf_init("hello\n", 6); r = uv_write2(&write_req, (uv_stream_t*)&channel, &buf, 1, (uv_stream_t*)&tcp_server, NULL); ASSERT(r == 0); + if (listen_after_write) { + r = uv_listen((uv_stream_t*)&tcp_server, 12, ipc_on_connection); + ASSERT(r == 0); + } + r = uv_run(uv_default_loop()); ASSERT(r == 0); @@ -251,8 +258,12 @@ static int maybe_run_test(int argc, char **argv) { return 0; } - if (strcmp(argv[1], "ipc_helper") == 0) { - return ipc_helper(); + if (strcmp(argv[1], "ipc_helper_listen_before_write") == 0) { + return ipc_helper(0); + } + + if (strcmp(argv[1], "ipc_helper_listen_after_write") == 0) { + return ipc_helper(1); } if (strcmp(argv[1], "stdio_over_pipes_helper") == 0) { diff --git a/src/rt/libuv/test/test-fs-event.c b/src/rt/libuv/test/test-fs-event.c index 724000db153c..c1f23fe996a9 100644 --- a/src/rt/libuv/test/test-fs-event.c +++ b/src/rt/libuv/test/test-fs-event.c @@ -144,7 +144,7 @@ TEST_IMPL(fs_event_watch_dir) { uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL); create_dir(loop, "watch_dir"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir); + r = uv_fs_event_init(loop, &fs_event, "watch_dir", fs_event_cb_dir, 0); ASSERT(r != -1); r = uv_timer_init(loop, &timer); ASSERT(r != -1); @@ -178,7 +178,7 @@ TEST_IMPL(fs_event_watch_file) { create_file(loop, "watch_dir/file1"); create_file(loop, "watch_dir/file2"); - r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file); + r = uv_fs_event_init(loop, &fs_event, "watch_dir/file2", fs_event_cb_file, 0); ASSERT(r != -1); r = uv_timer_init(loop, &timer); ASSERT(r != -1); @@ -212,7 +212,7 @@ TEST_IMPL(fs_event_watch_file_current_dir) { create_file(loop, "watch_file"); r = uv_fs_event_init(loop, &fs_event, "watch_file", - fs_event_cb_file_current_dir); + fs_event_cb_file_current_dir, 0); ASSERT(r != -1); r = uv_timer_init(loop, &timer); @@ -235,3 +235,36 @@ TEST_IMPL(fs_event_watch_file_current_dir) { r = uv_fs_unlink(loop, &fs_req, "watch_file", NULL); return 0; } + + +TEST_IMPL(fs_event_no_callback_on_close) { + uv_fs_t fs_req; + uv_loop_t* loop = uv_default_loop(); + int r; + + /* Setup */ + uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL); + uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL); + create_dir(loop, "watch_dir"); + create_file(loop, "watch_dir/file1"); + + r = uv_fs_event_init(loop, + &fs_event, + "watch_dir/file1", + fs_event_cb_file, + 0); + ASSERT(r != -1); + + uv_close((uv_handle_t*)&fs_event, close_cb); + + uv_run(loop); + + ASSERT(fs_event_cb_called == 0); + ASSERT(close_cb_called == 1); + + /* Cleanup */ + r = uv_fs_unlink(loop, &fs_req, "watch_dir/file1", NULL); + r = uv_fs_rmdir(loop, &fs_req, "watch_dir", NULL); + + return 0; +} \ No newline at end of file diff --git a/src/rt/libuv/test/test-fs.c b/src/rt/libuv/test/test-fs.c index a8065192fa4a..28b914a770ba 100644 --- a/src/rt/libuv/test/test-fs.c +++ b/src/rt/libuv/test/test-fs.c @@ -1408,3 +1408,71 @@ TEST_IMPL(fs_open_dir) { return 0; } + + +TEST_IMPL(fs_file_open_append) { + int r; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(loop, &open_req1, "test_file", O_WRONLY | O_CREAT, + S_IWRITE | S_IREAD, NULL); + ASSERT(r != -1); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_write(loop, &write_req, open_req1.result, test_buf, + sizeof(test_buf), -1, NULL); + ASSERT(r != -1); + ASSERT(write_req.result != -1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r != -1); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(loop, &open_req1, "test_file", O_RDWR | O_APPEND, 0, NULL); + ASSERT(r != -1); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_write(loop, &write_req, open_req1.result, test_buf, + sizeof(test_buf), -1, NULL); + ASSERT(r != -1); + ASSERT(write_req.result != -1); + uv_fs_req_cleanup(&write_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r != -1); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + r = uv_fs_open(loop, &open_req1, "test_file", O_RDONLY, S_IREAD, NULL); + ASSERT(r != -1); + ASSERT(open_req1.result != -1); + uv_fs_req_cleanup(&open_req1); + + r = uv_fs_read(loop, &read_req, open_req1.result, buf, sizeof(buf), -1, + NULL); + printf("read = %d\n", r); + ASSERT(r == 26); + ASSERT(read_req.result == 26); + ASSERT(memcmp(buf, + "test-buffer\n\0test-buffer\n\0", + sizeof("test-buffer\n\0test-buffer\n\0") - 1) == 0); + uv_fs_req_cleanup(&read_req); + + r = uv_fs_close(loop, &close_req, open_req1.result, NULL); + ASSERT(r != -1); + ASSERT(close_req.result != -1); + uv_fs_req_cleanup(&close_req); + + /* Cleanup */ + unlink("test_file"); + + return 0; +} diff --git a/src/rt/libuv/test/test-ipc.c b/src/rt/libuv/test/test-ipc.c index 5119b59bf5c3..0908879510fa 100644 --- a/src/rt/libuv/test/test-ipc.c +++ b/src/rt/libuv/test/test-ipc.c @@ -184,7 +184,7 @@ static void on_read(uv_pipe_t* pipe, ssize_t nread, uv_buf_t buf, } -TEST_IMPL(ipc) { +int run_ipc_test(const char* helper) { int r; uv_process_options_t options; uv_process_t process; @@ -199,7 +199,7 @@ TEST_IMPL(ipc) { ASSERT(r == 0); exepath[exepath_size] = '\0'; args[0] = exepath; - args[1] = "ipc_helper"; + args[1] = (char*)helper; args[2] = NULL; options.file = exepath; options.args = args; @@ -220,3 +220,59 @@ TEST_IMPL(ipc) { ASSERT(exit_cb_called == 1); return 0; } + + +TEST_IMPL(ipc_listen_before_write) { + return run_ipc_test("ipc_helper_listen_before_write"); +} + + +TEST_IMPL(ipc_listen_after_write) { + return run_ipc_test("ipc_helper_listen_after_write"); +} + + +#ifdef _WIN32 +TEST_IMPL(listen_with_simultaneous_accepts) { + uv_tcp_t server; + int r; + struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); + + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + r = uv_tcp_bind(&server, addr); + ASSERT(r == 0); + + r = uv_tcp_simultaneous_accepts(&server, 1); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); + ASSERT(r == 0); + ASSERT(server.reqs_pending == 32); + + return 0; +} + + +TEST_IMPL(listen_no_simultaneous_accepts) { + uv_tcp_t server; + int r; + struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); + + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + r = uv_tcp_bind(&server, addr); + ASSERT(r == 0); + + r = uv_tcp_simultaneous_accepts(&server, 0); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, SOMAXCONN, NULL); + ASSERT(r == 0); + ASSERT(server.reqs_pending == 1); + + return 0; +} +#endif diff --git a/src/rt/libuv/test/test-list.h b/src/rt/libuv/test/test-list.h index 19c999132676..9051fdb35ce6 100644 --- a/src/rt/libuv/test/test-list.h +++ b/src/rt/libuv/test/test-list.h @@ -21,13 +21,15 @@ TEST_DECLARE (tty) TEST_DECLARE (stdio_over_pipes) -TEST_DECLARE (ipc) +TEST_DECLARE (ipc_listen_before_write) +TEST_DECLARE (ipc_listen_after_write) TEST_DECLARE (tcp_ping_pong) TEST_DECLARE (tcp_ping_pong_v6) TEST_DECLARE (tcp_ref) TEST_DECLARE (tcp_ref2) TEST_DECLARE (pipe_ping_pong) TEST_DECLARE (delayed_accept) +TEST_DECLARE (multiple_listen) TEST_DECLARE (tcp_writealot) TEST_DECLARE (tcp_bind_error_addrinuse) TEST_DECLARE (tcp_bind_error_addrnotavail_1) @@ -39,6 +41,7 @@ TEST_DECLARE (tcp_listen_without_bind) TEST_DECLARE (tcp_close) TEST_DECLARE (tcp_flags) TEST_DECLARE (tcp_write_error) +TEST_DECLARE (tcp_write_to_half_open_connection) TEST_DECLARE (tcp_bind6_error_addrinuse) TEST_DECLARE (tcp_bind6_error_addrnotavail) TEST_DECLARE (tcp_bind6_error_fault) @@ -53,6 +56,7 @@ TEST_DECLARE (pipe_bind_error_addrinuse) TEST_DECLARE (pipe_bind_error_addrnotavail) TEST_DECLARE (pipe_bind_error_inval) TEST_DECLARE (pipe_listen_without_bind) +TEST_DECLARE (pipe_connect_bad_name) TEST_DECLARE (connection_fail) TEST_DECLARE (connection_fail_doesnt_auto_close) TEST_DECLARE (shutdown_eof) @@ -87,6 +91,7 @@ TEST_DECLARE (spawn_stdout) TEST_DECLARE (spawn_stdin) TEST_DECLARE (spawn_and_kill) TEST_DECLARE (spawn_and_ping) +TEST_DECLARE (kill) TEST_DECLARE (fs_file_noent) TEST_DECLARE (fs_file_async) TEST_DECLARE (fs_file_sync) @@ -99,10 +104,12 @@ TEST_DECLARE (fs_link) TEST_DECLARE (fs_symlink) TEST_DECLARE (fs_utime) TEST_DECLARE (fs_futime) +TEST_DECLARE (fs_file_open_append) TEST_DECLARE (fs_stat_missing_path) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_file) TEST_DECLARE (fs_event_watch_file_current_dir) +TEST_DECLARE (fs_event_no_callback_on_close) TEST_DECLARE (fs_readdir_empty_dir) TEST_DECLARE (fs_readdir_file) TEST_DECLARE (fs_open_dir) @@ -111,6 +118,8 @@ TEST_DECLARE (threadpool_queue_work_simple) TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) TEST_DECLARE (argument_escaping) TEST_DECLARE (environment_creation) +TEST_DECLARE (listen_with_simultaneous_accepts) +TEST_DECLARE (listen_no_simultaneous_accepts) #endif HELPER_DECLARE (tcp4_echo_server) HELPER_DECLARE (tcp6_echo_server) @@ -118,10 +127,12 @@ HELPER_DECLARE (pipe_echo_server) TASK_LIST_START + TEST_ENTRY (pipe_connect_bad_name) + TEST_ENTRY (tty) TEST_ENTRY (stdio_over_pipes) - TEST_ENTRY (ipc) - + TEST_ENTRY (ipc_listen_before_write) + TEST_ENTRY (ipc_listen_after_write) TEST_ENTRY (tcp_ref) @@ -138,6 +149,7 @@ TASK_LIST_START TEST_HELPER (pipe_ping_pong, pipe_echo_server) TEST_ENTRY (delayed_accept) + TEST_ENTRY (multiple_listen) TEST_ENTRY (tcp_writealot) TEST_HELPER (tcp_writealot, tcp4_echo_server) @@ -152,6 +164,7 @@ TASK_LIST_START TEST_ENTRY (tcp_close) TEST_ENTRY (tcp_flags) TEST_ENTRY (tcp_write_error) + TEST_ENTRY (tcp_write_to_half_open_connection) TEST_ENTRY (tcp_bind6_error_addrinuse) TEST_ENTRY (tcp_bind6_error_addrnotavail) @@ -222,10 +235,13 @@ TASK_LIST_START TEST_ENTRY (spawn_stdin) TEST_ENTRY (spawn_and_kill) TEST_ENTRY (spawn_and_ping) + TEST_ENTRY (kill) #ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) TEST_ENTRY (argument_escaping) TEST_ENTRY (environment_creation) + TEST_ENTRY (listen_with_simultaneous_accepts) + TEST_ENTRY (listen_no_simultaneous_accepts) #endif TEST_ENTRY (fs_file_noent) @@ -240,9 +256,11 @@ TASK_LIST_START TEST_ENTRY (fs_futime) TEST_ENTRY (fs_symlink) TEST_ENTRY (fs_stat_missing_path) + TEST_ENTRY (fs_file_open_append) TEST_ENTRY (fs_event_watch_dir) TEST_ENTRY (fs_event_watch_file) TEST_ENTRY (fs_event_watch_file_current_dir) + TEST_ENTRY (fs_event_no_callback_on_close) TEST_ENTRY (fs_readdir_empty_dir) TEST_ENTRY (fs_readdir_file) TEST_ENTRY (fs_open_dir) diff --git a/src/rt/libuv/test/test-multiple-listen.c b/src/rt/libuv/test/test-multiple-listen.c new file mode 100644 index 000000000000..0b5c887d69c5 --- /dev/null +++ b/src/rt/libuv/test/test-multiple-listen.c @@ -0,0 +1,102 @@ +/* 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 +#include + +static int connection_cb_called = 0; +static int close_cb_called = 0; +static int connect_cb_called = 0; +static uv_tcp_t server; +static uv_tcp_t client; + + +static void close_cb(uv_handle_t* handle) { + ASSERT(handle != NULL); + close_cb_called++; +} + + +static void connection_cb(uv_stream_t* tcp, int status) { + ASSERT(status == 0); + uv_close((uv_handle_t*)&server, close_cb); + connection_cb_called++; +} + + +static void start_server() { + struct sockaddr_in addr = uv_ip4_addr("0.0.0.0", TEST_PORT); + int r; + + r = uv_tcp_init(uv_default_loop(), &server); + ASSERT(r == 0); + + r = uv_tcp_bind(&server, addr); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, 128, connection_cb); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&server, 128, connection_cb); + ASSERT(r == 0); +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(req != NULL); + ASSERT(status == 0); + free(req); + uv_close((uv_handle_t*)&client, close_cb); + connect_cb_called++; +} + + +static void client_connect() { + struct sockaddr_in addr = uv_ip4_addr("127.0.0.1", TEST_PORT); + uv_connect_t* connect_req = malloc(sizeof *connect_req); + int r; + + ASSERT(connect_req != NULL); + + r = uv_tcp_init(uv_default_loop(), &client); + ASSERT(r == 0); + + r = uv_tcp_connect(connect_req, &client, addr, connect_cb); + ASSERT(r == 0); +} + + + +TEST_IMPL(multiple_listen) { + start_server(); + + client_connect(); + + uv_run(uv_default_loop()); + + ASSERT(connection_cb_called == 1); + ASSERT(connect_cb_called == 1); + ASSERT(close_cb_called == 2); + + return 0; +} diff --git a/src/rt/libuv/test/test-ping-pong.c b/src/rt/libuv/test/test-ping-pong.c index 0e59166c48d1..b73b4ce4d8ed 100644 --- a/src/rt/libuv/test/test-ping-pong.c +++ b/src/rt/libuv/test/test-ping-pong.c @@ -211,9 +211,8 @@ static void pipe_pinger_new() { /* We are never doing multiple reads/connects at a time anyway. */ /* so these handles can be pre-initialized. */ - r = uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME, + uv_pipe_connect(&pinger->connect_req, &pinger->stream.pipe, TEST_PIPENAME, pinger_on_connect); - ASSERT(!r); /* Synchronous connect callbacks are not allowed. */ ASSERT(pinger_on_connect_count == 0); diff --git a/src/rt/libuv/test/test-pipe-bind-error.c b/src/rt/libuv/test/test-pipe-bind-error.c index 3443f19dc872..b84d20f1eaf4 100644 --- a/src/rt/libuv/test/test-pipe-bind-error.c +++ b/src/rt/libuv/test/test-pipe-bind-error.c @@ -84,7 +84,7 @@ TEST_IMPL(pipe_bind_error_addrnotavail) { r = uv_pipe_bind(&server, BAD_PIPENAME); ASSERT(r == -1); - ASSERT(uv_last_error(uv_default_loop()).code == UV_EACCESS); + ASSERT(uv_last_error(uv_default_loop()).code == UV_EACCES); uv_close((uv_handle_t*)&server, close_cb); diff --git a/src/rt/libuv/test/test-pipe-connect-error.c b/src/rt/libuv/test/test-pipe-connect-error.c new file mode 100644 index 000000000000..2faa446148ef --- /dev/null +++ b/src/rt/libuv/test/test-pipe-connect-error.c @@ -0,0 +1,68 @@ +/* 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 +#include + + +#ifdef _WIN32 +# define BAD_PIPENAME "bad-pipe" +#else +# define BAD_PIPENAME "/path/to/unix/socket/that/really/should/not/be/there" +#endif + + +static int close_cb_called = 0; +static int connect_cb_called = 0; + + +static void close_cb(uv_handle_t* handle) { + ASSERT(handle != NULL); + close_cb_called++; +} + + +static void connect_cb(uv_connect_t* connect_req, int status) { + ASSERT(status == -1); + ASSERT(uv_last_error(uv_default_loop()).code == UV_ENOENT); + uv_close((uv_handle_t*)connect_req->handle, close_cb); + connect_cb_called++; +} + + +TEST_IMPL(pipe_connect_bad_name) { + uv_pipe_t client; + uv_connect_t req; + int r; + + r = uv_pipe_init(uv_default_loop(), &client, 0); + ASSERT(r == 0); + uv_pipe_connect(&req, &client, BAD_PIPENAME, connect_cb); + + uv_run(uv_default_loop()); + + ASSERT(close_cb_called == 1); + ASSERT(connect_cb_called == 1); + + return 0; +} diff --git a/src/rt/libuv/test/test-spawn.c b/src/rt/libuv/test/test-spawn.c index e73515858cee..192644bad261 100644 --- a/src/rt/libuv/test/test-spawn.c +++ b/src/rt/libuv/test/test-spawn.c @@ -33,6 +33,7 @@ static uv_process_options_t options; static char exepath[1024]; static size_t exepath_size = 1024; static char* args[3]; +static int no_term_signal; #define OUTPUT_SIZE 1024 static char output[OUTPUT_SIZE]; @@ -55,6 +56,8 @@ static void exit_cb(uv_process_t* process, int exit_status, int term_signal) { static void kill_cb(uv_process_t* process, int exit_status, int term_signal) { + uv_err_t err; + printf("exit_cb\n"); exit_cb_called++; #ifdef _WIN32 @@ -62,8 +65,14 @@ static void kill_cb(uv_process_t* process, int exit_status, int term_signal) { #else ASSERT(exit_status == 0); #endif - ASSERT(term_signal == 15); + ASSERT(no_term_signal || term_signal == 15); uv_close((uv_handle_t*)process, close_cb); + + /* Sending signum == 0 should check if the + * child process is still alive, not kill it. + */ + err = uv_kill(process->pid, 0); + ASSERT(err.code != UV_OK); } @@ -261,6 +270,39 @@ TEST_IMPL(spawn_and_ping) { } +TEST_IMPL(kill) { + int r; + uv_err_t err; + +#ifdef _WIN32 + no_term_signal = 1; +#endif + + init_process_options("spawn_helper4", kill_cb); + + r = uv_spawn(uv_default_loop(), &process, options); + ASSERT(r == 0); + + /* Sending signum == 0 should check if the + * child process is still alive, not kill it. + */ + err = uv_kill(process.pid, 0); + ASSERT(err.code == UV_OK); + + /* Kill the process. */ + err = uv_kill(process.pid, /* SIGTERM */ 15); + ASSERT(err.code == UV_OK); + + r = uv_run(uv_default_loop()); + ASSERT(r == 0); + + ASSERT(exit_cb_called == 1); + ASSERT(close_cb_called == 1); + + return 0; +} + + #ifdef _WIN32 TEST_IMPL(spawn_detect_pipe_name_collisions_on_windows) { int r; diff --git a/src/rt/libuv/test/test-stdio-over-pipes.c b/src/rt/libuv/test/test-stdio-over-pipes.c index fd96fc2d28a8..7c0a692bf927 100644 --- a/src/rt/libuv/test/test-stdio-over-pipes.c +++ b/src/rt/libuv/test/test-stdio-over-pipes.c @@ -22,6 +22,9 @@ #include "uv.h" #include "task.h" +#include +#include + static char exepath[1024]; static size_t exepath_size = 1024; diff --git a/src/rt/libuv/test/test-tcp-write-to-half-open-connection.c b/src/rt/libuv/test/test-tcp-write-to-half-open-connection.c new file mode 100644 index 000000000000..9e7f553ad24a --- /dev/null +++ b/src/rt/libuv/test/test-tcp-write-to-half-open-connection.c @@ -0,0 +1,139 @@ +/* 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 +#include +#include + +static void connection_cb(uv_stream_t* server, int status); +static void connect_cb(uv_connect_t* req, int status); +static void write_cb(uv_write_t* req, int status); +static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf); +static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size); + +static uv_tcp_t tcp_server; +static uv_tcp_t tcp_client; +static uv_tcp_t tcp_peer; /* client socket as accept()-ed by server */ +static uv_connect_t connect_req; +static uv_write_t write_req; + +static int write_cb_called; +static int read_cb_called; +static int read_eof_cb_called; + + +static void connection_cb(uv_stream_t* server, int status) { + int r; + uv_buf_t buf; + + ASSERT(server == (uv_stream_t*)&tcp_server); + ASSERT(status == 0); + + r = uv_tcp_init(server->loop, &tcp_peer); + ASSERT(r == 0); + + r = uv_accept(server, (uv_stream_t*)&tcp_peer); + ASSERT(r == 0); + + r = uv_read_start((uv_stream_t*)&tcp_peer, alloc_cb, read_cb); + ASSERT(r == 0); + + buf.base = "hello\n"; + buf.len = 6; + + r = uv_write(&write_req, (uv_stream_t*)&tcp_peer, &buf, 1, write_cb); + ASSERT(r == 0); +} + + +static uv_buf_t alloc_cb(uv_handle_t* handle, size_t suggested_size) { + static char slab[1024]; + return uv_buf_init(slab, sizeof slab); +} + + +static void read_cb(uv_stream_t* stream, ssize_t nread, uv_buf_t buf) { + if (nread == -1) { + fprintf(stderr, "read_cb error: %s\n", uv_err_name(uv_last_error(stream->loop))); + ASSERT(uv_last_error(stream->loop).code == UV_EOF); + + uv_close((uv_handle_t*)&tcp_server, NULL); + uv_close((uv_handle_t*)&tcp_peer, NULL); + + read_eof_cb_called++; + } + + read_cb_called++; +} + + +static void connect_cb(uv_connect_t* req, int status) { + ASSERT(req == &connect_req); + ASSERT(status == 0); + + /* Close the client. */ + uv_close((uv_handle_t*)&tcp_client, NULL); +} + + +static void write_cb(uv_write_t* req, int status) { + ASSERT(status == 0); + write_cb_called++; +} + + +TEST_IMPL(tcp_write_to_half_open_connection) { + uv_loop_t* loop; + int r; + + loop = uv_default_loop(); + ASSERT(loop != NULL); + + r = uv_tcp_init(loop, &tcp_server); + ASSERT(r == 0); + + r = uv_tcp_bind(&tcp_server, uv_ip4_addr("127.0.0.1", TEST_PORT)); + ASSERT(r == 0); + + r = uv_listen((uv_stream_t*)&tcp_server, 1, connection_cb); + ASSERT(r == 0); + + r = uv_tcp_init(loop, &tcp_client); + ASSERT(r == 0); + + r = uv_tcp_connect(&connect_req, + &tcp_client, + uv_ip4_addr("127.0.0.1", TEST_PORT), + connect_cb); + ASSERT(r == 0); + + r = uv_run(loop); + ASSERT(r == 0); + + ASSERT(write_cb_called > 0); + ASSERT(read_cb_called > 0); + ASSERT(read_eof_cb_called > 0); + + return 0; +} diff --git a/src/rt/libuv/uv.gyp b/src/rt/libuv/uv.gyp index b4ef0144048b..83129b5c956b 100644 --- a/src/rt/libuv/uv.gyp +++ b/src/rt/libuv/uv.gyp @@ -8,6 +8,15 @@ '_GNU_SOURCE', 'EIO_STACKSIZE=262144' ], + 'conditions': [ + ['OS=="solaris"', { + 'cflags': ['-pthreads'], + 'ldlags': ['-pthreads'], + }, { + 'cflags': ['-pthread'], + 'ldlags': ['-pthread'], + }], + ], }], ], }, @@ -29,6 +38,7 @@ 'HAVE_CONFIG_H' ], 'sources': [ + 'common.gypi', 'include/ares.h', 'include/ares_version.h', 'include/uv.h', @@ -120,6 +130,7 @@ 'src/win/async.c', 'src/win/cares.c', 'src/win/core.c', + 'src/win/dl.c', 'src/win/error.c', 'src/win/fs.c', 'src/win/fs-event.c', @@ -172,6 +183,7 @@ 'src/unix/tty.c', 'src/unix/stream.c', 'src/unix/cares.c', + 'src/unix/dl.c', 'src/unix/error.c', 'src/unix/process.c', 'src/unix/internal.h', @@ -280,9 +292,11 @@ 'test/test-ipc.c', 'test/test-list.h', 'test/test-loop-handles.c', + 'test/test-multiple-listen.c', 'test/test-pass-always.c', 'test/test-ping-pong.c', 'test/test-pipe-bind-error.c', + 'test/test-pipe-connect-error.c', 'test/test-ref.c', 'test/test-shutdown-eof.c', 'test/test-spawn.c', @@ -294,6 +308,7 @@ 'test/test-tcp-connect-error.c', 'test/test-tcp-connect6-error.c', 'test/test-tcp-write-error.c', + 'test/test-tcp-write-to-half-open-connection.c', 'test/test-tcp-writealot.c', 'test/test-threadpool.c', 'test/test-timer-again.c', @@ -313,11 +328,10 @@ 'libraries': [ 'ws2_32.lib' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], - 'ldflags': [ '-pthread' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', - ] + ], }], [ 'OS=="solaris"', { # make test-fs.c compile, needs _POSIX_C_SOURCE 'defines': [ @@ -365,7 +379,6 @@ 'libraries': [ 'ws2_32.lib' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], - 'ldflags': [ '-pthread' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h',