From 895e77639ee9aa3bc17b4bc9d675d63d7940c396 Mon Sep 17 00:00:00 2001 From: Fedor Indutny Date: Mon, 8 Apr 2013 17:10:39 +0400 Subject: [PATCH 1/9] unix: don't write more than IOV_MAX iovecs Write no more than `IOV_MAX` chunks with `writev()` at once, otherwise `writev()` returns EINVAL. --- src/unix/stream.c | 5 +++++ test/test-tcp-writealot.c | 4 ++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index d95fa0dbe..bc9d4f1bb 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -33,6 +33,7 @@ #include #include #include +#include /* IOV_MAX */ #if defined(__APPLE__) # include @@ -742,6 +743,10 @@ start: iov = (struct iovec*) &(req->bufs[req->write_index]); iovcnt = req->bufcnt - req->write_index; + /* Limit iov count to avoid EINVALs from writev() */ + if (iovcnt > IOV_MAX) + iovcnt = IOV_MAX; + /* * 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. diff --git a/test/test-tcp-writealot.c b/test/test-tcp-writealot.c index 3ddcd6d2e..ab8c46adf 100644 --- a/test/test-tcp-writealot.c +++ b/test/test-tcp-writealot.c @@ -26,8 +26,8 @@ #define WRITES 3 -#define CHUNKS_PER_WRITE 3 -#define CHUNK_SIZE 10485760 /* 10 MB */ +#define CHUNKS_PER_WRITE 4096 +#define CHUNK_SIZE 10024 /* 10 kb */ #define TOTAL_BYTES (WRITES * CHUNKS_PER_WRITE * CHUNK_SIZE) From 5676924c5bd7a6e59ec0abb958c31a98b667ea87 Mon Sep 17 00:00:00 2001 From: Nils Maier Date: Wed, 10 Apr 2013 14:00:37 +0200 Subject: [PATCH 2/9] mingw-w64: don't call _set_invalid_parameter_handler Check the __MSVCRT_VERSION__, as mingw-w64 always defines _WRITE_ABORT_MSG. Closes #774 --- src/win/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/core.c b/src/win/core.c index a06c23f3c..0d85c07bb 100644 --- a/src/win/core.c +++ b/src/win/core.c @@ -55,7 +55,7 @@ static void uv_init(void) { /* Tell the CRT to not exit the application when an invalid parameter is */ /* passed. The main issue is that invalid FDs will trigger this behavior. */ -#ifdef _WRITE_ABORT_MSG +#if !defined(__MINGW32__) || __MSVCRT_VERSION__ >= 0x800 _set_invalid_parameter_handler(uv__crt_invalid_parameter_handler); #endif From e294975bb4e01efac13a134b3282193e543c68c7 Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Mon, 8 Apr 2013 16:30:27 -0700 Subject: [PATCH 3/9] build: gyp disable thin archives Thin archives aren't available on all platforms, notably smartos --- common.gypi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common.gypi b/common.gypi index 8c6c88758..a5f11649f 100644 --- a/common.gypi +++ b/common.gypi @@ -132,6 +132,11 @@ [ 'OS=="linux" or OS=="freebsd" or OS=="openbsd" or OS=="solaris"', { 'cflags': [ '-Wall' ], 'cflags_cc': [ '-fno-rtti', '-fno-exceptions' ], + 'target_conditions': [ + ['_type=="static_library"', { + 'standalone_static_library': 1, # disable thin archive which needs binutils >= 2.19 + }], + ], 'conditions': [ [ 'host_arch != target_arch and target_arch=="ia32"', { 'cflags': [ '-m32' ], From 0da533e84f0a4f32d200bf9568548bce1e5e315a Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Mon, 8 Apr 2013 16:31:35 -0700 Subject: [PATCH 4/9] sunos: re-export entire library when static This is useful to make sure linker doesn't strip things like dtrace --- common.gypi | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/common.gypi b/common.gypi index a5f11649f..c3462821f 100644 --- a/common.gypi +++ b/common.gypi @@ -197,6 +197,11 @@ }], ], }], + ['OS=="solaris"', { + 'cflags': [ '-fno-omit-frame-pointer' ], + # pull in V8's postmortem metadata + 'ldflags': [ '-Wl,-z,allextract' ] + }], ], }, } From e1ffc6c0eed94a328e8435bc215820a4701ee8b5 Mon Sep 17 00:00:00 2001 From: Timothy J Fontaine Date: Mon, 8 Apr 2013 16:17:01 -0700 Subject: [PATCH 5/9] unix: dtrace probes for tick-start and tick-stop --- config-unix.mk | 27 ++++++++++++++++-- src/unix/core.c | 4 +++ src/unix/internal.h | 7 +++++ src/unix/uv-dtrace.d | 25 +++++++++++++++++ uv.gyp | 65 ++++++++++++++++++++++++++++++++++++++++++-- 5 files changed, 124 insertions(+), 4 deletions(-) create mode 100644 src/unix/uv-dtrace.d diff --git a/config-unix.mk b/config-unix.mk index f9f2c15ed..c6b34a12b 100644 --- a/config-unix.mk +++ b/config-unix.mk @@ -33,6 +33,10 @@ RUNNER_SRC=test/runner-unix.c RUNNER_CFLAGS=$(CFLAGS) -I$(SRCDIR)/test RUNNER_LDFLAGS=-L"$(CURDIR)" -luv -Xlinker -rpath -Xlinker "$(CURDIR)" +HAVE_DTRACE= +DTRACE_OBJS= +DTRACE_HEADER= + OBJS += src/unix/async.o OBJS += src/unix/core.o OBJS += src/unix/dl.o @@ -58,11 +62,14 @@ OBJS += src/inet.o OBJS += src/version.o ifeq (sunos,$(PLATFORM)) +HAVE_DTRACE=1 CPPFLAGS += -D__EXTENSIONS__ -D_XOPEN_SOURCE=500 LDFLAGS+=-lkstat -lnsl -lsendfile -lsocket # Library dependencies are not transitive. RUNNER_LDFLAGS += $(LDFLAGS) OBJS += src/unix/sunos.o +OBJS += src/unix/dtrace.o +DTRACE_OBJS += src/unix/core.o endif ifeq (aix,$(PLATFORM)) @@ -72,6 +79,7 @@ OBJS += src/unix/aix.o endif ifeq (darwin,$(PLATFORM)) +HAVE_DTRACE=1 CPPFLAGS += -D_DARWIN_USE_64_BIT_INODE=1 LDFLAGS += -framework Foundation \ -framework CoreServices \ @@ -96,6 +104,7 @@ OBJS += src/unix/linux-core.o \ endif ifeq (freebsd,$(PLATFORM)) +HAVE_DTRACE=1 LDFLAGS+=-lkvm OBJS += src/unix/freebsd.o OBJS += src/unix/kqueue.o @@ -132,6 +141,11 @@ else RUNNER_LDFLAGS += -pthread endif +ifeq ($(HAVE_DTRACE), 1) +DTRACE_HEADER=src/unix/uv-dtrace.h +CFLAGS += -DHAVE_DTRACE +endif + libuv.a: $(OBJS) $(AR) rcs $@ $^ @@ -151,7 +165,7 @@ src/.buildstamp src/unix/.buildstamp test/.buildstamp: mkdir -p $(@D) 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 +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 $(DTRACE_HEADER) $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ src/%.o src/%.pic.o: src/%.c include/uv.h include/uv-private/uv-unix.h src/.buildstamp @@ -161,7 +175,16 @@ test/%.o: test/%.c include/uv.h test/.buildstamp $(CC) $(CSTDFLAG) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ clean-platform: - $(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) + $(RM) test/run-{tests,benchmarks}.dSYM $(OBJS) $(OBJS:%.o=%.pic.o) src/unix/uv-dtrace.h %.pic.o %.o: %.m $(OBJC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ + +src/unix/uv-dtrace.h: src/unix/uv-dtrace.d + dtrace -h -xnolibs -s src/unix/uv-dtrace.d -o $@ + +src/unix/dtrace.o: src/unix/uv-dtrace.d $(DTRACE_OBJS) + dtrace -G -s $^ -o $@ + +src/unix/dtrace.pic.o: src/unix/uv-dtrace.d $(DTRACE_OBJS:%.o=%.pic.o) + dtrace -G -s $^ -o $@ diff --git a/src/unix/core.c b/src/unix/core.c index 9b471ec7e..b8bae48a5 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -299,6 +299,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { r = uv__loop_alive(loop); while (r != 0 && loop->stop_flag == 0) { + UV_TICK_START(loop, mode); + uv__update_time(loop); uv__run_timers(loop); uv__run_idle(loop); @@ -314,6 +316,8 @@ int uv_run(uv_loop_t* loop, uv_run_mode mode) { uv__run_closing_handles(loop); r = uv__loop_alive(loop); + UV_TICK_STOP(loop, mode); + if (mode & (UV_RUN_ONCE | UV_RUN_NOWAIT)) break; } diff --git a/src/unix/internal.h b/src/unix/internal.h index 4053d4243..899c972b0 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -256,4 +256,11 @@ static void uv__update_time(uv_loop_t* loop) { loop->time = uv__hrtime() / 1000000; } +#ifdef HAVE_DTRACE +#include "uv-dtrace.h" +#else +#define UV_TICK_START(arg0, arg1) +#define UV_TICK_STOP(arg0, arg1) +#endif + #endif /* UV_UNIX_INTERNAL_H_ */ diff --git a/src/unix/uv-dtrace.d b/src/unix/uv-dtrace.d new file mode 100644 index 000000000..7848450c9 --- /dev/null +++ b/src/unix/uv-dtrace.d @@ -0,0 +1,25 @@ +/* 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. + */ + +provider uv { + probe tick__start(void* loop, int mode); + probe tick__stop(void* loop, int mode); +}; diff --git a/uv.gyp b/uv.gyp index db90ee90e..7824819a9 100644 --- a/uv.gyp +++ b/uv.gyp @@ -1,4 +1,13 @@ { + 'variables': { + 'uv_use_dtrace%': 'false', + # uv_parent_path is the relative path to libuv in the parent project + # this is only relevant when dtrace is enabled and libuv is a child project + # as it's necessary to correctly locate the object files for post + # processing. + 'uv_parent_path': '', + }, + 'target_defaults': { 'conditions': [ ['OS != "win"', { @@ -248,7 +257,17 @@ }], ['library=="shared_library"', { 'defines': [ 'BUILDING_UV_SHARED=1' ] - }] + }], + ['uv_use_dtrace=="true"', { + 'defines': [ 'HAVE_DTRACE=1' ], + 'dependencies': [ 'uv_dtrace_header' ], + 'include_dirs': [ '<(SHARED_INTERMEDIATE_DIR)' ], + 'conditions': [ + ['OS != "mac"', { + 'sources': ['src/unix/dtrace.c' ], + }], + ], + }], ] }, @@ -426,6 +445,48 @@ 'SubSystem': 1, # /subsystem:console }, }, - } + }, + + { + 'target_name': 'uv_dtrace_header', + 'type': 'none', + 'conditions': [ + [ 'uv_use_dtrace=="true"', { + 'actions': [ + { + 'action_name': 'uv_dtrace_header', + 'inputs': [ 'src/unix/uv-dtrace.d' ], + 'outputs': [ '<(SHARED_INTERMEDIATE_DIR)/uv-dtrace.h' ], + 'action': [ 'dtrace', '-h', '-xnolibs', '-s', '<@(_inputs)', + '-o', '<@(_outputs)' ], + }, + ], + }], + ], + }, + + { + 'target_name': 'uv_dtrace_provider', + 'type': 'none', + 'conditions': [ + [ 'uv_use_dtrace=="true" and OS!="mac"', { + 'actions': [ + { + 'action_name': 'uv_dtrace_o', + 'inputs': [ + 'src/unix/uv-dtrace.d', + '<(PRODUCT_DIR)/obj.target/libuv/<(uv_parent_path)/src/unix/core.o', + ], + 'outputs': [ + '<(PRODUCT_DIR)/obj.target/libuv/<(uv_parent_path)/src/unix/dtrace.o', + ], + 'action': [ 'dtrace', '-G', '-xnolibs', '-s', '<@(_inputs)', + '-o', '<@(_outputs)' ] + } + ] + } ] + ] + }, + ] } From 7570a35b70a33258e4c36e080e900f30c3213697 Mon Sep 17 00:00:00 2001 From: Shannen Saez Date: Wed, 10 Apr 2013 14:15:13 +0200 Subject: [PATCH 6/9] windows: fix memory leak in fs__sendfile --- src/win/fs.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win/fs.c b/src/win/fs.c index 60e67a41d..52290a9f5 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -1048,6 +1048,8 @@ static void fs__sendfile(uv_fs_t* req) { } } + free(buf); + SET_REQ_RESULT(req, result); } From 603915dd0081ec2f34d612291a1aeb909f6f2b76 Mon Sep 17 00:00:00 2001 From: Shannen Saez Date: Wed, 10 Apr 2013 14:16:39 +0200 Subject: [PATCH 7/9] windows: remove double initialization in uv_tty_init --- src/win/tty.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/tty.c b/src/win/tty.c index 8f7e76574..64934ffa9 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -96,7 +96,7 @@ void uv_console_init() { int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, uv_file fd, int readable) { - HANDLE handle = INVALID_HANDLE_VALUE; + HANDLE handle; CONSOLE_SCREEN_BUFFER_INFO screen_buffer_info; handle = (HANDLE) _get_osfhandle(fd); From be5b16aabd1d1996ca666a48b933a79e3d37b340 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 10 Apr 2013 14:19:14 +0200 Subject: [PATCH 8/9] build: fix dtrace-enabled out of tree build --- config-unix.mk | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config-unix.mk b/config-unix.mk index c6b34a12b..494e60de9 100644 --- a/config-unix.mk +++ b/config-unix.mk @@ -142,7 +142,8 @@ RUNNER_LDFLAGS += -pthread endif ifeq ($(HAVE_DTRACE), 1) -DTRACE_HEADER=src/unix/uv-dtrace.h +DTRACE_HEADER = src/unix/uv-dtrace.h +CPPFLAGS += -Isrc/unix CFLAGS += -DHAVE_DTRACE endif @@ -181,7 +182,7 @@ clean-platform: $(OBJC) $(CPPFLAGS) $(CFLAGS) -c $^ -o $@ src/unix/uv-dtrace.h: src/unix/uv-dtrace.d - dtrace -h -xnolibs -s src/unix/uv-dtrace.d -o $@ + dtrace -h -xnolibs -s $< -o $@ src/unix/dtrace.o: src/unix/uv-dtrace.d $(DTRACE_OBJS) dtrace -G -s $^ -o $@ From bad707db3f499decd864907809cb5d9b423d1d98 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 10 Apr 2013 14:21:38 +0200 Subject: [PATCH 9/9] gitigore: ignore auto-generated uv-dtrace.h header --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index d6c65dbae..3f4c5193a 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,9 @@ vgcore.* /libuv.so /libuv.dylib +# Generated by dtrace(1) when doing an in-tree build. +/src/unix/uv-dtrace.h + /out/ /build/gyp