diff --git a/deps/uv/.gitignore b/deps/uv/.gitignore index 29b70ae0af..d6c65dbae2 100644 --- a/deps/uv/.gitignore +++ b/deps/uv/.gitignore @@ -7,6 +7,7 @@ *.suo core vgcore.* +.buildstamp /libuv.so /libuv.dylib @@ -14,12 +15,12 @@ vgcore.* /out/ /build/gyp -/test/run-tests -/test/run-tests.exe -/test/run-tests.dSYM -/test/run-benchmarks -/test/run-benchmarks.exe -/test/run-benchmarks.dSYM +/run-tests +/run-tests.exe +/run-tests.dSYM +/run-benchmarks +/run-benchmarks.exe +/run-benchmarks.dSYM *.sln *.vcproj diff --git a/deps/uv/Makefile b/deps/uv/Makefile index ef2b352583..069c67e542 100644 --- a/deps/uv/Makefile +++ b/deps/uv/Makefile @@ -18,51 +18,36 @@ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. -uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not') +SRCDIR ?= $(CURDIR) -ifdef MSVC -uname_S := MINGW -endif - -CPPFLAGS += -Iinclude -Iinclude/uv-private - -ifeq (Darwin,$(uname_S)) -SOEXT = dylib -else -SOEXT = so -endif - -ifneq (,$(findstring MINGW,$(uname_S))) -include config-mingw.mk -else -include config-unix.mk -endif - -TESTS=test/blackhole-server.c test/echo-server.c test/test-*.c -BENCHMARKS=test/blackhole-server.c test/echo-server.c test/dns-server.c test/benchmark-*.c - -all: libuv.a +ifeq (,$(builddir_name)) -test/run-tests$(E): test/run-tests.c test/runner.c $(RUNNER_SRC) $(TESTS) libuv.$(SOEXT) - $(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS) +VPATH := $(SRCDIR) +include $(SRCDIR)/build.mk -test/run-benchmarks$(E): test/run-benchmarks.c test/runner.c $(RUNNER_SRC) $(BENCHMARKS) libuv.$(SOEXT) - $(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS) +else # Out of tree build. -test/echo.o: test/echo.c test/echo.h +# Drop all built-in rules. +.SUFFIXES: +.PHONY: $(builddir_name) +$(builddir_name): $(builddir_name)/.buildstamp + $(MAKE) -C $@ -f $(CURDIR)/Makefile $(MAKECMDGOALS) \ + SRCDIR=$(CURDIR) builddir_name= -.PHONY: clean clean-platform distclean distclean-platform test bench +$(builddir_name)/.buildstamp: + mkdir -p $(dir $@) + touch $@ +# Add no-op rules for Makefiles to stop make from trying to rebuild them. +Makefile:: ; +%.mk:: ; -test: test/run-tests$(E) - $< +# Turn everything else into a no-op rule that depends on the build directory. +%:: $(builddir_name) ; -bench: test/run-benchmarks$(E) - $< +.PHONY: clean +clean: + $(RM) -fr $(builddir_name) -clean: clean-platform - $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) - -distclean: distclean-platform - $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) +endif diff --git a/deps/uv/README.md b/deps/uv/README.md index b4cb4849fd..cdddbd2a4b 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -62,7 +62,15 @@ To build via Makefile simply execute: make -To build with Visual Studio run the vcbuilds.bat file which will +MinGW users should run this instead: + + make OS=mingw + +Out-of-tree builds are supported: + + make builddir_name=/path/to/builddir + +To build with Visual Studio run the vcbuild.bat file which will checkout the GYP code into build/gyp and generate the uv.sln and related files. @@ -91,6 +99,9 @@ Macintosh users run ./gyp_uv -f xcode xcodebuild -project uv.xcodeproj -configuration Release -target All +Note for UNIX users: compile your project with `-D_LARGEFILE_SOURCE` and +`-D_FILE_OFFSET_BITS=64`. GYP builds take care of that automatically. + Note for Linux users: compile your project with `-D_GNU_SOURCE` when you include `uv.h`. GYP builds take care of that automatically. If you use autotools, add a `AC_GNU_SOURCE` declaration to your `configure.ac`. diff --git a/deps/uv/build.mk b/deps/uv/build.mk new file mode 100644 index 0000000000..88de949dd3 --- /dev/null +++ b/deps/uv/build.mk @@ -0,0 +1,163 @@ +# 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. + +OS ?= $(shell sh -c 'uname -s | tr "[A-Z]" "[a-z]"') + +CPPFLAGS += -I$(SRCDIR)/include -I$(SRCDIR)/include/uv-private + +ifeq (darwin,$(OS)) +SOEXT = dylib +else +SOEXT = so +endif + +ifneq (,$(findstring mingw,$(OS))) +include $(SRCDIR)/config-mingw.mk +else +include $(SRCDIR)/config-unix.mk +endif + +BENCHMARKS= \ + test/benchmark-async-pummel.o \ + test/benchmark-async.o \ + test/benchmark-fs-stat.o \ + test/benchmark-getaddrinfo.o \ + test/benchmark-loop-count.o \ + test/benchmark-million-async.o \ + test/benchmark-million-timers.o \ + test/benchmark-multi-accept.o \ + test/benchmark-ping-pongs.o \ + test/benchmark-pound.o \ + test/benchmark-pump.o \ + test/benchmark-sizes.o \ + test/benchmark-spawn.o \ + test/benchmark-tcp-write-batch.o \ + test/benchmark-thread.o \ + test/benchmark-udp-pummel.o \ + test/blackhole-server.o \ + test/dns-server.o \ + test/echo-server.o \ + +TESTS= \ + test/blackhole-server.o \ + test/dns-server.o \ + test/echo-server.o \ + test/test-active.o \ + test/test-async.o \ + test/test-barrier.o \ + test/test-callback-order.o \ + test/test-callback-stack.o \ + test/test-condvar.o \ + test/test-connection-fail.o \ + test/test-cwd-and-chdir.o \ + test/test-delayed-accept.o \ + test/test-dlerror.o \ + test/test-embed.o \ + test/test-error.o \ + test/test-fail-always.o \ + test/test-fs.o \ + test/test-fs-event.o \ + test/test-fs-poll.o \ + test/test-getaddrinfo.o \ + test/test-get-currentexe.o \ + test/test-get-loadavg.o \ + test/test-get-memory.o \ + test/test-getsockname.o \ + test/test-hrtime.o \ + test/test-idle.o \ + test/test-ipc.o \ + test/test-ipc-send-recv.o \ + test/test-loop-handles.o \ + test/test-multiple-listen.o \ + test/test-mutexes.o \ + test/test-pass-always.o \ + test/test-ping-pong.o \ + test/test-pipe-bind-error.o \ + test/test-pipe-connect-error.o \ + test/test-platform-output.o \ + test/test-poll.o \ + test/test-poll-close.o \ + test/test-process-title.o \ + test/test-ref.o \ + test/test-run-nowait.o \ + test/test-run-once.o \ + test/test-semaphore.o \ + test/test-shutdown-close.o \ + test/test-shutdown-eof.o \ + test/test-signal.o \ + test/test-signal-multiple-loops.o \ + test/test-spawn.o \ + test/test-stdio-over-pipes.o \ + test/test-tcp-bind6-error.o \ + test/test-tcp-bind-error.o \ + test/test-tcp-close.o \ + test/test-tcp-close-while-connecting.o \ + test/test-tcp-connect6-error.o \ + test/test-tcp-connect-error-after-write.o \ + test/test-tcp-connect-error.o \ + test/test-tcp-connect-timeout.o \ + test/test-tcp-flags.o \ + test/test-tcp-open.o \ + test/test-tcp-read-stop.o \ + test/test-tcp-shutdown-after-write.o \ + test/test-tcp-unexpected-read.o \ + test/test-tcp-writealot.o \ + test/test-tcp-write-to-half-open-connection.o \ + test/test-thread.o \ + test/test-threadpool.o \ + test/test-threadpool-cancel.o \ + test/test-timer-again.o \ + test/test-timer.o \ + test/test-tty.o \ + test/test-udp-dgram-too-big.o \ + test/test-udp-ipv6.o \ + test/test-udp-multicast-join.o \ + test/test-udp-multicast-ttl.o \ + test/test-udp-open.o \ + test/test-udp-options.o \ + test/test-udp-send-and-recv.o \ + test/test-util.o \ + test/test-walk-handles.o \ + +all: libuv.a + +run-tests$(E): test/run-tests.o test/runner.o $(RUNNER_SRC) $(TESTS) libuv.$(SOEXT) + $(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS) + +run-benchmarks$(E): test/run-benchmarks.o test/runner.o $(RUNNER_SRC) $(BENCHMARKS) libuv.$(SOEXT) + $(CC) $(CPPFLAGS) $(RUNNER_CFLAGS) -o $@ $^ $(RUNNER_LIBS) $(RUNNER_LDFLAGS) + +test/echo.o: test/echo.c test/echo.h + + +.PHONY: clean clean-platform distclean distclean-platform test bench + + +test: run-tests$(E) + $(CURDIR)/$< + +bench: run-benchmarks$(E) + $(CURDIR)/$< + +clean: clean-platform + $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) + +distclean: distclean-platform + $(RM) -f *.a *.so test/run-tests$(E) test/run-benchmarks$(E) diff --git a/deps/uv/checksparse.sh b/deps/uv/checksparse.sh index 3a19d161b5..f06b27d28f 100755 --- a/deps/uv/checksparse.sh +++ b/deps/uv/checksparse.sh @@ -195,10 +195,10 @@ Linux) SPARSE_FLAGS="$SPARSE_FLAGS -D__linux__=1" SOURCES="$SOURCES include/uv-private/uv-linux.h - src/unix/linux/inotify.c - src/unix/linux/linux-core.c - src/unix/linux/syscalls.c - src/unix/linux/syscalls.h" + src/unix/linux-inotify.c + src/unix/linux-core.c + src/unix/linux-syscalls.c + src/unix/linux-syscalls.h" ;; NetBSD) SPARSE_FLAGS="$SPARSE_FLAGS -D__NetBSD__=1" diff --git a/deps/uv/config-mingw.mk b/deps/uv/config-mingw.mk index 662831dcac..9906a1c621 100644 --- a/deps/uv/config-mingw.mk +++ b/deps/uv/config-mingw.mk @@ -27,7 +27,7 @@ E=.exe CFLAGS=$(CPPFLAGS) -g --std=gnu89 -D_WIN32_WINNT=0x0600 LDFLAGS=-lm -WIN_SRCS=$(wildcard src/win/*.c) +WIN_SRCS=$(wildcard $(SRCDIR)/src/win/*.c) WIN_OBJS=$(WIN_SRCS:.c=.o) RUNNER_CFLAGS=$(CFLAGS) -D_GNU_SOURCE # Need _GNU_SOURCE for strdup? diff --git a/deps/uv/config-unix.mk b/deps/uv/config-unix.mk index 66c74ee19f..1a4bf9b50e 100644 --- a/deps/uv/config-unix.mk +++ b/deps/uv/config-unix.mk @@ -21,15 +21,15 @@ E= CSTDFLAG=--std=c89 -pedantic -Wall -Wextra -Wno-unused-parameter CFLAGS += -g -CPPFLAGS += -Isrc +CPPFLAGS += -I$(SRCDIR)/src LDFLAGS=-lm CPPFLAGS += -D_LARGEFILE_SOURCE CPPFLAGS += -D_FILE_OFFSET_BITS=64 RUNNER_SRC=test/runner-unix.c -RUNNER_CFLAGS=$(CFLAGS) -Itest -RUNNER_LDFLAGS=-L"$(PWD)" -luv -Xlinker -rpath -Xlinker "$(PWD)" +RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test +RUNNER_LDFLAGS=-L"$(CURDIR)" -luv -Xlinker -rpath -Xlinker "$(CURDIR)" OBJS += src/unix/async.o OBJS += src/unix/core.o @@ -54,7 +54,7 @@ OBJS += src/fs-poll.o OBJS += src/uv-common.o OBJS += src/inet.o -ifeq (SunOS,$(uname_S)) +ifeq (sunos,$(OS)) CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket # Library dependencies are not transitive. @@ -62,13 +62,13 @@ RUNNER_LDFLAGS += $(LDFLAGS) OBJS += src/unix/sunos.o endif -ifeq (AIX,$(uname_S)) -CPPFLAGS += -Isrc/ares/config_aix -D_ALL_SOURCE -D_XOPEN_SOURCE=500 +ifeq (aix,$(OS)) +CPPFLAGS += -D_ALL_SOURCE -D_XOPEN_SOURCE=500 LDFLAGS+= -lperfstat OBJS += src/unix/aix.o endif -ifeq (Darwin,$(uname_S)) +ifeq (darwin,$(OS)) CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 LDFLAGS+=-framework CoreServices -dynamiclib -install_name "@rpath/libuv.dylib" SOEXT = dylib @@ -77,78 +77,82 @@ OBJS += src/unix/kqueue.o OBJS += src/unix/fsevents.o endif -ifeq (Linux,$(uname_S)) +ifeq (linux,$(OS)) CSTDFLAG += -D_GNU_SOURCE LDFLAGS+=-ldl -lrt RUNNER_CFLAGS += -D_GNU_SOURCE -OBJS += src/unix/linux/linux-core.o \ - src/unix/linux/inotify.o \ - src/unix/linux/syscalls.o +OBJS += src/unix/linux-core.o \ + src/unix/linux-inotify.o \ + src/unix/linux-syscalls.o endif -ifeq (FreeBSD,$(uname_S)) +ifeq (freebsd,$(OS)) LDFLAGS+=-lkvm OBJS += src/unix/freebsd.o OBJS += src/unix/kqueue.o endif -ifeq (DragonFly,$(uname_S)) +ifeq (dragonfly,$(OS)) LDFLAGS+=-lkvm OBJS += src/unix/freebsd.o OBJS += src/unix/kqueue.o endif -ifeq (NetBSD,$(uname_S)) +ifeq (netbsd,$(OS)) LDFLAGS+=-lkvm OBJS += src/unix/netbsd.o OBJS += src/unix/kqueue.o endif -ifeq (OpenBSD,$(uname_S)) +ifeq (openbsd,$(OS)) LDFLAGS+=-lkvm OBJS += src/unix/openbsd.o OBJS += src/unix/kqueue.o endif -ifneq (,$(findstring CYGWIN,$(uname_S))) +ifneq (,$(findstring cygwin,$(OS))) # We drop the --std=c89, it hides CLOCK_MONOTONIC on cygwin CSTDFLAG = -D_GNU_SOURCE LDFLAGS+= OBJS += src/unix/cygwin.o endif -ifeq (SunOS,$(uname_S)) +ifeq (sunos,$(OS)) RUNNER_LDFLAGS += -pthreads else RUNNER_LDFLAGS += -pthread endif -OBJDIR := out -ifeq ($(MAKECMDGOALS), test) - OBJDIR := $(OBJDIR)/test -endif - -OBJS := $(addprefix $(OBJDIR)/,$(OBJS)) - libuv.a: $(OBJS) $(AR) rcs $@ $^ libuv.$(SOEXT): override CFLAGS += -fPIC -libuv.$(SOEXT): $(OBJS) +libuv.$(SOEXT): $(OBJS:%.o=%.pic.o) $(CC) -shared -o $@ $^ $(LDFLAGS) -$(OBJDIR)/src/unix/%.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h - @mkdir -p $(dir $@) +include/uv-private/uv-unix.h: \ + include/uv-private/uv-bsd.h \ + include/uv-private/uv-darwin.h \ + include/uv-private/uv-linux.h \ + include/uv-private/uv-sunos.h + +src/unix/internal.h: src/unix/linux-syscalls.h + +src/.buildstamp src/unix/.buildstamp test/.buildstamp: + mkdir -p $(dir $@) + touch $@ + +src/unix/%.o src/unix/%.pic.o: src/unix/%.c include/uv.h include/uv-private/uv-unix.h src/unix/internal.h src/unix/.buildstamp + $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ + +src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ -$(OBJDIR)/src/%.o: src/%.c include/uv.h include/uv-private/uv-unix.h - @mkdir -p $(dir $@) +test/%.o: test/%.c include/uv.h test/.buildstamp $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ clean-platform: - -rm -rf $(OBJDIR) -rm -f libuv.a libuv.$(SOEXT) test/run-{tests,benchmarks}.dSYM distclean-platform: - -rm -rf $(OBJDIR) -rm -f libuv.a libuv.$(SOEXT) test/run-{tests,benchmarks}.dSYM diff --git a/deps/uv/include/uv-private/uv-bsd.h b/deps/uv/include/uv-private/uv-bsd.h index fc253aa89b..2d72b3d771 100644 --- a/deps/uv/include/uv-private/uv-bsd.h +++ b/deps/uv/include/uv-private/uv-bsd.h @@ -25,4 +25,10 @@ #define UV_PLATFORM_FS_EVENT_FIELDS \ uv__io_t event_watcher; \ +#define UV_IO_PRIVATE_PLATFORM_FIELDS \ + int rcount; \ + int wcount; \ + +#define UV_HAVE_KQUEUE 1 + #endif /* UV_BSD_H */ diff --git a/deps/uv/include/uv-private/uv-darwin.h b/deps/uv/include/uv-private/uv-darwin.h index f11c12aeea..e861cbab9a 100644 --- a/deps/uv/include/uv-private/uv-darwin.h +++ b/deps/uv/include/uv-private/uv-darwin.h @@ -30,6 +30,10 @@ # define UV_PLATFORM_SEM_T semaphore_t #endif +#define UV_IO_PRIVATE_PLATFORM_FIELDS \ + int rcount; \ + int wcount; \ + #define UV_PLATFORM_LOOP_FIELDS \ uv_thread_t cf_thread; \ void* cf_cb; \ @@ -52,4 +56,6 @@ #define UV_STREAM_PRIVATE_PLATFORM_FIELDS \ void* select; \ +#define UV_HAVE_KQUEUE 1 + #endif /* UV_DARWIN_H */ diff --git a/deps/uv/include/uv-private/uv-unix.h b/deps/uv/include/uv-private/uv-unix.h index 6d2efbe202..fe32c4b8ac 100644 --- a/deps/uv/include/uv-private/uv-unix.h +++ b/deps/uv/include/uv-private/uv-unix.h @@ -41,9 +41,29 @@ #include #include +#if defined(__linux__) +# include "uv-linux.h" +#elif defined(__sun) +# include "uv-sunos.h" +#elif defined(__APPLE__) +# include "uv-darwin.h" +#elif defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__OpenBSD__) || \ + defined(__NetBSD__) +# include "uv-bsd.h" +#endif + struct uv__io_s; struct uv_loop_s; +#ifndef UV_IO_PRIVATE_PLATFORM_FIELDS +# define UV_IO_PRIVATE_PLATFORM_FIELDS /* empty */ +#endif + +#define UV_IO_PRIVATE_FIELDS \ + UV_IO_PRIVATE_PLATFORM_FIELDS \ + typedef void (*uv__io_cb)(struct uv_loop_s* loop, struct uv__io_s* w, unsigned int events); @@ -56,6 +76,7 @@ struct uv__io_s { unsigned int pevents; /* Pending event mask i.e. mask at next tick. */ unsigned int events; /* Current event mask. */ int fd; + UV_IO_PRIVATE_FIELDS }; struct uv__work { @@ -65,19 +86,6 @@ struct uv__work { ngx_queue_t wq; }; -#if defined(__linux__) -# include "uv-linux.h" -#elif defined(__sun) -# include "uv-sunos.h" -#elif defined(__APPLE__) -# include "uv-darwin.h" -#elif defined(__DragonFly__) || \ - defined(__FreeBSD__) || \ - defined(__OpenBSD__) || \ - defined(__NetBSD__) -# include "uv-bsd.h" -#endif - #ifndef UV_PLATFORM_SEM_T # define UV_PLATFORM_SEM_T sem_t #endif @@ -170,6 +178,7 @@ typedef struct { uv__io_t signal_io_watcher; \ uv_signal_t child_watcher; \ int emfile_fd; \ + uint64_t timer_counter; \ UV_PLATFORM_LOOP_FIELDS \ #define UV_REQ_TYPE_PRIVATE /* empty */ @@ -257,7 +266,8 @@ typedef struct { } tree_entry; \ uv_timer_cb timer_cb; \ uint64_t timeout; \ - uint64_t repeat; + uint64_t repeat; \ + uint64_t start_id; #define UV_GETADDRINFO_PRIVATE_FIELDS \ struct uv__work work_req; \ @@ -285,7 +295,6 @@ typedef struct { double atime; \ double mtime; \ struct uv__work work_req; \ - struct stat statbuf; \ #define UV_WORK_PRIVATE_FIELDS \ struct uv__work work_req; diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index 8c048bef51..574aa8f268 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -277,7 +277,7 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* The loop's I/O completion port */ \ HANDLE iocp; \ /* The current time according to the event loop. in msecs. */ \ - int64_t time; \ + uint64_t time; \ /* Tail of a single-linked circular queue of pending reqs. If the queue */ \ /* is empty, tail_ is NULL. If there is only one item, */ \ /* tail_->next_req == tail_ */ \ @@ -302,7 +302,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* Counter to keep track of active tcp streams */ \ unsigned int active_tcp_streams; \ /* Counter to keep track of active udp streams */ \ - unsigned int active_udp_streams; + unsigned int active_udp_streams; \ + /* Counter to started timer */ \ + uint64_t timer_counter; #define UV_REQ_TYPE_PRIVATE \ /* TODO: remove the req suffix */ \ @@ -485,8 +487,9 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); #define UV_TIMER_PRIVATE_FIELDS \ RB_ENTRY(uv_timer_s) tree_entry; \ - int64_t due; \ - int64_t repeat; \ + uint64_t due; \ + uint64_t repeat; \ + uint64_t start_id; \ uv_timer_cb timer_cb; #define UV_ASYNC_PRIVATE_FIELDS \ @@ -552,7 +555,6 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); size_t length; \ int64_t offset; \ }; \ - struct _stati64 stat; \ struct { \ double atime; \ double mtime; \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index cfe297d636..4d6a2e80cd 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -266,7 +266,7 @@ UV_EXTERN void uv_ref(uv_handle_t*); UV_EXTERN void uv_unref(uv_handle_t*); UV_EXTERN void uv_update_time(uv_loop_t*); -UV_EXTERN int64_t uv_now(uv_loop_t*); +UV_EXTERN uint64_t uv_now(uv_loop_t*); /* * Get backend file descriptor. Only kqueue, epoll and event ports are @@ -1161,7 +1161,7 @@ struct uv_timer_s { UV_TIMER_PRIVATE_FIELDS }; -UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* timer); +UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* handle); /* * Start the timer. `timeout` and `repeat` are in milliseconds. @@ -1170,24 +1170,20 @@ UV_EXTERN int uv_timer_init(uv_loop_t*, uv_timer_t* timer); * * If repeat is non-zero, the callback fires first after timeout milliseconds * and then repeatedly after repeat milliseconds. - * - * timeout and repeat are signed integers but that will change in a future - * version of libuv. Don't pass in negative values, you'll get a nasty surprise - * when that change becomes effective. */ -UV_EXTERN int uv_timer_start(uv_timer_t* timer, +UV_EXTERN int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, - int64_t timeout, - int64_t repeat); + uint64_t timeout, + uint64_t repeat); -UV_EXTERN int uv_timer_stop(uv_timer_t* timer); +UV_EXTERN int uv_timer_stop(uv_timer_t* handle); /* * 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. */ -UV_EXTERN int uv_timer_again(uv_timer_t* timer); +UV_EXTERN int uv_timer_again(uv_timer_t* handle); /* * Set the repeat value in milliseconds. Note that if the repeat value is set @@ -1195,9 +1191,9 @@ UV_EXTERN int uv_timer_again(uv_timer_t* timer); * non-repeating before, it will have been stopped. If it was repeating, then * the old repeat value will have been used to schedule the next timeout. */ -UV_EXTERN void uv_timer_set_repeat(uv_timer_t* timer, int64_t repeat); +UV_EXTERN void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat); -UV_EXTERN int64_t uv_timer_get_repeat(uv_timer_t* timer); +UV_EXTERN uint64_t uv_timer_get_repeat(const uv_timer_t* handle); /* @@ -1515,6 +1511,7 @@ struct uv_fs_s { void* ptr; const char* path; uv_err_code errorno; + uv_statbuf_t statbuf; /* Stores the result of uv_fs_stat and uv_fs_fstat. */ UV_FS_PRIVATE_FIELDS }; @@ -1878,12 +1875,6 @@ UV_EXTERN void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex); * 1. callers should be prepared to deal with spurious wakeups. * 2. the granularity of timeout on Windows is never less than one millisecond. * 3. uv_cond_timedwait takes a relative timeout, not an absolute time. - * 4. the precision of timeout on OSX is never less than one microsecond. - * Here is the reason. - * OSX doesn't support CLOCK_MONOTONIC nor pthread_condattr_setclock() - * (see man pthread_cond_init on OSX). - * An example in man pthread_cond_timedwait on OSX uses gettimeofday() - * and its resolution is a microsecond. */ UV_EXTERN int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout); diff --git a/deps/uv/src/fs-poll.c b/deps/uv/src/fs-poll.c index 8d736caba9..ad27f18432 100644 --- a/deps/uv/src/fs-poll.c +++ b/deps/uv/src/fs-poll.c @@ -158,7 +158,7 @@ static void poll_cb(uv_fs_t* req) { goto out; } - statbuf = req->ptr; + statbuf = &req->statbuf; if (ctx->busy_polling != 0) if (ctx->busy_polling < 0 || !statbuf_eq(&ctx->statbuf, statbuf)) diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c index 6bf3f7b274..d59927729b 100644 --- a/deps/uv/src/unix/core.c +++ b/deps/uv/src/unix/core.c @@ -306,7 +306,7 @@ void uv_update_time(uv_loop_t* loop) { } -int64_t uv_now(uv_loop_t* loop) { +uint64_t uv_now(uv_loop_t* loop) { return loop->time; } @@ -595,6 +595,11 @@ void uv__io_init(uv__io_t* w, uv__io_cb cb, int fd) { w->fd = fd; w->events = 0; w->pevents = 0; + +#if defined(UV_HAVE_KQUEUE) + w->rcount = 0; + w->wcount = 0; +#endif /* defined(UV_HAVE_KQUEUE) */ } diff --git a/deps/uv/src/unix/fs.c b/deps/uv/src/unix/fs.c index 6b7ac6c5a1..f9181df127 100644 --- a/deps/uv/src/unix/fs.c +++ b/deps/uv/src/unix/fs.c @@ -187,11 +187,7 @@ static ssize_t uv__fs_read(uv_fs_t* req) { } -#if defined(__APPLE__) || defined(__OpenBSD__) -static int uv__fs_readdir_filter(struct dirent* dent) { -#else static int uv__fs_readdir_filter(const struct dirent* dent) { -#endif return strcmp(dent->d_name, ".") != 0 && strcmp(dent->d_name, "..") != 0; } diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 2c61f910e6..d6d2e45fd1 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -32,7 +32,7 @@ #endif #if defined(__linux__) -# include "linux/syscalls.h" +# include "linux-syscalls.h" #endif /* __linux__ */ #if defined(__sun) diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 2ab0854beb..fa09070961 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -197,9 +197,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { revents = 0; if (ev->filter == EVFILT_READ) { - if (w->events & UV__POLLIN) + if (w->events & UV__POLLIN) { revents |= UV__POLLIN; - else { + w->rcount = ev->data; + } else { /* TODO batch up */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); @@ -210,9 +211,10 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { } if (ev->filter == EVFILT_WRITE) { - if (w->events & UV__POLLOUT) + if (w->events & UV__POLLOUT) { revents |= UV__POLLOUT; - else { + w->wcount = ev->data; + } else { /* TODO batch up */ struct kevent events[1]; EV_SET(events + 0, fd, ev->filter, EV_DELETE, 0, 0, 0); diff --git a/deps/uv/src/unix/linux/linux-core.c b/deps/uv/src/unix/linux-core.c similarity index 98% rename from deps/uv/src/unix/linux/linux-core.c rename to deps/uv/src/unix/linux-core.c index b591314ff0..7c01d78015 100644 --- a/deps/uv/src/unix/linux/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -19,7 +19,7 @@ */ #include "uv.h" -#include "../internal.h" +#include "internal.h" #include #include @@ -218,11 +218,12 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w = loop->watchers[fd]; if (w == NULL) { - /* File descriptor that we've stopped watching, disarm it. */ - if (uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe)) - if (errno != EBADF && errno != ENOENT) - abort(); - + /* File descriptor that we've stopped watching, disarm it. + * + * Ignore all errors because we may be racing with another thread + * when the file descriptor is closed. + */ + uv__epoll_ctl(loop->backend_fd, UV__EPOLL_CTL_DEL, fd, pe); continue; } diff --git a/deps/uv/src/unix/linux/inotify.c b/deps/uv/src/unix/linux-inotify.c similarity index 99% rename from deps/uv/src/unix/linux/inotify.c rename to deps/uv/src/unix/linux-inotify.c index 2edf221c14..108345aa84 100644 --- a/deps/uv/src/unix/linux/inotify.c +++ b/deps/uv/src/unix/linux-inotify.c @@ -20,8 +20,7 @@ #include "uv.h" #include "tree.h" -#include "../internal.h" -#include "syscalls.h" +#include "internal.h" #include #include diff --git a/deps/uv/src/unix/linux/syscalls.c b/deps/uv/src/unix/linux-syscalls.c similarity index 99% rename from deps/uv/src/unix/linux/syscalls.c rename to deps/uv/src/unix/linux-syscalls.c index 870763be2e..06cc5943cf 100644 --- a/deps/uv/src/unix/linux/syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -19,7 +19,7 @@ * IN THE SOFTWARE. */ -#include "syscalls.h" +#include "linux-syscalls.h" #include #include #include diff --git a/deps/uv/src/unix/linux/syscalls.h b/deps/uv/src/unix/linux-syscalls.h similarity index 88% rename from deps/uv/src/unix/linux/syscalls.h rename to deps/uv/src/unix/linux-syscalls.h index 195a981dec..ba44974a06 100644 --- a/deps/uv/src/unix/linux/syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -30,8 +30,27 @@ #include #include -#define UV__O_NONBLOCK 0x800 -#define UV__O_CLOEXEC 0x80000 +#if defined(__alpha__) +# define UV__O_CLOEXEC 0x200000 +#elif defined(__hppa__) +# define UV__O_CLOEXEC 0x200000 +#elif defined(__sparc__) +# define UV__O_CLOEXEC 0x400000 +#else +# define UV__O_CLOEXEC 0x80000 +#endif + +#if defined(__alpha__) +# define UV__O_NONBLOCK 0x4 +#elif defined(__hppa__) +# define UV__O_NONBLOCK 0x10004 +#elif defined(__mips__) +# define UV__O_NONBLOCK 0x80 +#elif defined(__sparc__) +# define UV__O_NONBLOCK 0x4000 +#else +# define UV__O_NONBLOCK 0x800 +#endif #define UV__EFD_CLOEXEC UV__O_CLOEXEC #define UV__EFD_NONBLOCK UV__O_NONBLOCK diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index 5672abe9f0..9935310749 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -57,6 +57,8 @@ int uv__loop_init(uv_loop_t* loop, int default_loop) { loop->backend_fd = -1; loop->emfile_fd = -1; + loop->timer_counter = 0; + if (uv__platform_loop_init(loop, default_loop)) return -1; diff --git a/deps/uv/src/unix/signal.c b/deps/uv/src/unix/signal.c index d3ab6035bf..f7fd2e5e4f 100644 --- a/deps/uv/src/unix/signal.c +++ b/deps/uv/src/unix/signal.c @@ -136,7 +136,9 @@ inline static uv_signal_t* uv__signal_first_handle(int signum) { static void uv__signal_handler(int signum) { uv__signal_msg_t msg; uv_signal_t* handle; + int saved_errno; + saved_errno = errno; memset(&msg, 0, sizeof msg); uv__signal_lock(); @@ -165,6 +167,7 @@ static void uv__signal_handler(int signum) { } uv__signal_unlock(); + errno = saved_errno; } diff --git a/deps/uv/src/unix/stream.c b/deps/uv/src/unix/stream.c index fbe4bd1161..00e451c561 100644 --- a/deps/uv/src/unix/stream.c +++ b/deps/uv/src/unix/stream.c @@ -484,6 +484,13 @@ static int uv__emfile_trick(uv_loop_t* loop, int accept_fd) { } +#if defined(UV_HAVE_KQUEUE) +# define UV_DEC_BACKLOG(w) w->rcount--; +#else +# define UV_DEC_BACKLOG(w) /* no-op */ +#endif /* defined(UV_HAVE_KQUEUE) */ + + void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { static int use_emfile_trick = -1; uv_stream_t* stream; @@ -503,6 +510,10 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { */ while (uv__stream_fd(stream) != -1) { assert(stream->accepted_fd == -1); +#if defined(UV_HAVE_KQUEUE) + if (w->rcount <= 0) + return; +#endif /* defined(UV_HAVE_KQUEUE) */ fd = uv__accept(uv__stream_fd(stream)); if (fd == -1) { @@ -514,6 +525,7 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { return; /* Not an error. */ case ECONNABORTED: + UV_DEC_BACKLOG(w) continue; /* Ignore. */ case EMFILE: @@ -525,8 +537,10 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { if (use_emfile_trick) { SAVE_ERRNO(r = uv__emfile_trick(loop, uv__stream_fd(stream))); - if (r == 0) + if (r == 0) { + UV_DEC_BACKLOG(w) continue; + } } /* Fall through. */ @@ -538,6 +552,8 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { } } + UV_DEC_BACKLOG(w) + stream->accepted_fd = fd; stream->connection_cb(stream, 0); @@ -556,6 +572,9 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { } +#undef UV_DEC_BACKLOG + + int uv_accept(uv_stream_t* server, uv_stream_t* client) { uv_stream_t* streamServer; uv_stream_t* streamClient; diff --git a/deps/uv/src/unix/thread.c b/deps/uv/src/unix/thread.c index 4fd5d2f58f..e44a77ffce 100644 --- a/deps/uv/src/unix/thread.c +++ b/deps/uv/src/unix/thread.c @@ -323,41 +323,22 @@ void uv_cond_wait(uv_cond_t* cond, uv_mutex_t* mutex) { abort(); } -#if defined(__APPLE__) && defined(__MACH__) int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { int r; - struct timeval tv; struct timespec ts; - uint64_t abstime; - gettimeofday(&tv, NULL); - abstime = tv.tv_sec * 1e9 + tv.tv_usec * 1e3 + timeout; - ts.tv_sec = abstime / NANOSEC; - ts.tv_nsec = abstime % NANOSEC; +#if defined(__APPLE__) && defined(__MACH__) + ts.tv_sec = timeout / NANOSEC; + ts.tv_nsec = timeout % NANOSEC; + r = pthread_cond_timedwait_relative_np(cond, mutex, &ts); +#else + timeout += uv__hrtime(); + ts.tv_sec = timeout / NANOSEC; + ts.tv_nsec = timeout % NANOSEC; r = pthread_cond_timedwait(cond, mutex, &ts); +#endif - if (r == 0) - return 0; - - if (r == ETIMEDOUT) - return -1; - - abort(); - return -1; /* Satisfy the compiler. */ -} - -#else /* !(defined(__APPLE__) && defined(__MACH__)) */ - -int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { - int r; - struct timespec ts; - uint64_t abstime; - - abstime = uv__hrtime() + timeout; - ts.tv_sec = abstime / NANOSEC; - ts.tv_nsec = abstime % NANOSEC; - r = pthread_cond_timedwait(cond, mutex, &ts); if (r == 0) return 0; @@ -369,8 +350,6 @@ int uv_cond_timedwait(uv_cond_t* cond, uv_mutex_t* mutex, uint64_t timeout) { return -1; /* Satisfy the compiler. */ } -#endif /* defined(__APPLE__) && defined(__MACH__) */ - #if defined(__APPLE__) && defined(__MACH__) diff --git a/deps/uv/src/unix/timer.c b/deps/uv/src/unix/timer.c index 9708dbd89b..41038c8ac0 100644 --- a/deps/uv/src/unix/timer.c +++ b/deps/uv/src/unix/timer.c @@ -27,9 +27,13 @@ static int uv__timer_cmp(const uv_timer_t* a, const uv_timer_t* b) { return -1; if (a->timeout > b->timeout) return 1; - if (a < b) + /* + * compare start_id when both has the same timeout. start_id is + * allocated with loop->timer_counter in uv_timer_start(). + */ + if (a->start_id < b->start_id) return -1; - if (a > b) + if (a->start_id > b->start_id) return 1; return 0; } @@ -48,17 +52,16 @@ int uv_timer_init(uv_loop_t* loop, uv_timer_t* handle) { int uv_timer_start(uv_timer_t* handle, uv_timer_cb cb, - int64_t timeout, - int64_t repeat) { - assert(timeout >= 0); - assert(repeat >= 0); - + uint64_t timeout, + uint64_t repeat) { if (uv__is_active(handle)) uv_timer_stop(handle); handle->timer_cb = cb; handle->timeout = handle->loop->time + timeout; handle->repeat = repeat; + /* start_id is the second index to be compared in uv__timer_cmp() */ + handle->start_id = handle->loop->timer_counter++; RB_INSERT(uv__timers, &handle->loop->timer_handles, handle); uv__handle_start(handle); @@ -91,13 +94,12 @@ int uv_timer_again(uv_timer_t* handle) { } -void uv_timer_set_repeat(uv_timer_t* handle, int64_t repeat) { - assert(repeat >= 0); +void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { handle->repeat = repeat; } -int64_t uv_timer_get_repeat(uv_timer_t* handle) { +uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { return handle->repeat; } diff --git a/deps/uv/src/unix/udp.c b/deps/uv/src/unix/udp.c index 8388ba6c23..56c1b25072 100644 --- a/deps/uv/src/unix/udp.c +++ b/deps/uv/src/unix/udp.c @@ -35,8 +35,13 @@ static void uv__udp_io(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static void uv__udp_recvmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static void uv__udp_sendmsg(uv_loop_t* loop, uv__io_t* w, unsigned int revents); static int uv__udp_maybe_deferred_bind(uv_udp_t* handle, int domain); -static int uv__udp_send(uv_udp_send_t* req, uv_udp_t* handle, uv_buf_t bufs[], - int bufcnt, struct sockaddr* addr, socklen_t addrlen, uv_udp_send_cb send_cb); +static int uv__udp_send(uv_udp_send_t* req, + uv_udp_t* handle, + uv_buf_t bufs[], + int bufcnt, + struct sockaddr* addr, + socklen_t addrlen, + uv_udp_send_cb send_cb); void uv__udp_close(uv_udp_t* handle) { @@ -519,11 +524,13 @@ out: } -int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, - const char* interface_addr, uv_membership membership) { - - int optname; +int uv_udp_set_membership(uv_udp_t* handle, + const char* multicast_addr, + const char* interface_addr, + uv_membership membership) { struct ip_mreq mreq; + int optname; + memset(&mreq, 0, sizeof mreq); if (interface_addr) { @@ -545,9 +552,12 @@ int uv_udp_set_membership(uv_udp_t* handle, const char* multicast_addr, return uv__set_artificial_error(handle->loop, UV_EINVAL); } - if (setsockopt(handle->io_watcher.fd, IPPROTO_IP, optname, (void*) &mreq, sizeof mreq) == -1) { - uv__set_sys_error(handle->loop, errno); - return -1; + if (setsockopt(handle->io_watcher.fd, + IPPROTO_IP, + optname, + &mreq, + sizeof(mreq))) { + return uv__set_sys_error(handle->loop, errno); } return 0; @@ -572,8 +582,13 @@ static int uv__setsockopt_maybe_char(uv_udp_t* handle, int option, int val) { int uv_udp_set_broadcast(uv_udp_t* handle, int on) { - if (setsockopt(handle->io_watcher.fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on))) + if (setsockopt(handle->io_watcher.fd, + SOL_SOCKET, + SO_BROADCAST, + &on, + sizeof(on))) { return uv__set_sys_error(handle->loop, errno); + } return 0; } diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index 0b05334945..ae2ca71474 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -197,44 +197,38 @@ int uv_ip6_name(struct sockaddr_in6* src, char* dst, size_t size) { int uv_tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) { - if (handle->type != UV_TCP || addr.sin_family != AF_INET) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__tcp_bind(handle, addr); + if (handle->type != UV_TCP || addr.sin_family != AF_INET) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__tcp_bind(handle, addr); } int uv_tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) { - if (handle->type != UV_TCP || addr.sin6_family != AF_INET6) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__tcp_bind6(handle, addr); + if (handle->type != UV_TCP || addr.sin6_family != AF_INET6) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__tcp_bind6(handle, addr); } -int uv_udp_bind(uv_udp_t* handle, struct sockaddr_in addr, - unsigned int flags) { - if (handle->type != UV_UDP || addr.sin_family != AF_INET) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__udp_bind(handle, addr, flags); +int uv_udp_bind(uv_udp_t* handle, + struct sockaddr_in addr, + unsigned int flags) { + if (handle->type != UV_UDP || addr.sin_family != AF_INET) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__udp_bind(handle, addr, flags); } -int uv_udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, - unsigned int flags) { - if (handle->type != UV_UDP || addr.sin6_family != AF_INET6) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__udp_bind6(handle, addr, flags); +int uv_udp_bind6(uv_udp_t* handle, + struct sockaddr_in6 addr, + unsigned int flags) { + if (handle->type != UV_UDP || addr.sin6_family != AF_INET6) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__udp_bind6(handle, addr, flags); } @@ -242,12 +236,10 @@ int uv_tcp_connect(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in address, uv_connect_cb cb) { - if (handle->type != UV_TCP || address.sin_family != AF_INET) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__tcp_connect(req, handle, address, cb); + if (handle->type != UV_TCP || address.sin_family != AF_INET) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__tcp_connect(req, handle, address, cb); } @@ -255,12 +247,10 @@ int uv_tcp_connect6(uv_connect_t* req, uv_tcp_t* handle, struct sockaddr_in6 address, uv_connect_cb cb) { - if (handle->type != UV_TCP || address.sin6_family != AF_INET6) { - uv__set_artificial_error(handle->loop, UV_EINVAL); - return -1; - } - - return uv__tcp_connect6(req, handle, address, cb); + if (handle->type != UV_TCP || address.sin6_family != AF_INET6) + return uv__set_artificial_error(handle->loop, UV_EINVAL); + else + return uv__tcp_connect6(req, handle, address, cb); } diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 67558b4904..e56536a7fa 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -115,6 +115,8 @@ static void uv_loop_init(uv_loop_t* loop) { loop->active_tcp_streams = 0; loop->active_udp_streams = 0; + loop->timer_counter = 0; + loop->last_err = uv_ok_; } diff --git a/deps/uv/src/win/error.c b/deps/uv/src/win/error.c index ff79f9c814..40852cffcb 100644 --- a/deps/uv/src/win/error.c +++ b/deps/uv/src/win/error.c @@ -66,31 +66,6 @@ void uv_fatal_error(const int errorno, const char* syscall) { uv_err_code uv_translate_sys_error(int sys_errno) { switch (sys_errno) { case ERROR_SUCCESS: return UV_OK; - case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; - case ERROR_BUS_RESET: return UV_EIO; - case ERROR_CRC: return UV_EIO; - case ERROR_DEVICE_DOOR_OPEN: return UV_EIO; - case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO; - case ERROR_DISK_CORRUPT: return UV_EIO; - case ERROR_EOM_OVERFLOW: return UV_EIO; - case ERROR_FILEMARK_DETECTED: return UV_EIO; - case ERROR_GEN_FAILURE: return UV_EIO; - case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO; - case ERROR_IO_DEVICE: return UV_EIO; - case ERROR_NO_DATA_DETECTED: return UV_EIO; - case ERROR_NO_SIGNAL_SENT: return UV_EIO; - case ERROR_OPEN_FAILED: return UV_EIO; - case ERROR_SETMARK_DETECTED: return UV_EIO; - case ERROR_SIGNAL_REFUSED: return UV_EIO; - case ERROR_DIRECTORY: return UV_ENOENT; - case ERROR_FILE_NOT_FOUND: return UV_ENOENT; - case ERROR_INVALID_NAME: return UV_ENOENT; - case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT; - case ERROR_MOD_NOT_FOUND: return UV_ENOENT; - case ERROR_PATH_NOT_FOUND: return UV_ENOENT; - case WSANO_DATA: return UV_ENOENT; - case ERROR_ACCESS_DENIED: return UV_EPERM; - case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM; case ERROR_NOACCESS: return UV_EACCES; case WSAEACCES: return UV_EACCES; case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE; @@ -99,8 +74,14 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case WSAEAFNOSUPPORT: return UV_EAFNOSUPPORT; case WSAEWOULDBLOCK: return UV_EAGAIN; case WSAEALREADY: return UV_EALREADY; + case ERROR_INVALID_FLAGS: return UV_EBADF; + case ERROR_INVALID_HANDLE: return UV_EBADF; case ERROR_LOCK_VIOLATION: return UV_EBUSY; + case ERROR_PIPE_BUSY: return UV_EBUSY; case ERROR_SHARING_VIOLATION: return UV_EBUSY; + case ERROR_OPERATION_ABORTED: return UV_ECANCELED; + case WSAEINTR: return UV_ECANCELED; + case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET; case ERROR_CONNECTION_ABORTED: return UV_ECONNABORTED; case WSAECONNABORTED: return UV_ECONNABORTED; case ERROR_CONNECTION_REFUSED: return UV_ECONNREFUSED; @@ -113,11 +94,29 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case WSAEFAULT: return UV_EFAULT; case ERROR_HOST_UNREACHABLE: return UV_EHOSTUNREACH; case WSAEHOSTUNREACH: return UV_EHOSTUNREACH; - case ERROR_OPERATION_ABORTED: return UV_ECANCELED; - case WSAEINTR: return UV_ECANCELED; + case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL; case ERROR_INVALID_DATA: return UV_EINVAL; + case ERROR_INVALID_PARAMETER: return UV_EINVAL; case ERROR_SYMLINK_NOT_SUPPORTED: return UV_EINVAL; case WSAEINVAL: return UV_EINVAL; + case WSAEPFNOSUPPORT: return UV_EINVAL; + case WSAESOCKTNOSUPPORT: return UV_EINVAL; + case ERROR_BEGINNING_OF_MEDIA: return UV_EIO; + case ERROR_BUS_RESET: return UV_EIO; + case ERROR_CRC: return UV_EIO; + case ERROR_DEVICE_DOOR_OPEN: return UV_EIO; + case ERROR_DEVICE_REQUIRES_CLEANING: return UV_EIO; + case ERROR_DISK_CORRUPT: return UV_EIO; + case ERROR_EOM_OVERFLOW: return UV_EIO; + case ERROR_FILEMARK_DETECTED: return UV_EIO; + case ERROR_GEN_FAILURE: return UV_EIO; + case ERROR_INVALID_BLOCK_LENGTH: return UV_EIO; + case ERROR_IO_DEVICE: return UV_EIO; + case ERROR_NO_DATA_DETECTED: return UV_EIO; + case ERROR_NO_SIGNAL_SENT: return UV_EIO; + case ERROR_OPEN_FAILED: return UV_EIO; + case ERROR_SETMARK_DETECTED: return UV_EIO; + case ERROR_SIGNAL_REFUSED: return UV_EIO; case ERROR_CANT_RESOLVE_FILENAME: return UV_ELOOP; case ERROR_TOO_MANY_OPEN_FILES: return UV_EMFILE; case WSAEMFILE: return UV_EMFILE; @@ -126,6 +125,14 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_NETWORK_UNREACHABLE: return UV_ENETUNREACH; case WSAENETUNREACH: return UV_ENETUNREACH; case WSAENOBUFS: return UV_ENOBUFS; + case ERROR_DIRECTORY: return UV_ENOENT; + case ERROR_FILE_NOT_FOUND: return UV_ENOENT; + case ERROR_INVALID_NAME: return UV_ENOENT; + case ERROR_INVALID_REPARSE_DATA: return UV_ENOENT; + case ERROR_MOD_NOT_FOUND: return UV_ENOENT; + case ERROR_PATH_NOT_FOUND: return UV_ENOENT; + case WSAHOST_NOT_FOUND: return UV_ENOENT; + case WSANO_DATA: return UV_ENOENT; case ERROR_NOT_ENOUGH_MEMORY: return UV_ENOMEM; case ERROR_OUTOFMEMORY: return UV_ENOMEM; case ERROR_CANNOT_MAKE: return UV_ENOSPC; @@ -133,26 +140,22 @@ uv_err_code uv_translate_sys_error(int sys_errno) { case ERROR_EA_TABLE_FULL: return UV_ENOSPC; case ERROR_END_OF_MEDIA: return UV_ENOSPC; case ERROR_HANDLE_DISK_FULL: return UV_ENOSPC; - case ERROR_WRITE_PROTECT: return UV_EROFS; case ERROR_NOT_CONNECTED: return UV_ENOTCONN; case WSAENOTCONN: return UV_ENOTCONN; case ERROR_DIR_NOT_EMPTY: return UV_ENOTEMPTY; + case WSAENOTSOCK: return UV_ENOTSOCK; case ERROR_NOT_SUPPORTED: return UV_ENOTSUP; - case ERROR_INSUFFICIENT_BUFFER: return UV_EINVAL; - case ERROR_INVALID_FLAGS: return UV_EBADF; - case ERROR_INVALID_HANDLE: return UV_EBADF; - case ERROR_INVALID_PARAMETER: return UV_EINVAL; - case ERROR_NO_UNICODE_TRANSLATION: return UV_ECHARSET; case ERROR_BROKEN_PIPE: return UV_EOF; + case ERROR_ACCESS_DENIED: return UV_EPERM; + case ERROR_PRIVILEGE_NOT_HELD: return UV_EPERM; case ERROR_BAD_PIPE: return UV_EPIPE; case ERROR_NO_DATA: return UV_EPIPE; case ERROR_PIPE_NOT_CONNECTED: return UV_EPIPE; case WSAESHUTDOWN: return UV_EPIPE; - case ERROR_PIPE_BUSY: return UV_EBUSY; + case WSAEPROTONOSUPPORT: return UV_EPROTONOSUPPORT; + case ERROR_WRITE_PROTECT: return UV_EROFS; case ERROR_SEM_TIMEOUT: return UV_ETIMEDOUT; case WSAETIMEDOUT: return UV_ETIMEDOUT; - case WSAHOST_NOT_FOUND: return UV_ENOENT; - case WSAENOTSOCK: return UV_ENOTSOCK; case ERROR_NOT_SAME_DEVICE: return UV_EXDEV; default: return UV_UNKNOWN; } diff --git a/deps/uv/src/win/fs.c b/deps/uv/src/win/fs.c index 9b920c817a..60e67a41d5 100644 --- a/deps/uv/src/win/fs.c +++ b/deps/uv/src/win/fs.c @@ -889,7 +889,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { return; } - if (fs__stat_handle(handle, &req->stat) != 0) { + if (fs__stat_handle(handle, &req->statbuf) != 0) { DWORD error = GetLastError(); if (do_lstat && error == ERROR_SYMLINK_NOT_SUPPORTED) { /* We opened a reparse point but it was not a symlink. Try again. */ @@ -904,7 +904,7 @@ INLINE static void fs__stat_impl(uv_fs_t* req, int do_lstat) { return; } - req->ptr = &req->stat; + req->ptr = &req->statbuf; req->result = 0; CloseHandle(handle); } @@ -935,12 +935,12 @@ static void fs__fstat(uv_fs_t* req) { return; } - if (fs__stat_handle(handle, &req->stat) != 0) { + if (fs__stat_handle(handle, &req->statbuf) != 0) { SET_REQ_WIN32_ERROR(req, GetLastError()); return; } - req->ptr = &req->stat; + req->ptr = &req->statbuf; req->result = 0; } diff --git a/deps/uv/src/win/internal.h b/deps/uv/src/win/internal.h index f0d0d7a55a..9920f704ab 100644 --- a/deps/uv/src/win/internal.h +++ b/deps/uv/src/win/internal.h @@ -335,9 +335,6 @@ int WSAAPI uv_wsarecvfrom_workaround(SOCKET socket, WSABUF* buffers, int WSAAPI uv_msafd_poll(SOCKET socket, AFD_POLL_INFO* info, OVERLAPPED* overlapped); -/* Whether ipv6 is supported */ -extern int uv_allow_ipv6; - /* Whether there are any non-IFS LSPs stacked on TCP */ extern int uv_tcp_non_ifs_lsp_ipv4; extern int uv_tcp_non_ifs_lsp_ipv6; diff --git a/deps/uv/src/win/tcp.c b/deps/uv/src/win/tcp.c index ff7b27b805..7158216131 100644 --- a/deps/uv/src/win/tcp.c +++ b/deps/uv/src/win/tcp.c @@ -81,7 +81,7 @@ static int uv__tcp_keepalive(uv_tcp_t* handle, SOCKET socket, int enable, unsign static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, - SOCKET socket, int imported) { + SOCKET socket, int family, int imported) { DWORD yes = 1; int non_ifs_lsp; @@ -107,8 +107,11 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, } } - non_ifs_lsp = (handle->flags & UV_HANDLE_IPV6) ? uv_tcp_non_ifs_lsp_ipv6 : - uv_tcp_non_ifs_lsp_ipv4; + if (family == AF_INET6) { + non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv6; + } else { + non_ifs_lsp = uv_tcp_non_ifs_lsp_ipv4; + } if (pSetFileCompletionNotificationModes && !non_ifs_lsp) { if (pSetFileCompletionNotificationModes((HANDLE) socket, @@ -134,6 +137,12 @@ static int uv_tcp_set_socket(uv_loop_t* loop, uv_tcp_t* handle, handle->socket = socket; + if (family == AF_INET6) { + handle->flags |= UV_HANDLE_IPV6; + } else { + assert(!(handle->flags & UV_HANDLE_IPV6)); + } + return 0; } @@ -230,14 +239,14 @@ void uv_tcp_endgame(uv_loop_t* loop, uv_tcp_t* handle) { static int uv__bind(uv_tcp_t* handle, - int domain, + int family, struct sockaddr* addr, int addrsize) { DWORD err; int r; if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(domain, SOCK_STREAM, 0); + SOCKET sock = socket(family, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; @@ -250,7 +259,7 @@ static int uv__bind(uv_tcp_t* handle, return -1; } - if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) { + if (uv_tcp_set_socket(handle->loop, handle, sock, family, 0) < 0) { closesocket(sock); return -1; } @@ -285,17 +294,10 @@ int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr) { int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr) { - if (uv_allow_ipv6) { - handle->flags |= UV_HANDLE_IPV6; - return uv__bind(handle, - AF_INET6, - (struct sockaddr*)&addr, - sizeof(struct sockaddr_in6)); - - } else { - uv__set_sys_error(handle->loop, WSAEAFNOSUPPORT); - return -1; - } + return uv__bind(handle, + AF_INET6, + (struct sockaddr*)&addr, + sizeof(struct sockaddr_in6)); } @@ -584,6 +586,7 @@ int uv_tcp_listen(uv_tcp_t* handle, int backlog, uv_connection_cb cb) { int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { uv_loop_t* loop = server->loop; int rv = 0; + int family; uv_tcp_accept_t* req = server->pending_accepts; @@ -598,7 +601,17 @@ int uv_tcp_accept(uv_tcp_t* server, uv_tcp_t* client) { return -1; } - if (uv_tcp_set_socket(client->loop, client, req->accept_socket, 0) == -1) { + if (server->flags & UV_HANDLE_IPV6) { + family = AF_INET6; + } else { + family = AF_INET; + } + + if (uv_tcp_set_socket(client->loop, + client, + req->accept_socket, + family, + 0) < 0) { closesocket(req->accept_socket); rv = -1; } else { @@ -733,11 +746,6 @@ int uv__tcp_connect6(uv_connect_t* req, BOOL success; DWORD bytes; - if (!uv_allow_ipv6) { - uv__set_sys_error(loop, WSAEAFNOSUPPORT); - return -1; - } - if (handle->flags & UV_HANDLE_BIND_ERROR) { uv__set_sys_error(loop, handle->bind_error); return -1; @@ -1148,7 +1156,11 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, return -1; } - if (uv_tcp_set_socket(tcp->loop, tcp, socket, 1) != 0) { + if (uv_tcp_set_socket(tcp->loop, + tcp, + socket, + socket_protocol_info->iAddressFamily, + 1) < 0) { closesocket(socket); return -1; } @@ -1161,10 +1173,6 @@ int uv_tcp_import(uv_tcp_t* tcp, WSAPROTOCOL_INFOW* socket_protocol_info, tcp->flags |= UV_HANDLE_BOUND; tcp->flags |= UV_HANDLE_SHARED_TCP_SOCKET; - if (socket_protocol_info->iAddressFamily == AF_INET6) { - tcp->flags |= UV_HANDLE_IPV6; - } - tcp->loop->active_tcp_streams++; return 0; } @@ -1381,13 +1389,31 @@ void uv_tcp_close(uv_loop_t* loop, uv_tcp_t* tcp) { int uv_tcp_open(uv_tcp_t* handle, uv_os_sock_t sock) { + WSAPROTOCOL_INFOW protocol_info; + int opt_len; + + /* Detect the address family of the socket. */ + opt_len = (int) sizeof protocol_info; + if (getsockopt(sock, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) { + uv__set_sys_error(handle->loop, GetLastError()); + return -1; + } + /* Make the socket non-inheritable */ if (!SetHandleInformation((HANDLE) sock, HANDLE_FLAG_INHERIT, 0)) { uv__set_sys_error(handle->loop, GetLastError()); return -1; } - if (uv_tcp_set_socket(handle->loop, handle, sock, 0) == -1) { + if (uv_tcp_set_socket(handle->loop, + handle, + sock, + protocol_info.iAddressFamily, + 1) < 0) { return -1; } diff --git a/deps/uv/src/win/timer.c b/deps/uv/src/win/timer.c index 370f2b6dc8..0c055da941 100644 --- a/deps/uv/src/win/timer.c +++ b/deps/uv/src/win/timer.c @@ -45,7 +45,7 @@ void uv_update_time(uv_loop_t* loop) { } -int64_t uv_now(uv_loop_t* loop) { +uint64_t uv_now(uv_loop_t* loop) { return loop->time; } @@ -55,9 +55,13 @@ static int uv_timer_compare(uv_timer_t* a, uv_timer_t* b) { return -1; if (a->due > b->due) return 1; - if ((intptr_t)a < (intptr_t)b) + /* + * compare start_id when both has the same due. start_id is + * allocated with loop->timer_counter in uv_timer_start(). + */ + if (a->start_id < b->start_id) return -1; - if ((intptr_t)a > (intptr_t)b) + if (a->start_id > b->start_id) return 1; return 0; } @@ -83,8 +87,8 @@ void uv_timer_endgame(uv_loop_t* loop, uv_timer_t* handle) { } -int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout, - int64_t repeat) { +int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, uint64_t timeout, + uint64_t repeat) { uv_loop_t* loop = handle->loop; uv_timer_t* old; @@ -98,6 +102,9 @@ int uv_timer_start(uv_timer_t* handle, uv_timer_cb timer_cb, int64_t timeout, handle->flags |= UV_HANDLE_ACTIVE; uv__handle_start(handle); + /* start_id is the second index to be compared in uv__timer_cmp() */ + handle->start_id = handle->loop->timer_counter++; + old = RB_INSERT(uv_timer_tree_s, &loop->timers, handle); assert(old == NULL); @@ -150,13 +157,13 @@ int uv_timer_again(uv_timer_t* handle) { } -void uv_timer_set_repeat(uv_timer_t* handle, int64_t repeat) { +void uv_timer_set_repeat(uv_timer_t* handle, uint64_t repeat) { assert(handle->type == UV_TIMER); handle->repeat = repeat; } -int64_t uv_timer_get_repeat(uv_timer_t* handle) { +uint64_t uv_timer_get_repeat(const uv_timer_t* handle) { assert(handle->type == UV_TIMER); return handle->repeat; } diff --git a/deps/uv/src/win/udp.c b/deps/uv/src/win/udp.c index 6d2cde30c6..23410528f5 100644 --- a/deps/uv/src/win/udp.c +++ b/deps/uv/src/win/udp.c @@ -56,14 +56,24 @@ int uv_udp_getsockname(uv_udp_t* handle, struct sockaddr* name, } -static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, - SOCKET socket) { +static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, SOCKET socket, + int family) { DWORD yes = 1; WSAPROTOCOL_INFOW info; int opt_len; assert(handle->socket == INVALID_SOCKET); + /* Set SO_REUSEADDR on the socket. */ + if (setsockopt(socket, + SOL_SOCKET, + SO_REUSEADDR, + (char*) &yes, + sizeof yes) == SOCKET_ERROR) { + uv__set_sys_error(loop, WSAGetLastError()); + return -1; + } + /* Set the socket to nonblocking mode */ if (ioctlsocket(socket, FIONBIO, &yes) == SOCKET_ERROR) { uv__set_sys_error(loop, WSAGetLastError()); @@ -93,7 +103,7 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, /* if the user is using the default UDP driver (AFD) and has no other */ /* LSPs stacked on top. Here we check whether that is the case. */ opt_len = (int) sizeof info; - if (!getsockopt(socket, + if (getsockopt(socket, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &info, @@ -118,6 +128,12 @@ static int uv_udp_set_socket(uv_loop_t* loop, uv_udp_t* handle, handle->socket = socket; + if (family == AF_INET6) { + handle->flags |= UV_HANDLE_IPV6; + } else { + assert(!(handle->flags & UV_HANDLE_IPV6)); + } + return 0; } @@ -161,33 +177,36 @@ void uv_udp_endgame(uv_loop_t* loop, uv_udp_t* handle) { static int uv__bind(uv_udp_t* handle, - int domain, + int family, struct sockaddr* addr, int addrsize, unsigned int flags) { int r; DWORD no = 0, yes = 1; - if ((flags & UV_UDP_IPV6ONLY) && domain != AF_INET6) { + if ((flags & UV_UDP_IPV6ONLY) && family != AF_INET6) { /* UV_UDP_IPV6ONLY is supported only for IPV6 sockets */ uv__set_artificial_error(handle->loop, UV_EINVAL); return -1; } if (handle->socket == INVALID_SOCKET) { - SOCKET sock = socket(domain, SOCK_DGRAM, 0); + SOCKET sock = socket(family, SOCK_DGRAM, 0); if (sock == INVALID_SOCKET) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } - if (uv_udp_set_socket(handle->loop, handle, sock) == -1) { + if (uv_udp_set_socket(handle->loop, handle, sock, family) < 0) { closesocket(sock); return -1; } + + if (family == AF_INET6) + handle->flags |= UV_HANDLE_IPV6; } - if (domain == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { + if (family == AF_INET6 && !(flags & UV_UDP_IPV6ONLY)) { /* On windows IPV6ONLY is on by default. */ /* If the user doesn't specify it libuv turns it off. */ @@ -201,16 +220,6 @@ static int uv__bind(uv_udp_t* handle, sizeof no); } - r = setsockopt(handle->socket, - SOL_SOCKET, - SO_REUSEADDR, - (char*) &yes, - sizeof yes); - if (r == SOCKET_ERROR) { - uv__set_sys_error(handle->loop, WSAGetLastError()); - return -1; - } - r = bind(handle->socket, addr, addrsize); if (r == SOCKET_ERROR) { uv__set_sys_error(handle->loop, WSAGetLastError()); @@ -235,17 +244,11 @@ int uv__udp_bind(uv_udp_t* handle, struct sockaddr_in addr, int uv__udp_bind6(uv_udp_t* handle, struct sockaddr_in6 addr, unsigned int flags) { - if (uv_allow_ipv6) { - handle->flags |= UV_HANDLE_IPV6; - return uv__bind(handle, - AF_INET6, - (struct sockaddr*) &addr, - sizeof(struct sockaddr_in6), - flags); - } else { - uv__set_sys_error(handle->loop, WSAEAFNOSUPPORT); - return -1; - } + return uv__bind(handle, + AF_INET6, + (struct sockaddr*) &addr, + sizeof(struct sockaddr_in6), + flags); } @@ -641,10 +644,10 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { } if (setsockopt(handle->socket, - SOL_SOCKET, - SO_BROADCAST, - (char*) &optval, - sizeof optval)) { + SOL_SOCKET, + SO_BROADCAST, + (char*) &optval, + sizeof optval)) { uv__set_sys_error(handle->loop, WSAGetLastError()); return -1; } @@ -653,20 +656,25 @@ int uv_udp_set_broadcast(uv_udp_t* handle, int value) { int uv_udp_open(uv_udp_t* handle, uv_os_sock_t sock) { - int r; + WSAPROTOCOL_INFOW protocol_info; + int opt_len; DWORD yes = 1; - if (uv_udp_set_socket(handle->loop, handle, sock) == -1) { + /* Detect the address family of the socket. */ + opt_len = (int) sizeof protocol_info; + if (getsockopt(sock, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) { + uv__set_sys_error(handle->loop, GetLastError()); return -1; } - r = setsockopt(handle->socket, - SOL_SOCKET, - SO_REUSEADDR, - (char*) &yes, - sizeof yes); - if (r == SOCKET_ERROR) { - uv__set_sys_error(handle->loop, WSAGetLastError()); + if (uv_udp_set_socket(handle->loop, + handle, + sock, + protocol_info.iAddressFamily) < 0) { return -1; } diff --git a/deps/uv/src/win/winsock.c b/deps/uv/src/win/winsock.c index 2c3e49a103..47395bb89d 100644 --- a/deps/uv/src/win/winsock.c +++ b/deps/uv/src/win/winsock.c @@ -25,9 +25,6 @@ #include "internal.h" -/* Whether ipv6 is supported */ -int uv_allow_ipv6; - /* Whether there are any non-IFS LSPs stacked on TCP */ int uv_tcp_non_ifs_lsp_ipv4; int uv_tcp_non_ifs_lsp_ipv6; @@ -75,6 +72,12 @@ BOOL uv_get_connectex_function(SOCKET socket, LPFN_CONNECTEX* target) { } +static int error_means_no_support(DWORD error) { + return error == WSAEPROTONOSUPPORT || error == WSAESOCKTNOSUPPORT || + error == WSAEPFNOSUPPORT || error == WSAEAFNOSUPPORT; +} + + void uv_winsock_init() { const GUID wsaid_connectex = WSAID_CONNECTEX; const GUID wsaid_acceptex = WSAID_ACCEPTEX; @@ -100,48 +103,48 @@ void uv_winsock_init() { /* Detect non-IFS LSPs */ dummy = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); - if (dummy == INVALID_SOCKET) { - uv_fatal_error(WSAGetLastError(), "socket"); - } - opt_len = (int) sizeof protocol_info; - if (!getsockopt(dummy, - SOL_SOCKET, - SO_PROTOCOL_INFOW, - (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - uv_fatal_error(WSAGetLastError(), "socket"); - } + if (dummy != INVALID_SOCKET) { + opt_len = (int) sizeof protocol_info; + if (!getsockopt(dummy, + SOL_SOCKET, + SO_PROTOCOL_INFOW, + (char*) &protocol_info, + &opt_len) == SOCKET_ERROR) + uv_fatal_error(WSAGetLastError(), "getsockopt"); - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) { - uv_tcp_non_ifs_lsp_ipv4 = 1; - } + if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) + uv_tcp_non_ifs_lsp_ipv4 = 1; + + if (closesocket(dummy) == SOCKET_ERROR) + uv_fatal_error(WSAGetLastError(), "closesocket"); - if (closesocket(dummy) == SOCKET_ERROR) { - uv_fatal_error(WSAGetLastError(), "closesocket"); + } else if (!error_means_no_support(WSAGetLastError())) { + /* Any error other than "socket type not supported" is fatal. */ + uv_fatal_error(WSAGetLastError(), "socket"); } /* Detect IPV6 support and non-IFS LSPs */ dummy = socket(AF_INET6, SOCK_STREAM, IPPROTO_IP); - if (dummy != INVALID_SOCKET) { - uv_allow_ipv6 = TRUE; + if (dummy != INVALID_SOCKET) { opt_len = (int) sizeof protocol_info; if (!getsockopt(dummy, SOL_SOCKET, SO_PROTOCOL_INFOW, (char*) &protocol_info, - &opt_len) == SOCKET_ERROR) { - uv_fatal_error(WSAGetLastError(), "socket"); - } + &opt_len) == SOCKET_ERROR) + uv_fatal_error(WSAGetLastError(), "getsockopt"); - if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) { + if (!(protocol_info.dwServiceFlags1 & XP1_IFS_HANDLES)) uv_tcp_non_ifs_lsp_ipv6 = 1; - } - if (closesocket(dummy) == SOCKET_ERROR) { + if (closesocket(dummy) == SOCKET_ERROR) uv_fatal_error(WSAGetLastError(), "closesocket"); - } + + } else if (!error_means_no_support(WSAGetLastError())) { + /* Any error other than "socket type not supported" is fatal. */ + uv_fatal_error(WSAGetLastError(), "socket"); } } diff --git a/deps/uv/test/test-fs.c b/deps/uv/test/test-fs.c index ddc3c73b13..0016b3bede 100644 --- a/deps/uv/test/test-fs.c +++ b/deps/uv/test/test-fs.c @@ -107,13 +107,13 @@ static char test_buf[] = "test-buffer\n"; static void check_permission(const char* filename, int mode) { int r; uv_fs_t req; - struct stat* s; + uv_statbuf_t* s; r = uv_fs_stat(uv_default_loop(), &req, filename, NULL); ASSERT(r == 0); ASSERT(req.result == 0); - s = req.ptr; + s = &req.statbuf; #ifdef _WIN32 /* * On Windows, chmod can only modify S_IWUSR (_S_IWRITE) bit, @@ -543,7 +543,7 @@ TEST_IMPL(fs_file_loop) { } static void check_utime(const char* path, double atime, double mtime) { - struct stat* s; + uv_statbuf_t* s; uv_fs_t req; int r; @@ -551,7 +551,7 @@ static void check_utime(const char* path, double atime, double mtime) { ASSERT(r == 0); ASSERT(req.result == 0); - s = req.ptr; + s = &req.statbuf; #if defined(_WIN32) || defined(_AIX) ASSERT(s->st_atime == atime); diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h index 77f1f35d8f..efc97380fa 100644 --- a/deps/uv/test/test-list.h +++ b/deps/uv/test/test-list.h @@ -96,6 +96,7 @@ TEST_DECLARE (error_message) TEST_DECLARE (timer) TEST_DECLARE (timer_again) TEST_DECLARE (timer_start_twice) +TEST_DECLARE (timer_order) TEST_DECLARE (idle_starvation) TEST_DECLARE (loop_handles) TEST_DECLARE (get_loadavg) @@ -334,6 +335,7 @@ TASK_LIST_START TEST_ENTRY (timer) TEST_ENTRY (timer_again) TEST_ENTRY (timer_start_twice) + TEST_ENTRY (timer_order) TEST_ENTRY (idle_starvation) diff --git a/deps/uv/test/test-timer-again.c b/deps/uv/test/test-timer-again.c index 6de2904694..536ac448e4 100644 --- a/deps/uv/test/test-timer-again.c +++ b/deps/uv/test/test-timer-again.c @@ -31,7 +31,7 @@ static int repeat_2_cb_allowed = 0; static uv_timer_t dummy, repeat_1, repeat_2; -static int64_t start_time; +static uint64_t start_time; static void close_cb(uv_handle_t* handle) { diff --git a/deps/uv/test/test-timer.c b/deps/uv/test/test-timer.c index b1accb1e01..60b080d28e 100644 --- a/deps/uv/test/test-timer.c +++ b/deps/uv/test/test-timer.c @@ -27,8 +27,9 @@ static int once_cb_called = 0; static int once_close_cb_called = 0; static int repeat_cb_called = 0; static int repeat_close_cb_called = 0; +static int order_cb_called = 0; -static int64_t start_time; +static uint64_t start_time; static void once_close_cb(uv_handle_t* handle) { @@ -153,3 +154,51 @@ TEST_IMPL(timer_start_twice) { MAKE_VALGRIND_HAPPY(); return 0; } + + +static void order_cb_a(uv_timer_t *handle, int status) { + ASSERT(order_cb_called++ == *(int*)handle->data); +} + + +static void order_cb_b(uv_timer_t *handle, int status) { + ASSERT(order_cb_called++ == *(int*)handle->data); +} + + +TEST_IMPL(timer_order) { + int first; + int second; + uv_timer_t handle_a; + uv_timer_t handle_b; + + first = 0; + second = 1; + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_a)); + ASSERT(0 == uv_timer_init(uv_default_loop(), &handle_b)); + + /* Test for starting handle_a then handle_b */ + handle_a.data = &first; + ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0)); + handle_b.data = &second; + ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(order_cb_called == 2); + + ASSERT(0 == uv_timer_stop(&handle_a)); + ASSERT(0 == uv_timer_stop(&handle_b)); + + /* Test for starting handle_b then handle_a */ + order_cb_called = 0; + handle_b.data = &first; + ASSERT(0 == uv_timer_start(&handle_b, order_cb_b, 0, 0)); + + handle_a.data = &second; + ASSERT(0 == uv_timer_start(&handle_a, order_cb_a, 0, 0)); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + + ASSERT(order_cb_called == 2); + + return 0; +} diff --git a/deps/uv/uv.gyp b/deps/uv/uv.gyp index 6ec5aa2893..301b938576 100644 --- a/deps/uv/uv.gyp +++ b/deps/uv/uv.gyp @@ -170,10 +170,10 @@ }], [ 'OS=="linux"', { 'sources': [ - 'src/unix/linux/linux-core.c', - 'src/unix/linux/inotify.c', - 'src/unix/linux/syscalls.c', - 'src/unix/linux/syscalls.h', + 'src/unix/linux-core.c', + 'src/unix/linux-inotify.c', + 'src/unix/linux-syscalls.c', + 'src/unix/linux-syscalls.h', ], 'link_settings': { 'libraries': [ '-ldl', '-lrt' ], diff --git a/deps/uv/vcbuild.bat b/deps/uv/vcbuild.bat index 678a910714..5864a3a99d 100644 --- a/deps/uv/vcbuild.bat +++ b/deps/uv/vcbuild.bat @@ -71,8 +71,8 @@ if defined noprojgen goto msbuild @rem Generate the VS project. if exist build\gyp goto have_gyp -echo svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp -svn co http://gyp.googlecode.com/svn/trunk@983 build/gyp +echo git clone https://git.chromium.org/external/gyp.git build/gyp +git clone https://git.chromium.org/external/gyp.git build/gyp if errorlevel 1 goto gyp_install_failed goto have_gyp