From c5622a1c4f083c7f43149755d52d1649c5266c29 Mon Sep 17 00:00:00 2001 From: cjihrig Date: Tue, 17 May 2016 14:53:19 -0400 Subject: [PATCH 01/43] doc: add cjihrig GPG ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/877 Reviewed-By: Saúl Ibarra Corretgé --- MAINTAINERS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 2f0e618c..80f63fd6 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -7,6 +7,7 @@ libuv is currently managed by the following individuals: - GPG key: D77B 1E34 243F BAF0 5F8E 9CC3 4F55 C8C8 46AB 89B9 (pubkey-bnoordhuis) * **Bert Belder** ([@piscisaureus](https://github.com/piscisaureus)) * **Colin Ihrig** ([@cjihrig](https://github.com/cjihrig)) + - GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig) * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) @@ -34,4 +35,3 @@ be garbage collected since nothing references it, so we'll create a tag for it: Commit the changes and push: $ git push origin pubkey-saghul - From 36a024de052d57edb40684f0adbafde4b0ccbf92 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Thu, 19 May 2016 00:26:12 +0200 Subject: [PATCH 02/43] win,build: fix compilation on old Windows / MSVC Observed on Windows XP with Visual Studio 2008. PR-URL: https://github.com/libuv/libuv/pull/880 Reviewed-By: Alexis Campailla --- src/win/tty.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/win/tty.c b/src/win/tty.c index 9b963778..59a991c6 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -40,6 +40,9 @@ #include "stream-inl.h" #include "req-inl.h" +#ifndef InterlockedOr +# define InterlockedOr _InterlockedOr +#endif #define UNICODE_REPLACEMENT_CHARACTER (0xfffd) From c0fdc7102b226b253135c34ecf1098c9ba12a53d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Wed, 18 May 2016 14:07:55 +0100 Subject: [PATCH 03/43] darwin: fix setting fd to non-blocking in select(() trick When the select trick is used fd is replaced with the fake fd (one end of the socketpair) so we're not setting the original fd in non-blocking mode. Refs: https://github.com/nodejs/node/issues/6456#issuecomment-220018822 PR-URL: https://github.com/libuv/libuv/pull/879 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny --- src/unix/tty.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/src/unix/tty.c b/src/unix/tty.c index 32fa37ea..ca108712 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -57,6 +57,7 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { int flags; int newfd; int r; + int saved_flags; char path[256]; /* File descriptors that refer to files cannot be monitored with epoll. @@ -113,6 +114,22 @@ int uv_tty_init(uv_loop_t* loop, uv_tty_t* tty, int fd, int readable) { fd = newfd; } +#if defined(__APPLE__) + /* Save the fd flags in case we need to restore them due to an error. */ + do + saved_flags = fcntl(fd, F_GETFL); + while (saved_flags == -1 && errno == EINTR); + + if (saved_flags == -1) { + if (newfd != -1) + uv__close(newfd); + return -errno; + } +#endif + + /* Pacify the compiler. */ + (void) &saved_flags; + skip: uv__stream_init(loop, (uv_stream_t*) tty, UV_TTY); @@ -120,13 +137,20 @@ skip: * the handle queue, since it was added by uv__handle_init in uv_stream_init. */ + if (!(flags & UV_STREAM_BLOCKING)) + uv__nonblock(fd, 1); + #if defined(__APPLE__) r = uv__stream_try_select((uv_stream_t*) tty, &fd); if (r) { + int rc = r; if (newfd != -1) uv__close(newfd); QUEUE_REMOVE(&tty->handle_queue); - return r; + do + r = fcntl(fd, F_SETFL, saved_flags); + while (r == -1 && errno == EINTR); + return rc; } #endif @@ -135,9 +159,6 @@ skip: else flags |= UV_STREAM_WRITABLE; - if (!(flags & UV_STREAM_BLOCKING)) - uv__nonblock(fd, 1); - uv__stream_open((uv_stream_t*) tty, fd, flags); tty->mode = UV_TTY_MODE_NORMAL; From c5c419f7c8bafb67b5cf077dbf53cf90b2a448e6 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 23 May 2016 20:03:30 +0200 Subject: [PATCH 04/43] unix: allow nesting of kqueue fds in uv_poll_start MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit kqueue file descriptors don't support ioctl(FIONBIO) (or any other ioctl for that matter) so retry using fcntl(F_GETFL) + fcntl(F_SETFL) when we receive a ENOTTY error. Fixes: https://github.com/libuv/libuv/issues/883 PR-URL: https://github.com/libuv/libuv/pull/885 Reviewed-By: Saúl Ibarra Corretgé --- src/unix/core.c | 28 +++++------------------ src/unix/internal.h | 18 +++++++++++++-- src/unix/poll.c | 7 ++++++ test/test-list.h | 14 ++++++++++++ test/test-poll.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 97 insertions(+), 24 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index cdcd0b50..eb6b483a 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,11 +41,8 @@ #include /* getrusage */ #include -#ifdef __linux__ -# include -#endif - #ifdef __sun +# include # include # include #endif @@ -52,7 +50,6 @@ #ifdef __APPLE__ # include /* _NSGetExecutablePath */ # include -# include # if defined(O_CLOEXEC) # define UV__O_CLOEXEC O_CLOEXEC # endif @@ -61,7 +58,6 @@ #if defined(__FreeBSD__) || defined(__DragonFly__) # include # include -# include # include # define UV__O_CLOEXEC O_CLOEXEC # if defined(__FreeBSD__) && __FreeBSD__ >= 10 @@ -74,10 +70,6 @@ # endif #endif -#ifdef _AIX -#include -#endif - #if defined(__ANDROID_API__) && __ANDROID_API__ < 21 # include /* for dlsym */ #endif @@ -523,10 +515,7 @@ int uv__close(int fd) { } -#if defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__) - -int uv__nonblock(int fd, int set) { +int uv__nonblock_ioctl(int fd, int set) { int r; do @@ -540,7 +529,7 @@ int uv__nonblock(int fd, int set) { } -int uv__cloexec(int fd, int set) { +int uv__cloexec_ioctl(int fd, int set) { int r; do @@ -553,10 +542,8 @@ int uv__cloexec(int fd, int set) { return 0; } -#else /* !(defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__)) */ -int uv__nonblock(int fd, int set) { +int uv__nonblock_fcntl(int fd, int set) { int flags; int r; @@ -587,7 +574,7 @@ int uv__nonblock(int fd, int set) { } -int uv__cloexec(int fd, int set) { +int uv__cloexec_fcntl(int fd, int set) { int flags; int r; @@ -617,9 +604,6 @@ int uv__cloexec(int fd, int set) { return 0; } -#endif /* defined(__linux__) || defined(__FreeBSD__) || defined(__APPLE__) || \ - defined(_AIX) || defined(__DragonFly__) */ - /* This function is not execve-safe, there is a race window * between the call to dup() and fcntl(FD_CLOEXEC). diff --git a/src/unix/internal.h b/src/unix/internal.h index 670b14bc..4cae7376 100644 --- a/src/unix/internal.h +++ b/src/unix/internal.h @@ -152,11 +152,25 @@ struct uv__stream_queued_fds_s { }; +#if defined(_AIX) || \ + defined(__APPLE__) || \ + defined(__DragonFly__) || \ + defined(__FreeBSD__) || \ + defined(__linux__) +#define uv__cloexec uv__cloexec_ioctl +#define uv__nonblock uv__nonblock_ioctl +#else +#define uv__cloexec uv__cloexec_fcntl +#define uv__nonblock uv__nonblock_fcntl +#endif + /* core */ -int uv__nonblock(int fd, int set); +int uv__cloexec_ioctl(int fd, int set); +int uv__cloexec_fcntl(int fd, int set); +int uv__nonblock_ioctl(int fd, int set); +int uv__nonblock_fcntl(int fd, int set); int uv__close(int fd); int uv__close_nocheckstdio(int fd); -int uv__cloexec(int fd, int set); int uv__socket(int domain, int type, int protocol); int uv__dup(int fd); ssize_t uv__recvmsg(int fd, struct msghdr *msg, int flags); diff --git a/src/unix/poll.c b/src/unix/poll.c index 0d5944b0..4c0d478e 100644 --- a/src/unix/poll.c +++ b/src/unix/poll.c @@ -59,7 +59,14 @@ int uv_poll_init(uv_loop_t* loop, uv_poll_t* handle, int fd) { if (err) return err; + /* If ioctl(FIONBIO) reports ENOTTY, try fcntl(F_GETFL) + fcntl(F_SETFL). + * Workaround for e.g. kqueue fds not supporting ioctls. + */ err = uv__nonblock(fd, 1); + if (err == -ENOTTY) + if (uv__nonblock == uv__nonblock_ioctl) + err = uv__nonblock_fcntl(fd, 1); + if (err) return err; diff --git a/test/test-list.h b/test/test-list.h index c93f0819..1227da36 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -19,6 +19,8 @@ * IN THE SOFTWARE. */ +#include "uv.h" + TEST_DECLARE (platform_output) TEST_DECLARE (callback_order) TEST_DECLARE (close_order) @@ -314,6 +316,12 @@ TEST_DECLARE (poll_duplex) TEST_DECLARE (poll_unidirectional) TEST_DECLARE (poll_close) TEST_DECLARE (poll_bad_fdtype) +#ifdef __linux__ +TEST_DECLARE (poll_nested_epoll) +#endif +#ifdef UV_HAVE_KQUEUE +TEST_DECLARE (poll_nested_kqueue) +#endif TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) @@ -624,6 +632,12 @@ TASK_LIST_START TEST_ENTRY (poll_unidirectional) TEST_ENTRY (poll_close) TEST_ENTRY (poll_bad_fdtype) +#ifdef __linux__ + TEST_ENTRY (poll_nested_epoll) +#endif +#ifdef UV_HAVE_KQUEUE + TEST_ENTRY (poll_nested_kqueue) +#endif TEST_ENTRY (socket_buffer_size) diff --git a/test/test-poll.c b/test/test-poll.c index f3cfe797..33d0761a 100644 --- a/test/test-poll.c +++ b/test/test-poll.c @@ -31,6 +31,16 @@ #include "uv.h" #include "task.h" +#ifdef __linux__ +# include +#endif + +#ifdef UV_HAVE_KQUEUE +# include +# include +# include +#endif + #define NUM_CLIENTS 5 #define TRANSFER_BYTES (1 << 16) @@ -601,3 +611,47 @@ TEST_IMPL(poll_bad_fdtype) { MAKE_VALGRIND_HAPPY(); return 0; } + + +#ifdef __linux__ +TEST_IMPL(poll_nested_epoll) { + uv_poll_t poll_handle; + int fd; + + fd = epoll_create(1); + ASSERT(fd != -1); + + ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd)); + ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort)); + ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT)); + + uv_close((uv_handle_t*) &poll_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(0 == close(fd)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif /* __linux__ */ + + +#ifdef UV_HAVE_KQUEUE +TEST_IMPL(poll_nested_kqueue) { + uv_poll_t poll_handle; + int fd; + + fd = kqueue(); + ASSERT(fd != -1); + + ASSERT(0 == uv_poll_init(uv_default_loop(), &poll_handle, fd)); + ASSERT(0 == uv_poll_start(&poll_handle, UV_READABLE, (uv_poll_cb) abort)); + ASSERT(0 != uv_run(uv_default_loop(), UV_RUN_NOWAIT)); + + uv_close((uv_handle_t*) &poll_handle, NULL); + ASSERT(0 == uv_run(uv_default_loop(), UV_RUN_DEFAULT)); + ASSERT(0 == close(fd)); + + MAKE_VALGRIND_HAPPY(); + return 0; +} +#endif /* UV_HAVE_KQUEUE */ From bd0e8e82def364fdd2c2cdf5466a362eb25f1210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 23 May 2016 23:23:08 +0200 Subject: [PATCH 05/43] doc: fix generation the first time livehtml runs PR-URL: https://github.com/libuv/libuv/pull/886 Reviewed-By: Ben Noordhuis --- docs/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Makefile b/docs/Makefile index 9d461ff8..d23c6948 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -57,7 +57,7 @@ html: @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." -livehtml: +livehtml: html $(SPHINXAUTOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html dirhtml: From 51d660de00e44f46d8d5222d370e52c99d76d842 Mon Sep 17 00:00:00 2001 From: Santiago Gimeno Date: Mon, 4 Apr 2016 17:59:34 +0200 Subject: [PATCH 06/43] test: fix test_close_accept flakiness on Centos5 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It is not guaranteed which stream will read the data first. PR-URL: https://github.com/libuv/libuv/pull/807 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- test/test-tcp-close-accept.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/test/test-tcp-close-accept.c b/test/test-tcp-close-accept.c index 5517aaf9..0729d46d 100644 --- a/test/test-tcp-close-accept.c +++ b/test/test-tcp-close-accept.c @@ -40,6 +40,7 @@ static unsigned int got_connections; static unsigned int close_cb_called; static unsigned int write_cb_called; static unsigned int read_cb_called; +static unsigned int pending_incoming; static void close_cb(uv_handle_t* handle) { close_cb_called++; @@ -58,8 +59,11 @@ static void connect_cb(uv_connect_t* req, int status) { if (req == &tcp_check_req) { ASSERT(status != 0); - /* Close check and incoming[0], time to finish test */ - uv_close((uv_handle_t*) &tcp_incoming[0], close_cb); + /* + * Time to finish the test: close both the check and pending incoming + * connections + */ + uv_close((uv_handle_t*) &tcp_incoming[pending_incoming], close_cb); uv_close((uv_handle_t*) &tcp_check, close_cb); return; } @@ -84,8 +88,8 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { uv_loop_t* loop; unsigned int i; - /* Only first stream should receive read events */ - ASSERT(stream == (uv_stream_t*) &tcp_incoming[0]); + pending_incoming = (uv_tcp_t*) stream - &tcp_incoming[0]; + ASSERT(pending_incoming < got_connections); ASSERT(0 == uv_read_stop(stream)); ASSERT(1 == nread); @@ -93,8 +97,10 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { read_cb_called++; /* Close all active incomings, except current one */ - for (i = 1; i < got_connections; i++) - uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); + for (i = 0; i < got_connections; i++) { + if (i != pending_incoming) + uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); + } /* Create new fd that should be one of the closed incomings */ ASSERT(0 == uv_tcp_init(loop, &tcp_check)); From f8691366466f020ac94a98fd6c5119938338bcce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 23 May 2016 23:26:12 +0200 Subject: [PATCH 07/43] license: libuv is no longer a Node project PR-URL: https://github.com/libuv/libuv/pull/887 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny --- LICENSE | 3 --- 1 file changed, 3 deletions(-) diff --git a/LICENSE b/LICENSE index 4d411670..cedae346 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,3 @@ -libuv is part of the Node project: http://nodejs.org/ -libuv may be distributed alone under Node's license: - ==== Copyright Joyent, Inc. and other Node contributors. All rights reserved. From acc0175c6c16299ba7c3d37e9bbfe56d0814c0ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 23 May 2016 23:34:01 +0200 Subject: [PATCH 08/43] license: add license text we've been using for a while PR-URL: https://github.com/libuv/libuv/pull/887 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny --- LICENSE | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/LICENSE b/LICENSE index cedae346..41ba44c2 100644 --- a/LICENSE +++ b/LICENSE @@ -1,3 +1,30 @@ +libuv is licensed for use as follows: + +==== +Copyright (c) 2015-present libuv project contributors. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to +deal in the Software without restriction, including without limitation the +rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +sell copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +IN THE SOFTWARE. +==== + +This license applies to parts of libuv originating from the +https://github.com/joyent/libuv repository: + ==== Copyright Joyent, Inc. and other Node contributors. All rights reserved. From 8b3176933d316e2de0eb4606e4afcac8c6a465ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Mon, 23 May 2016 23:39:46 +0200 Subject: [PATCH 09/43] doc: add licensing information to README PR-URL: https://github.com/libuv/libuv/pull/887 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index e94fcc90..1b40e76e 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,10 @@ Starting with version 1.0.0 libuv follows the [semantic versioning](http://semve scheme. The API change and backwards compatibility rules are those indicated by SemVer. libuv will keep a stable ABI across major releases. +## Licensing + +libuv is licensed under the MIT license. Check the [LICENSE file](LICENSE). + ## Community * [Mailing list](http://groups.google.com/group/libuv) From 6cf935b1eac69c9d7ab889469f524a795213e5ac Mon Sep 17 00:00:00 2001 From: Miodrag Milanovic Date: Sat, 28 May 2016 12:38:07 +0200 Subject: [PATCH 10/43] win,pipe: fixed formatting, DWORD is long unsigned MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/890 Reviewed-By: Saúl Ibarra Corretgé --- src/win/pipe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/win/pipe.c b/src/win/pipe.c index a784325c..2a949e79 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -85,7 +85,7 @@ static void eof_timer_close_cb(uv_handle_t* handle); static void uv_unique_pipe_name(char* ptr, char* name, size_t size) { - snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%u", ptr, GetCurrentProcessId()); + snprintf(name, size, "\\\\?\\pipe\\uv\\%p-%lu", ptr, GetCurrentProcessId()); } From 399e2c814019dfeeec45f2de0ecbb0893ebb5126 Mon Sep 17 00:00:00 2001 From: Jason Ginchereau Date: Sat, 30 Apr 2016 16:56:56 -0700 Subject: [PATCH 11/43] win: support sub-second precision in uv_fs_futimes() Fixes: https://github.com/libuv/libuv/issues/800 PR-URL: https://github.com/libuv/libuv/pull/849 Reviewed-by: Bert Belder --- docs/src/fs.rst | 2 ++ src/win/fs.c | 6 +++--- test/test-fs.c | 22 ++++++++++++++++++++-- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 69e283f4..918bff94 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -258,6 +258,8 @@ API Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively. + .. versionchanged:: 1.10.0 sub-second precission is supported on Windows + .. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) Equivalent to :man:`link(2)`. diff --git a/src/win/fs.c b/src/win/fs.c index 54dfea72..24c60847 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -94,7 +94,7 @@ #define TIME_T_TO_FILETIME(time, filetime_ptr) \ do { \ - uint64_t bigtime = ((int64_t) (time) * 10000000LL) + \ + uint64_t bigtime = ((uint64_t) ((time) * 10000000ULL)) + \ 116444736000000000ULL; \ (filetime_ptr)->dwLowDateTime = bigtime & 0xFFFFFFFF; \ (filetime_ptr)->dwHighDateTime = bigtime >> 32; \ @@ -1429,8 +1429,8 @@ static void fs__fchmod(uv_fs_t* req) { INLINE static int fs__utime_handle(HANDLE handle, double atime, double mtime) { FILETIME filetime_a, filetime_m; - TIME_T_TO_FILETIME((time_t) atime, &filetime_a); - TIME_T_TO_FILETIME((time_t) mtime, &filetime_m); + TIME_T_TO_FILETIME(atime, &filetime_a); + TIME_T_TO_FILETIME(mtime, &filetime_m); if (!SetFileTime(handle, NULL, &filetime_a, &filetime_m)) { return -1; diff --git a/test/test-fs.c b/test/test-fs.c index 1cc1a7c0..250d1350 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -662,8 +662,8 @@ static void check_utime(const char* path, double atime, double mtime) { ASSERT(req.result == 0); s = &req.statbuf; - ASSERT(s->st_atim.tv_sec == atime); - ASSERT(s->st_mtim.tv_sec == mtime); + ASSERT(s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime); + ASSERT(s->st_mtim.tv_sec + (s->st_mtim.tv_nsec / 1000000000.0) == mtime); uv_fs_req_cleanup(&req); } @@ -1968,6 +1968,15 @@ TEST_IMPL(fs_utime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + /* + * Test sub-second timestamps only on Windows (assuming NTFS). Some other + * platforms support sub-second timestamps, but that support is filesystem- + * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. + */ +#ifdef _WIN32 + mtime += 0.444; /* 1982-09-10 11:22:33.444 */ +#endif + r = uv_fs_utime(NULL, &req, path, atime, mtime, NULL); ASSERT(r == 0); ASSERT(req.result == 0); @@ -2055,6 +2064,15 @@ TEST_IMPL(fs_futime) { atime = mtime = 400497753; /* 1982-09-10 11:22:33 */ + /* + * Test sub-second timestamps only on Windows (assuming NTFS). Some other + * platforms support sub-second timestamps, but that support is filesystem- + * dependent. Notably OS X (HFS Plus) does NOT support sub-second timestamps. + */ +#ifdef _WIN32 + mtime += 0.444; /* 1982-09-10 11:22:33.444 */ +#endif + r = uv_fs_open(NULL, &req, path, O_RDWR, 0, NULL); ASSERT(r >= 0); ASSERT(req.result >= 0); From 193a6f9b93b8b50f9fa9290b207a3513480c4f94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Sun, 29 May 2016 11:50:54 +0200 Subject: [PATCH 12/43] unix: ignore EINPROGRESS in uv__close It's just an indicator that the operation will happen later, so return success. PR-URL: https://github.com/libuv/libuv/pull/892 Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis --- src/unix/core.c | 4 ++-- src/unix/fs.c | 2 +- src/unix/process.c | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/unix/core.c b/src/unix/core.c index eb6b483a..64522383 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -500,8 +500,8 @@ int uv__close_nocheckstdio(int fd) { rc = close(fd); if (rc == -1) { rc = -errno; - if (rc == -EINTR) - rc = -EINPROGRESS; /* For platform/libc consistency. */ + if (rc == -EINTR || rc == -EINPROGRESS) + rc = 0; /* The close is in progress, not an error. */ errno = saved_errno; } diff --git a/src/unix/fs.c b/src/unix/fs.c index 085970a0..fed15d5e 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -251,7 +251,7 @@ static ssize_t uv__fs_open(uv_fs_t* req) { */ if (r >= 0 && uv__cloexec(r, 1) != 0) { r = uv__close(r); - if (r != 0 && r != -EINPROGRESS) + if (r != 0) abort(); r = -1; } diff --git a/src/unix/process.c b/src/unix/process.c index ef10a342..8a010edc 100644 --- a/src/unix/process.c +++ b/src/unix/process.c @@ -232,7 +232,7 @@ static int uv__process_open_stream(uv_stdio_container_t* container, return 0; err = uv__close(pipefds[1]); - if (err != 0 && err != -EINPROGRESS) + if (err != 0) abort(); pipefds[1] = -1; From 422bc5f16814e4d123077b8ed119f30d1c49d8ca Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Mon, 30 May 2016 11:21:00 -0400 Subject: [PATCH 13/43] doc: add Imran Iqbal (iWuzHere) to maintainers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/894 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- MAINTAINERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 80f63fd6..420e4498 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -10,6 +10,7 @@ libuv is currently managed by the following individuals: - GPG key: 94AE 3667 5C46 4D64 BAFA 68DD 7434 390B DBE9 B9C5 (pubkey-cjihrig) * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) +* **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) - GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul) From 71bd07e588942b95009fbe055d4ae8cafe6532fa Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Tue, 31 May 2016 14:16:07 -0400 Subject: [PATCH 14/43] doc: update docs with AIX related information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/libuv/libuv/issues/882 PR-URL: https://github.com/libuv/libuv/pull/896 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- docs/src/fs.rst | 4 ++++ docs/src/fs_event.rst | 14 ++++++++++++++ 2 files changed, 18 insertions(+) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 918bff94..f810319c 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -258,6 +258,10 @@ API Equivalent to :man:`utime(2)` and :man:`futime(2)` respectively. + .. note:: + AIX: This function only works for AIX 7.1 and newer. It can still be called on older + versions but will return ``UV_ENOSYS``. + .. versionchanged:: 1.10.0 sub-second precission is supported on Windows .. c:function:: int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb) diff --git a/docs/src/fs_event.rst b/docs/src/fs_event.rst index c2d7f520..c08ade2e 100644 --- a/docs/src/fs_event.rst +++ b/docs/src/fs_event.rst @@ -8,6 +8,20 @@ FS Event handles allow the user to monitor a given path for changes, for example if the file was renamed or there was a generic change in it. This handle uses the best backend for the job on each platform. +.. note:: + For AIX, the non default IBM bos.ahafs package has to be installed. + The AIX Event Infrastructure file system (ahafs) has some limitations: + + - ahafs tracks monitoring per process and is not thread safe. A separate process + must be spawned for each monitor for the same event. + - Events for file modification (writing to a file) are not received if only the + containing folder is watched. + + See documentation_ for more details. + + .. _documentation: http://www.ibm.com/developerworks/aix/library/au-aix_event_infrastructure/ + + Data types ---------- From 89f01a41ab71b3f539247bfb54e15f8dc2c395f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A1ri=20Tristan=20Helgason?= Date: Mon, 30 May 2016 08:36:36 +0000 Subject: [PATCH 15/43] test: silence build warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/893 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Johan Bergström Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 2 +- test/test-list.h | 4 ++-- test/test-platform-output.c | 2 -- test/test-poll-close-doesnt-corrupt-stack.c | 10 ++++++---- test/test-poll-closesocket.c | 8 ++++++-- uv.gyp | 1 + 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/Makefile.am b/Makefile.am index 05ccd58a..3670ad46 100644 --- a/Makefile.am +++ b/Makefile.am @@ -128,7 +128,7 @@ EXTRA_DIST = test/fixtures/empty_file \ TESTS = test/run-tests check_PROGRAMS = test/run-tests -test_run_tests_CFLAGS = +test_run_tests_CFLAGS = -Wno-long-long test_run_tests_LDFLAGS = test_run_tests_SOURCES = test/blackhole-server.c \ test/dns-server.c \ diff --git a/test/test-list.h b/test/test-list.h index 1227da36..3d99c266 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -326,9 +326,9 @@ TEST_DECLARE (poll_nested_kqueue) TEST_DECLARE (ip4_addr) TEST_DECLARE (ip6_addr_link_local) -#ifdef _WIN32 TEST_DECLARE (poll_close_doesnt_corrupt_stack) TEST_DECLARE (poll_closesocket) +#ifdef _WIN32 TEST_DECLARE (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) TEST_DECLARE (argument_escaping) @@ -669,9 +669,9 @@ TASK_LIST_START TEST_ENTRY (fs_poll_getpath) TEST_ENTRY (kill) -#ifdef _WIN32 TEST_ENTRY (poll_close_doesnt_corrupt_stack) TEST_ENTRY (poll_closesocket) +#ifdef _WIN32 TEST_ENTRY (spawn_detect_pipe_name_collisions_on_windows) #if !defined(USING_UV_SHARED) TEST_ENTRY (argument_escaping) diff --git a/test/test-platform-output.c b/test/test-platform-output.c index bd61454f..b8955080 100644 --- a/test/test-platform-output.c +++ b/test/test-platform-output.c @@ -61,8 +61,6 @@ TEST_IMPL(platform_output) { ASSERT(rusage.ru_utime.tv_usec >= 0); ASSERT(rusage.ru_stime.tv_sec >= 0); ASSERT(rusage.ru_stime.tv_usec >= 0); - ASSERT(rusage.ru_majflt >= 0); - ASSERT(rusage.ru_maxrss >= 0); printf("uv_getrusage:\n"); printf(" user: %llu sec %llu microsec\n", (unsigned long long) rusage.ru_utime.tv_sec, diff --git a/test/test-poll-close-doesnt-corrupt-stack.c b/test/test-poll-close-doesnt-corrupt-stack.c index fc2cc004..1dfc80e3 100644 --- a/test/test-poll-close-doesnt-corrupt-stack.c +++ b/test/test-poll-close-doesnt-corrupt-stack.c @@ -19,8 +19,6 @@ * IN THE SOFTWARE. */ -#ifdef _WIN32 - #include #include @@ -37,6 +35,7 @@ uv_os_sock_t sock; uv_poll_t handle; +#ifdef _WIN32 static int close_cb_called = 0; @@ -69,9 +68,13 @@ static void NO_INLINE close_socket_and_verify_stack() { for (i = 0; i < ARRAY_SIZE(data); i++) ASSERT(data[i] == MARKER); } +#endif TEST_IMPL(poll_close_doesnt_corrupt_stack) { +#ifndef _WIN32 + RETURN_SKIP("Test only relevant on Windows"); +#else struct WSAData wsa_data; int r; unsigned long on; @@ -109,6 +112,5 @@ TEST_IMPL(poll_close_doesnt_corrupt_stack) { MAKE_VALGRIND_HAPPY(); return 0; +#endif } - -#endif /* _WIN32 */ diff --git a/test/test-poll-closesocket.c b/test/test-poll-closesocket.c index 4db74a01..ecaa9e54 100644 --- a/test/test-poll-closesocket.c +++ b/test/test-poll-closesocket.c @@ -19,7 +19,6 @@ * IN THE SOFTWARE. */ -#ifdef _WIN32 #include @@ -29,6 +28,7 @@ uv_os_sock_t sock; uv_poll_t handle; +#ifdef _WIN32 static int close_cb_called = 0; @@ -50,9 +50,13 @@ static void poll_cb(uv_poll_t* h, int status, int events) { uv_close((uv_handle_t*) &handle, close_cb); } +#endif TEST_IMPL(poll_closesocket) { +#ifndef _WIN32 + RETURN_SKIP("Test only relevant on Windows"); +#else struct WSAData wsa_data; int r; unsigned long on; @@ -85,5 +89,5 @@ TEST_IMPL(poll_closesocket) { MAKE_VALGRIND_HAPPY(); return 0; -} #endif +} diff --git a/uv.gyp b/uv.gyp index 2fdd59ac..aa4a4244 100644 --- a/uv.gyp +++ b/uv.gyp @@ -426,6 +426,7 @@ 'libraries': [ '-lws2_32' ] }, { # POSIX 'defines': [ '_GNU_SOURCE' ], + 'cflags': [ '-Wno-long-long' ], 'sources': [ 'test/runner-unix.c', 'test/runner-unix.h', From 5af420669a40974ce91dd66c51f779fd66c19f63 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Wed, 8 Jun 2016 17:18:37 -0400 Subject: [PATCH 16/43] doc: add iWuzHere GPG ID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/902 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- MAINTAINERS.md | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS.md b/MAINTAINERS.md index 420e4498..5974d9d3 100644 --- a/MAINTAINERS.md +++ b/MAINTAINERS.md @@ -11,6 +11,7 @@ libuv is currently managed by the following individuals: * **Fedor Indutny** ([@indutny](https://github.com/indutny)) - GPG key: AF2E EA41 EC34 47BF DD86 FED9 D706 3CCE 19B7 E890 (pubkey-indutny) * **Imran Iqbal** ([@iWuzHere](https://github.com/iWuzHere)) + - GPG key: 9DFE AA5F 481B BF77 2D90 03CE D592 4925 2F8E C41A (pubkey-iwuzhere) * **Saúl Ibarra Corretgé** ([@saghul](https://github.com/saghul)) - GPG key: FDF5 1936 4458 319F A823 3DC9 410E 5553 AE9B C059 (pubkey-saghul) From c4e917790ed17c3452e4a97e74fd3b7d60a004e0 Mon Sep 17 00:00:00 2001 From: Nicolas Cavallari Date: Wed, 8 Jun 2016 14:33:58 +0200 Subject: [PATCH 17/43] linux-core: fix uv_get_total/free_memory on uclibc MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The _SC_PHYS_PAGES and _SC_AVPHYS_PAGES are not POSIX sysconf values, so the standart C libraries have no obligation to support it, even on Linux. Use the Linux sysinfo() system call instead. PR-URL: https://github.com/libuv/libuv/pull/901 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- src/unix/linux-core.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index b48a1111..ae927b7e 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -484,12 +484,20 @@ int uv_exepath(char* buffer, size_t* size) { uint64_t uv_get_free_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_AVPHYS_PAGES); + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.freeram * info.mem_unit; + return 0; } uint64_t uv_get_total_memory(void) { - return (uint64_t) sysconf(_SC_PAGESIZE) * sysconf(_SC_PHYS_PAGES); + struct sysinfo info; + + if (sysinfo(&info) == 0) + return (uint64_t) info.totalram * info.mem_unit; + return 0; } From 0c82efa4d5e949318909786ac5e8c00376ccc76d Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Sun, 22 May 2016 23:51:51 +0200 Subject: [PATCH 18/43] build: fix build on DragonFly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/884 Reviewed-By: Ben Noordhuis Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile.am b/Makefile.am index 3670ad46..882bbef5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -312,6 +312,7 @@ endif if DRAGONFLY include_HEADERS += include/uv-bsd.h +libuv_la_SOURCES += src/unix/freebsd.c src/unix/kqueue.c test_run_tests_LDFLAGS += -lutil endif From 96b37293a9a6a4f100e117b9760aaac3e39f94ee Mon Sep 17 00:00:00 2001 From: Michael Neumann Date: Mon, 23 May 2016 00:02:54 +0200 Subject: [PATCH 19/43] unix: correctly detect named pipes on DragonFly MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This fixes test-stdio-over-pipes and test-pipe-sendmsg test cases. ~~~~ Assertion failed in test/test-stdio-over-pipes.c on line 56: term_signal == 0 Assertion failed in test/test-pipe-sendmsg.c on line 86: pending == UV_NAMED_PIPE ~~~~ This fixes a longstanding issue with nodejs on DragonFly, which was triggered whenever spawning a process and pipes were involed. PR-URL: https://github.com/libuv/libuv/pull/884 Reviewed-By: Ben Noordhuis Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- src/unix/stream.c | 4 ++-- src/unix/tty.c | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index 7dbc556f..eaec92bb 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -962,8 +962,8 @@ uv_handle_type uv__handle_type(int fd) { return UV_UNKNOWN_HANDLE; if (type == SOCK_STREAM) { -#if defined(_AIX) - /* on AIX the getsockname call returns an empty sa structure +#if defined(_AIX) || defined(__DragonFly__) + /* on AIX/DragonFly the getsockname call returns an empty sa structure * for sockets of type AF_UNIX. For all other types it will * return a properly filled in structure. */ diff --git a/src/unix/tty.c b/src/unix/tty.c index ca108712..a56afe18 100644 --- a/src/unix/tty.c +++ b/src/unix/tty.c @@ -289,14 +289,14 @@ uv_handle_type uv_guess_handle(uv_file file) { return UV_UDP; if (type == SOCK_STREAM) { -#if defined(_AIX) - /* on AIX the getsockname call returns an empty sa structure +#if defined(_AIX) || defined(__DragonFly__) + /* on AIX/DragonFly the getsockname call returns an empty sa structure * for sockets of type AF_UNIX. For all other types it will * return a properly filled in structure. */ if (len == 0) return UV_NAMED_PIPE; -#endif /* defined(_AIX) */ +#endif /* defined(_AIX) || defined(__DragonFly__) */ if (sa.sa_family == AF_INET || sa.sa_family == AF_INET6) return UV_TCP; From cc1d38ea933e457b7a075b5a26822936aae1ce34 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 6 Jun 2016 14:39:05 +0200 Subject: [PATCH 20/43] test: make tap output the default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the non-tap output, it's sometimes difficult to distinguish skipped tests from test failures. PR-URL: https://github.com/libuv/libuv/pull/898 Reviewed-By: Saúl Ibarra Corretgé --- test/runner-unix.c | 9 +------ test/runner-win.c | 31 ++++++++-------------- test/runner.c | 64 +++------------------------------------------- test/runner.h | 3 --- 4 files changed, 15 insertions(+), 92 deletions(-) diff --git a/test/runner-unix.c b/test/runner-unix.c index 2405fa87..69b81b21 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -43,11 +43,6 @@ /* Do platform-specific initialization. */ int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - /* Disable stdio output buffering. */ setvbuf(stdout, NULL, _IONBF, 0); setvbuf(stderr, NULL, _IONBF, 0); @@ -310,9 +305,7 @@ int process_copy_output(process_info_t *p, int fd) { /* TODO: what if write doesn't write the whole buffer... */ nwritten = 0; - if (tap_output) - nwritten += write(fd, "#", 1); - + nwritten += write(fd, "#", 1); nwritten += write(fd, buf, strlen(buf)); if (nwritten < 0) { diff --git a/test/runner-win.c b/test/runner-win.c index 97ef7599..c2a45828 100644 --- a/test/runner-win.c +++ b/test/runner-win.c @@ -44,11 +44,6 @@ /* Do platform-specific initialization. */ int platform_init(int argc, char **argv) { - const char* tap; - - tap = getenv("UV_TAP_OUTPUT"); - tap_output = (tap != NULL && atoi(tap) > 0); - /* Disable the "application crashed" popup. */ SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX); @@ -225,29 +220,23 @@ int process_copy_output(process_info_t *p, int fd) { return -1; } - if (tap_output) - write(fd, "#", 1); + write(fd, "#", 1); while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) && read > 0) { - if (tap_output) { - start = buf; + start = buf; - while ((line = strchr(start, '\n')) != NULL) { - write(fd, start, line - start + 1); - write(fd, "#", 1); - start = line + 1; - } - - if (start < buf + read) - write(fd, start, buf + read - start); - } else { - write(fd, buf, read); + while ((line = strchr(start, '\n')) != NULL) { + write(fd, start, line - start + 1); + write(fd, "#", 1); + start = line + 1; } + + if (start < buf + read) + write(fd, start, buf + read - start); } - if (tap_output) - write(fd, "\n", 1); + write(fd, "\n", 1); if (GetLastError() != ERROR_HANDLE_EOF) return -1; diff --git a/test/runner.c b/test/runner.c index c616d176..ef3fda57 100644 --- a/test/runner.c +++ b/test/runner.c @@ -28,31 +28,6 @@ char executable_path[sizeof(executable_path)]; -int tap_output = 0; - - -static void log_progress(int total, - int passed, - int failed, - int todos, - int skipped, - const char* name) { - int progress; - - if (total == 0) - total = 1; - - progress = 100 * (passed + failed + skipped + todos) / total; - fprintf(stderr, "[%% %3d|+ %3d|- %3d|T %3d|S %3d]: %s", - progress, - passed, - failed, - todos, - skipped, - name); - fflush(stderr); -} - const char* fmt(double d) { static char buf[1024]; @@ -109,10 +84,8 @@ int run_tests(int benchmark_output) { } } - if (tap_output) { - fprintf(stderr, "1..%d\n", total); - fflush(stderr); - } + fprintf(stderr, "1..%d\n", total); + fflush(stderr); /* Run all tests. */ passed = 0; @@ -125,13 +98,6 @@ int run_tests(int benchmark_output) { continue; } - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, task->task_name); - } - test_result = run_test(task->task_name, benchmark_output, current); switch (test_result) { case TEST_OK: passed++; break; @@ -142,13 +108,6 @@ int run_tests(int benchmark_output) { current++; } - if (!tap_output) - rewind_cursor(); - - if (!benchmark_output && !tap_output) { - log_progress(total, passed, failed, todos, skipped, "Done.\n"); - } - return failed; } @@ -319,22 +278,11 @@ out: FATAL("process_wait failed"); } - if (tap_output) - log_tap_result(test_count, test, status, &processes[i]); + log_tap_result(test_count, test, status, &processes[i]); /* Show error and output from processes if the test failed. */ if (status != 0 || task->show_output) { - if (tap_output) { - fprintf(stderr, "#"); - } else if (status == TEST_TODO) { - fprintf(stderr, "\n`%s` todo\n", test); - } else if (status == TEST_SKIP) { - fprintf(stderr, "\n`%s` skipped\n", test); - } else if (status != 0) { - fprintf(stderr, "\n`%s` failed: %s\n", test, errmsg); - } else { - fprintf(stderr, "\n"); - } + fprintf(stderr, "#"); fflush(stderr); for (i = 0; i < process_count; i++) { @@ -359,10 +307,6 @@ out: } } - if (!tap_output) { - fprintf(stderr, "=============================================================\n"); - } - /* In benchmark mode show concise output from the main process. */ } else if (benchmark_output) { switch (process_output_size(main_proc)) { diff --git a/test/runner.h b/test/runner.h index 78f3c880..85174478 100644 --- a/test/runner.h +++ b/test/runner.h @@ -172,7 +172,4 @@ void process_cleanup(process_info_t *p); /* Move the console cursor one line up and back to the first column. */ void rewind_cursor(void); -/* trigger output as tap */ -extern int tap_output; - #endif /* RUNNER_H_ */ From dd9f751eadffdc63f25917f1cb8859707b90d3de Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 6 Jun 2016 14:45:40 +0200 Subject: [PATCH 21/43] test: don't dump output for skipped tests MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A skipped test already prints a diagnostic. Dumping its output just prints the same message twice. PR-URL: https://github.com/libuv/libuv/pull/898 Reviewed-By: Saúl Ibarra Corretgé --- test/runner.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/runner.c b/test/runner.c index ef3fda57..ee87a298 100644 --- a/test/runner.c +++ b/test/runner.c @@ -281,7 +281,7 @@ out: log_tap_result(test_count, test, status, &processes[i]); /* Show error and output from processes if the test failed. */ - if (status != 0 || task->show_output) { + if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) { fprintf(stderr, "#"); fflush(stderr); From b936ace934abcebad19b9bc0089998cc89e151af Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 6 Jun 2016 14:47:51 +0200 Subject: [PATCH 22/43] test: improve formatting of diagnostic messages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Put a space after the '#' and handle messages with newlines. PR-URL: https://github.com/libuv/libuv/pull/898 Reviewed-By: Saúl Ibarra Corretgé --- test/runner-unix.c | 17 +++-------------- test/runner-win.c | 22 +++------------------- test/runner.c | 24 +++++++++++++++++++++--- test/runner.h | 6 ++++-- 4 files changed, 31 insertions(+), 38 deletions(-) diff --git a/test/runner-unix.c b/test/runner-unix.c index 69b81b21..0edd671b 100644 --- a/test/runner-unix.c +++ b/test/runner-unix.c @@ -289,8 +289,7 @@ long int process_output_size(process_info_t *p) { /* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd) { - ssize_t nwritten; +int process_copy_output(process_info_t* p, FILE* stream) { char buf[1024]; int r; @@ -301,18 +300,8 @@ int process_copy_output(process_info_t *p, int fd) { } /* TODO: what if the line is longer than buf */ - while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) { - /* TODO: what if write doesn't write the whole buffer... */ - nwritten = 0; - - nwritten += write(fd, "#", 1); - nwritten += write(fd, buf, strlen(buf)); - - if (nwritten < 0) { - perror("write"); - return -1; - } - } + while (fgets(buf, sizeof(buf), p->stdout_file) != NULL) + print_lines(buf, strlen(buf), stream); if (ferror(p->stdout_file)) { perror("read"); diff --git a/test/runner-win.c b/test/runner-win.c index c2a45828..1b4a569a 100644 --- a/test/runner-win.c +++ b/test/runner-win.c @@ -208,10 +208,9 @@ long int process_output_size(process_info_t *p) { } -int process_copy_output(process_info_t *p, int fd) { +int process_copy_output(process_info_t* p, FILE* stream) { DWORD read; char buf[1024]; - char *line, *start; if (SetFilePointer(p->stdio_out, 0, @@ -220,23 +219,8 @@ int process_copy_output(process_info_t *p, int fd) { return -1; } - write(fd, "#", 1); - - while (ReadFile(p->stdio_out, (void*)&buf, sizeof(buf), &read, NULL) && - read > 0) { - start = buf; - - while ((line = strchr(start, '\n')) != NULL) { - write(fd, start, line - start + 1); - write(fd, "#", 1); - start = line + 1; - } - - if (start < buf + read) - write(fd, start, buf + read - start); - } - - write(fd, "\n", 1); + while (ReadFile(p->stdio_out, &buf, sizeof(buf), &read, NULL) && read > 0) + print_lines(buf, read, stream); if (GetLastError() != ERROR_HANDLE_EOF) return -1; diff --git a/test/runner.c b/test/runner.c index ee87a298..f611ae28 100644 --- a/test/runner.c +++ b/test/runner.c @@ -282,7 +282,7 @@ out: /* Show error and output from processes if the test failed. */ if ((status != TEST_OK && status != TEST_SKIP) || task->show_output) { - fprintf(stderr, "#"); + fprintf(stderr, "# "); fflush(stderr); for (i = 0; i < process_count; i++) { @@ -302,7 +302,7 @@ out: default: fprintf(stderr, "Output from process `%s`:\n", process_get_name(&processes[i])); fflush(stderr); - process_copy_output(&processes[i], fileno(stderr)); + process_copy_output(&processes[i], stderr); break; } } @@ -322,7 +322,7 @@ out: default: for (i = 0; i < process_count; i++) { - process_copy_output(&processes[i], fileno(stderr)); + process_copy_output(&processes[i], stderr); } break; } @@ -408,3 +408,21 @@ void print_tests(FILE* stream) { } } } + + +void print_lines(const char* buffer, size_t size, FILE* stream) { + const char* start; + const char* end; + + start = buffer; + while ((end = memchr(start, '\n', &buffer[size] - start))) { + fprintf(stream, "# %.*s\n", (int) (end - start), start); + fflush(stream); + start = end + 1; + } + + if (start < &buffer[size]) { + fprintf(stream, "# %s\n", start); + fflush(stream); + } +} diff --git a/test/runner.h b/test/runner.h index 85174478..555f2f8e 100644 --- a/test/runner.h +++ b/test/runner.h @@ -126,6 +126,8 @@ int run_test_part(const char* test, const char* part); */ void print_tests(FILE* stream); +/* Print lines in |buffer| as TAP diagnostics to |stream|. */ +void print_lines(const char* buffer, size_t size, FILE* stream); /* * Stuff that should be implemented by test-runner-.h @@ -148,8 +150,8 @@ int process_wait(process_info_t *vec, int n, int timeout); /* Returns the number of bytes in the stdio output buffer for process `p`. */ long int process_output_size(process_info_t *p); -/* Copy the contents of the stdio output buffer to `fd`. */ -int process_copy_output(process_info_t *p, int fd); +/* Copy the contents of the stdio output buffer to `stream`. */ +int process_copy_output(process_info_t* p, FILE* stream); /* Copy the last line of the stdio output buffer to `buffer` */ int process_read_last_line(process_info_t *p, From 7e7e22126008813a187aa95041ae95f03afc3c5b Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Mon, 6 Jun 2016 15:37:42 +0200 Subject: [PATCH 23/43] test: remove unused RETURN_TODO macro MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/898 Reviewed-By: Saúl Ibarra Corretgé --- test/runner.c | 10 +--------- test/task.h | 8 -------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/test/runner.c b/test/runner.c index f611ae28..5e22c18f 100644 --- a/test/runner.c +++ b/test/runner.c @@ -70,7 +70,6 @@ int run_tests(int benchmark_output) { int total; int passed; int failed; - int todos; int skipped; int current; int test_result; @@ -90,7 +89,6 @@ int run_tests(int benchmark_output) { /* Run all tests. */ passed = 0; failed = 0; - todos = 0; skipped = 0; current = 1; for (task = TASKS; task->main; task++) { @@ -101,7 +99,6 @@ int run_tests(int benchmark_output) { test_result = run_test(task->task_name, benchmark_output, current); switch (test_result) { case TEST_OK: passed++; break; - case TEST_TODO: todos++; break; case TEST_SKIP: skipped++; break; default: failed++; } @@ -125,10 +122,6 @@ void log_tap_result(int test_count, result = "ok"; directive = ""; break; - case TEST_TODO: - result = "not ok"; - directive = " # TODO "; - break; case TEST_SKIP: result = "ok"; directive = " # SKIP "; @@ -138,8 +131,7 @@ void log_tap_result(int test_count, directive = ""; } - if ((status == TEST_SKIP || status == TEST_TODO) && - process_output_size(process) > 0) { + if (status == TEST_SKIP && process_output_size(process) > 0) { process_read_last_line(process, reason, sizeof reason); } else { reason[0] = '\0'; diff --git a/test/task.h b/test/task.h index 96cc6377..65a1132e 100644 --- a/test/task.h +++ b/test/task.h @@ -136,7 +136,6 @@ const char* fmt(double d); /* Reserved test exit codes. */ enum test_status { TEST_OK = 0, - TEST_TODO, TEST_SKIP }; @@ -145,13 +144,6 @@ enum test_status { return TEST_OK; \ } while (0) -#define RETURN_TODO(explanation) \ - do { \ - fprintf(stderr, "%s\n", explanation); \ - fflush(stderr); \ - return TEST_TODO; \ - } while (0) - #define RETURN_SKIP(explanation) \ do { \ fprintf(stderr, "%s\n", explanation); \ From 23043a7e95c93c35d076211a640427ce69f0cb96 Mon Sep 17 00:00:00 2001 From: Pierre-Marie de Rodat Date: Mon, 13 Jun 2016 08:15:33 +0200 Subject: [PATCH 24/43] doc: fix stream typos MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/910 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- docs/src/stream.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/src/stream.rst b/docs/src/stream.rst index ed0c79d0..dfcad0fa 100644 --- a/docs/src/stream.rst +++ b/docs/src/stream.rst @@ -61,7 +61,7 @@ Data types .. c:type:: void (*uv_shutdown_cb)(uv_shutdown_t* req, int status) - Callback called after s shutdown request has been completed. `status` will + Callback called after a shutdown request has been completed. `status` will be 0 in case of success, < 0 otherwise. .. c:type:: void (*uv_connection_cb)(uv_stream_t* server, int status) @@ -92,7 +92,7 @@ Public members .. c:member:: uv_stream_t* uv_write_t.send_handle - Pointer to the stream being sent using this write request.. + Pointer to the stream being sent using this write request. .. seealso:: The :c:type:`uv_handle_t` members also apply. From e2da05669812ab0385870b9e293ae1cf4425bebb Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Fri, 10 Jun 2016 18:41:49 -0400 Subject: [PATCH 25/43] doc: update coding style link MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/909 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ef5c2b2f..aa97506d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -165,5 +165,5 @@ not send out notifications when you add commits. [issue tracker]: https://github.com/libuv/libuv/issues [libuv mailing list]: http://groups.google.com/group/libuv [IRC]: http://webchat.freelibuv.net/?channels=libuv -[Google C/C++ style guide]: http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml +[Google C/C++ style guide]: https://google.github.io/styleguide/cppguide.html [project maintainers]: https://github.com/libuv/libuv/blob/master/MAINTAINERS.md From fcfe230130b26a943fd5fd4b390c484a5ab308f4 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Tue, 14 Jun 2016 15:17:43 -0400 Subject: [PATCH 26/43] unix,fs: use uint64_t instead of unsigned long MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `unsigned long` is not guaranteed to be 8 bytes long. This prevents overflow errors from occurring as seen in issue #913 Fixes: https://github.com/libuv/libuv/issues/913 PR-URL: https://github.com/libuv/libuv/pull/914 Reviewed-By: Saúl Ibarra Corretgé Reviewed-By: Colin Ihrig Reviewed-By: Ben Noordhuis --- src/unix/fs.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index fed15d5e..508b748a 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -151,9 +151,9 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { goto skip; ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; + ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; + ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; r = uv__utimesat(req->file, NULL, ts, 0); if (r == 0) @@ -167,9 +167,9 @@ static ssize_t uv__fs_futime(uv_fs_t* req) { skip: tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; + tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; + tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; snprintf(path, sizeof(path), "/proc/self/fd/%d", (int) req->file); r = utimes(path, tv); @@ -198,9 +198,9 @@ skip: || defined(__sun) struct timeval tv[2]; tv[0].tv_sec = req->atime; - tv[0].tv_usec = (unsigned long)(req->atime * 1000000) % 1000000; + tv[0].tv_usec = (uint64_t)(req->atime * 1000000) % 1000000; tv[1].tv_sec = req->mtime; - tv[1].tv_usec = (unsigned long)(req->mtime * 1000000) % 1000000; + tv[1].tv_usec = (uint64_t)(req->mtime * 1000000) % 1000000; # if defined(__sun) return futimesat(req->file, NULL, tv); # else @@ -209,9 +209,9 @@ skip: #elif defined(_AIX71) struct timespec ts[2]; ts[0].tv_sec = req->atime; - ts[0].tv_nsec = (unsigned long)(req->atime * 1000000) % 1000000 * 1000; + ts[0].tv_nsec = (uint64_t)(req->atime * 1000000) % 1000000 * 1000; ts[1].tv_sec = req->mtime; - ts[1].tv_nsec = (unsigned long)(req->mtime * 1000000) % 1000000 * 1000; + ts[1].tv_nsec = (uint64_t)(req->mtime * 1000000) % 1000000 * 1000; return futimens(req->file, ts); #else errno = ENOSYS; From 9940b84041402f85ec90596a47ea5c4dec6efd14 Mon Sep 17 00:00:00 2001 From: Imran Iqbal Date: Mon, 13 Jun 2016 14:55:41 -0400 Subject: [PATCH 27/43] build: check for warnings for -fvisibility=hidden MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/libuv/libuv/issues/911 PR-URL: https://github.com/libuv/libuv/pull/912 Reviewed-By: Ben Noordhuis Reviewed-By: Fedor Indutny Reviewed-By: Saúl Ibarra Corretgé --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index d9251f31..4a106bec 100644 --- a/configure.ac +++ b/configure.ac @@ -24,7 +24,7 @@ AC_ENABLE_SHARED AC_ENABLE_STATIC AC_PROG_CC AM_PROG_CC_C_O -CC_CHECK_CFLAGS_APPEND([-fvisibility=hidden]) +CC_FLAG_VISIBILITY #[-fvisibility=hidden] CC_CHECK_CFLAGS_APPEND([-g]) CC_CHECK_CFLAGS_APPEND([-std=gnu89]) CC_CHECK_CFLAGS_APPEND([-pedantic]) From 2fc54807fca6d3d3022d23fda6d3c060ebbc5be1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Wed, 15 Jun 2016 09:46:03 +0200 Subject: [PATCH 28/43] unix: remove unneeded TODO note It's already documented in http://docs.libuv.org/en/v1.x/stream.html#c.uv_accept PR-URL: https://github.com/libuv/libuv/pull/916 Reviewed-By: Ben Noordhuis Reviewed-By: Colin Ihrig Reviewed-By: Imran Iqbal --- src/unix/stream.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/unix/stream.c b/src/unix/stream.c index eaec92bb..2143cd88 100644 --- a/src/unix/stream.c +++ b/src/unix/stream.c @@ -571,7 +571,6 @@ void uv__server_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) { int uv_accept(uv_stream_t* server, uv_stream_t* client) { int err; - /* TODO document this */ assert(server->loop == client->loop); if (server->accepted_fd == -1) From 7b9e25a9a978e2655b77678670f4b329d95bb9d5 Mon Sep 17 00:00:00 2001 From: Luca Bruno Date: Sun, 19 Jun 2016 18:20:53 +0200 Subject: [PATCH 29/43] test: skip tty_pty test if pty is not available MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Do not let `tty_pty` test fail if no terminals are available to `openpty()`. PR-URL: https://github.com/libuv/libuv/pull/919 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- test/test-tty.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/test/test-tty.c b/test/test-tty.c index 55cc0167..5787d1da 100644 --- a/test/test-tty.c +++ b/test/test-tty.c @@ -262,14 +262,17 @@ TEST_IMPL(tty_file) { TEST_IMPL(tty_pty) { # if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || \ defined(__APPLE__) || defined(__FreeBSD__) || defined(__DragonFly__) - int master_fd, slave_fd; + int master_fd, slave_fd, r; struct winsize w; uv_loop_t loop; uv_tty_t master_tty, slave_tty; ASSERT(0 == uv_loop_init(&loop)); - ASSERT(0 == openpty(&master_fd, &slave_fd, NULL, NULL, &w)); + r = openpty(&master_fd, &slave_fd, NULL, NULL, &w); + if (r != 0) + RETURN_SKIP("No pty available, skipping."); + ASSERT(0 == uv_tty_init(&loop, &slave_tty, slave_fd, 0)); ASSERT(0 == uv_tty_init(&loop, &master_tty, master_fd, 0)); /* Check if the file descriptor was reopened. If it is, From d75e334e34487575bcb46f6311fefbdc4849a564 Mon Sep 17 00:00:00 2001 From: Brian Maher Date: Fri, 10 Jun 2016 09:04:59 -0700 Subject: [PATCH 30/43] sunos: set phys_addr of interface_address using ARP MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If getifaddrs() returns an all zero ifa_addr field, then use ARP to set the phys_addr field of the uv_interface_address_t on the sunos platform. PR-URL: https://github.com/libuv/libuv/pull/907 Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- src/unix/sunos.c | 68 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 48 insertions(+), 20 deletions(-) diff --git a/src/unix/sunos.c b/src/unix/sunos.c index e67be8fc..efadcea7 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -33,6 +33,8 @@ #endif #include #include +#include +#include #include #include @@ -692,13 +694,57 @@ void uv_free_cpu_info(uv_cpu_info_t* cpu_infos, int count) { uv__free(cpu_infos); } +/* + * Inspired By: + * https://blogs.oracle.com/paulie/entry/retrieving_mac_address_in_solaris + * http://www.pauliesworld.org/project/getmac.c + */ +static int uv__set_phys_addr(uv_interface_address_t* address, + struct ifaddrs* ent) { + + struct sockaddr_dl* sa_addr; + int sockfd; + int i; + struct arpreq arpreq; + + /* This appears to only work as root */ + sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); + memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); + for (i = 0; i < sizeof(address->phys_addr); i++) { + if (address->phys_addr[i] != 0) + return 0; + } + memset(&arpreq, 0, sizeof(arpreq)); + if (address->address.address4.sin_family == AF_INET) { + struct sockaddr_in* sin = ((struct sockaddr_in*)&arpreq.arp_pa); + sin->sin_addr.s_addr = address->address.address4.sin_addr.s_addr; + } else if (address->address.address4.sin_family == AF_INET6) { + struct sockaddr_in6* sin = ((struct sockaddr_in6*)&arpreq.arp_pa); + memcpy(sin->sin6_addr.s6_addr, + address->address.address6.sin6_addr.s6_addr, + sizeof(address->address.address6.sin6_addr.s6_addr)); + } else { + return 0; + } + + sockfd = socket(AF_INET, SOCK_DGRAM, 0); + if (sockfd < 0) + return -errno; + + if (ioctl(sockfd, SIOCGARP, (char*)&arpreq) == -1) { + uv__close(sockfd); + return -errno; + } + memcpy(address->phys_addr, arpreq.arp_ha.sa_data, sizeof(address->phys_addr)); + uv__close(sockfd); + return 0; +} int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { #ifdef SUNOS_NO_IFADDRS return -ENOSYS; #else uv_interface_address_t* address; - struct sockaddr_dl* sa_addr; struct ifaddrs* addrs; struct ifaddrs* ent; int i; @@ -751,28 +797,10 @@ int uv_interface_addresses(uv_interface_address_t** addresses, int* count) { address->is_internal = !!((ent->ifa_flags & IFF_PRIVATE) || (ent->ifa_flags & IFF_LOOPBACK)); + uv__set_phys_addr(address, ent); address++; } - /* Fill in physical addresses for each interface */ - for (ent = addrs; ent != NULL; ent = ent->ifa_next) { - if (!((ent->ifa_flags & IFF_UP) && (ent->ifa_flags & IFF_RUNNING)) || - (ent->ifa_addr == NULL) || - (ent->ifa_addr->sa_family != AF_LINK)) { - continue; - } - - address = *addresses; - - for (i = 0; i < (*count); i++) { - if (strcmp(address->name, ent->ifa_name) == 0) { - sa_addr = (struct sockaddr_dl*)(ent->ifa_addr); - memcpy(address->phys_addr, LLADDR(sa_addr), sizeof(address->phys_addr)); - } - address++; - } - } - freeifaddrs(addrs); return 0; From cdccd4f9900eaf123e1e70bca7e13e115f576bb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sa=C3=BAl=20Ibarra=20Corretg=C3=A9?= Date: Sat, 18 Jun 2016 18:57:12 +0200 Subject: [PATCH 31/43] doc: clarify callbacks won't be called in error case PR-URL: https://github.com/libuv/libuv/pull/918 Reviewed-By: Colin Ihrig --- docs/src/errors.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/src/errors.rst b/docs/src/errors.rst index cec25f51..2ebaf1e4 100644 --- a/docs/src/errors.rst +++ b/docs/src/errors.rst @@ -8,6 +8,9 @@ In libuv errors are negative numbered constants. As a rule of thumb, whenever there is a status parameter, or an API functions returns an integer, a negative number will imply an error. +When a function which takes a callback returns an error, the callback will never +be called. + .. note:: Implementation detail: on Unix error codes are the negated `errno` (or `-errno`), while on Windows they are defined by libuv to arbitrary negative numbers. From 34ee25734f752609707de339796c31b49fcfb683 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 22 Jun 2016 16:06:26 +0200 Subject: [PATCH 32/43] unix: don't convert stat buffer when syscall fails MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't call uv__to_stat() when the stat/fstat/lstat system call fails; the stack-allocated buffer contains only garbage in that case. Not a very serious bug it's technically undefined behavior and it made valgrind squawk. Introduced in commit 499c7976 ("unix, windows: nanosecond resolution for uv_fs_[fl]stat"). PR-URL: https://github.com/libuv/libuv/pull/921 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- src/unix/fs.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/unix/fs.c b/src/unix/fs.c index 508b748a..0b2505e4 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -810,8 +810,11 @@ static void uv__to_stat(struct stat* src, uv_stat_t* dst) { static int uv__fs_stat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = stat(path, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } @@ -819,8 +822,11 @@ static int uv__fs_stat(const char *path, uv_stat_t *buf) { static int uv__fs_lstat(const char *path, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = lstat(path, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } @@ -828,8 +834,11 @@ static int uv__fs_lstat(const char *path, uv_stat_t *buf) { static int uv__fs_fstat(int fd, uv_stat_t *buf) { struct stat pbuf; int ret; + ret = fstat(fd, &pbuf); - uv__to_stat(&pbuf, buf); + if (ret == 0) + uv__to_stat(&pbuf, buf); + return ret; } From 77c8abae33351acc3a845aebb61f485c94d61cdf Mon Sep 17 00:00:00 2001 From: cjihrig Date: Wed, 22 Jun 2016 13:14:04 -0400 Subject: [PATCH 33/43] win: compare entire filename in watch events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit causes Window file watching events to compare the entire file path when filtering events. This fixes a bug where incomplete path comparisons would cause invalid events to be raised. Refs: https://github.com/libuv/libuv/pull/682 PR-URL: https://github.com/libuv/libuv/pull/924 Reviewed-By: Saúl Ibarra Corretgé --- src/win/fs-event.c | 26 ++++++++++++++--- test/test-fs-event.c | 68 ++++++++++++++++++++++++++++++++++++++++---- test/test-list.h | 2 ++ 3 files changed, 86 insertions(+), 10 deletions(-) diff --git a/src/win/fs-event.c b/src/win/fs-event.c index e79a48d0..f96a7bfd 100644 --- a/src/win/fs-event.c +++ b/src/win/fs-event.c @@ -344,6 +344,22 @@ int uv_fs_event_stop(uv_fs_event_t* handle) { } +static int file_info_cmp(WCHAR* str, WCHAR* file_name, int file_name_len) { + int str_len; + + str_len = wcslen(str); + + /* + Since we only care about equality, return early if the strings + aren't the same length + */ + if (str_len != (file_name_len / sizeof(WCHAR))) + return -1; + + return _wcsnicmp(str, file_name, str_len); +} + + void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, uv_fs_event_t* handle) { FILE_NOTIFY_INFORMATION* file_info; @@ -383,10 +399,12 @@ void uv_process_fs_event_req(uv_loop_t* loop, uv_req_t* req, * or if the filename filter matches. */ if (handle->dirw || - _wcsnicmp(handle->filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0 || - _wcsnicmp(handle->short_filew, file_info->FileName, - file_info->FileNameLength / sizeof(WCHAR)) == 0) { + file_info_cmp(handle->filew, + file_info->FileName, + file_info->FileNameLength) == 0 || + file_info_cmp(handle->short_filew, + file_info->FileName, + file_info->FileNameLength) == 0) { if (handle->dirw) { /* diff --git a/test/test-fs-event.c b/test/test-fs-event.c index 353c43b0..25eef07b 100644 --- a/test/test-fs-event.c +++ b/test/test-fs-event.c @@ -53,6 +53,14 @@ static char fs_event_filename[PATH_MAX]; static char fs_event_filename[1024]; #endif /* defined(PATH_MAX) */ static int timer_cb_touch_called; +static int timer_cb_exact_called; + +static void fs_event_fail(uv_fs_event_t* handle, + const char* filename, + int events, + int status) { + ASSERT(0 && "should never be called"); +} static void create_dir(const char* name) { int r; @@ -345,6 +353,21 @@ static void timer_cb_touch(uv_timer_t* timer) { timer_cb_touch_called++; } +static void timer_cb_exact(uv_timer_t* handle) { + int r; + + if (timer_cb_exact_called == 0) { + touch_file("watch_dir/file.js"); + } else { + uv_close((uv_handle_t*)handle, NULL); + r = uv_fs_event_stop(&fs_event); + ASSERT(r == 0); + uv_close((uv_handle_t*) &fs_event, NULL); + } + + ++timer_cb_exact_called; +} + static void timer_cb_watch_twice(uv_timer_t* handle) { uv_fs_event_t* handles = handle->data; uv_close((uv_handle_t*) (handles + 0), NULL); @@ -467,6 +490,45 @@ TEST_IMPL(fs_event_watch_file) { return 0; } +TEST_IMPL(fs_event_watch_file_exact_path) { + /* + This test watches a file named "file.jsx" and modifies a file named + "file.js". The test verifies that no events occur for file.jsx. + */ + uv_loop_t* loop; + int r; + + loop = uv_default_loop(); + + /* Setup */ + remove("watch_dir/file.js"); + remove("watch_dir/file.jsx"); + remove("watch_dir/"); + create_dir("watch_dir"); + create_file("watch_dir/file.js"); + create_file("watch_dir/file.jsx"); + + r = uv_fs_event_init(loop, &fs_event); + ASSERT(r == 0); + r = uv_fs_event_start(&fs_event, fs_event_fail, "watch_dir/file.jsx", 0); + ASSERT(r == 0); + r = uv_timer_init(loop, &timer); + ASSERT(r == 0); + r = uv_timer_start(&timer, timer_cb_exact, 100, 100); + ASSERT(r == 0); + r = uv_run(loop, UV_RUN_DEFAULT); + ASSERT(r == 0); + ASSERT(timer_cb_exact_called == 2); + + /* Cleanup */ + remove("watch_dir/file.js"); + remove("watch_dir/file.jsx"); + remove("watch_dir/"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + TEST_IMPL(fs_event_watch_file_twice) { const char path[] = "test/fixtures/empty_file"; uv_fs_event_t watchers[2]; @@ -626,12 +688,6 @@ TEST_IMPL(fs_event_no_callback_on_close) { } -static void fs_event_fail(uv_fs_event_t* handle, const char* filename, - int events, int status) { - ASSERT(0 && "should never be called"); -} - - static void timer_cb(uv_timer_t* handle) { int r; diff --git a/test/test-list.h b/test/test-list.h index 3d99c266..41ed64c6 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -275,6 +275,7 @@ TEST_DECLARE (fs_read_file_eof) TEST_DECLARE (fs_event_watch_dir) TEST_DECLARE (fs_event_watch_dir_recursive) TEST_DECLARE (fs_event_watch_file) +TEST_DECLARE (fs_event_watch_file_exact_path) TEST_DECLARE (fs_event_watch_file_twice) TEST_DECLARE (fs_event_watch_file_current_dir) #ifdef _WIN32 @@ -724,6 +725,7 @@ TASK_LIST_START TEST_ENTRY (fs_event_watch_dir) TEST_ENTRY (fs_event_watch_dir_recursive) TEST_ENTRY (fs_event_watch_file) + TEST_ENTRY (fs_event_watch_file_exact_path) TEST_ENTRY (fs_event_watch_file_twice) TEST_ENTRY (fs_event_watch_file_current_dir) #ifdef _WIN32 From 1d27bbbb8d65b218f5c6cb7f9c4e2f4f043b30ad Mon Sep 17 00:00:00 2001 From: neevek Date: Mon, 27 Jun 2016 22:41:29 +0800 Subject: [PATCH 34/43] doc: add a note on safe reuse of uv_write_t MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit uv_write_t can be reused safely only after the callback passed to uv_write is fired. PR-URL: https://github.com/libuv/libuv/pull/927 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- docs/src/stream.rst | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/src/stream.rst b/docs/src/stream.rst index dfcad0fa..7989cd4f 100644 --- a/docs/src/stream.rst +++ b/docs/src/stream.rst @@ -26,7 +26,11 @@ Data types .. c:type:: uv_write_t - Write request type. + Write request type. Careful attention must be paid when reusing objects of + this type. When a stream is in non-blocking mode, write requests sent + with ``uv_write`` will be queued. Reusing objects at this point is undefined + behaviour. It is safe to reuse the ``uv_write_t`` object only after the + callback passed to ``uv_write`` is fired. .. c:type:: void (*uv_read_cb)(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) From 70002c80bf1447fad605b61d9d6e83e9d0c1a6bc Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Tue, 21 Jun 2016 15:25:43 +0200 Subject: [PATCH 35/43] linux: fix potential event loop stall It was pointed out[0] that libuv could effectively enter an infinite loop (but not a busy loop) under certain conditions when polling for events: 1. When the architecture is 32 bits, and 2. When timeout > 0, i.e., finite, and 3. When timeout > max_safe_timeout (~30 minutes), and 4. When epoll_wait(timeout) returns 0, then 5. timeout was not properly updated on the next call to epoll_wait(). Inspection of the code uncovered a secondary bug where under a similar set of circumstances the timeout could drift when the epoll_wait() system call returned late. [0] https://github.com/libuv/libuv/pull/354#discussion_r67837112 PR-URL: https://github.com/libuv/libuv/pull/922 Reviewed-By: Colin Ihrig --- src/unix/linux-core.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index ae927b7e..58dd813d 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -289,11 +289,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { if (nfds == 0) { assert(timeout != -1); - timeout = real_timeout - timeout; - if (timeout > 0) - continue; + if (timeout == 0) + return; - return; + /* We may have been inside the system call for longer than |timeout| + * milliseconds so we need to update the timestamp to avoid drift. + */ + goto update_timeout; } if (nfds == -1) { From 840a8c599ec1f138992a538f5b8109f91f31805e Mon Sep 17 00:00:00 2001 From: cjihrig Date: Mon, 27 Jun 2016 16:09:46 -0400 Subject: [PATCH 36/43] unix,win: make uv_get_process_title() stricter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit causes uv_get_process_title() to: - return EINVAL if the buffer is null or size is 0 - return ENOBUFS if the title is too big for the buffer - null terminate the buffer on success Fixes: https://github.com/libuv/libuv/issues/315 PR-URL: https://github.com/libuv/libuv/pull/928 Reviewed-By: Saúl Ibarra Corretgé --- docs/src/misc.rst | 4 +++- src/unix/aix.c | 27 ++++++++++++++------------- src/unix/freebsd.c | 18 ++++++++++++++---- src/unix/netbsd.c | 18 ++++++++++++++---- src/unix/openbsd.c | 18 ++++++++++++++---- src/unix/proctitle.c | 11 +++++++---- src/unix/sunos.c | 7 ++++--- src/win/util.c | 14 +++++++++++++- test/test-process-title.c | 22 ++++++++++++++++++++++ 9 files changed, 105 insertions(+), 34 deletions(-) diff --git a/docs/src/misc.rst b/docs/src/misc.rst index f32af48f..3b7f31aa 100644 --- a/docs/src/misc.rst +++ b/docs/src/misc.rst @@ -183,7 +183,9 @@ API .. c:function:: int uv_get_process_title(char* buffer, size_t size) - Gets the title of the current process. + Gets the title of the current process. If `buffer` is `NULL` or `size` is + zero, `UV_EINVAL` is returned. If `size` cannot accommodate the process + title and terminating `NULL` character, the function returns `UV_ENOBUFS`. .. c:function:: int uv_set_process_title(const char* title) diff --git a/src/unix/aix.c b/src/unix/aix.c index 2276985f..652cd980 100644 --- a/src/unix/aix.c +++ b/src/unix/aix.c @@ -156,7 +156,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { pqry.fd = pc.fd; rc = pollset_query(loop->backend_fd, &pqry); switch (rc) { - case -1: + case -1: assert(0 && "Failed to query pollset for file descriptor"); abort(); case 0: @@ -333,20 +333,20 @@ int uv_exepath(char* buffer, size_t* size) { pi.pi_pid = getpid(); res = getargs(&pi, sizeof(pi), args, sizeof(args)); - if (res < 0) + if (res < 0) return -EINVAL; /* * Possibilities for args: * i) an absolute path such as: /home/user/myprojects/nodejs/node * ii) a relative path such as: ./node or ../myprojects/nodejs/node - * iii) a bare filename such as "node", after exporting PATH variable + * iii) a bare filename such as "node", after exporting PATH variable * to its location. */ /* Case i) and ii) absolute or relative paths */ if (strchr(args, '/') != NULL) { - if (realpath(args, abspath) != abspath) + if (realpath(args, abspath) != abspath) return -errno; abspath_size = strlen(abspath); @@ -360,7 +360,7 @@ int uv_exepath(char* buffer, size_t* size) { return 0; } else { - /* Case iii). Search PATH environment variable */ + /* Case iii). Search PATH environment variable */ char trypath[PATH_MAX]; char *clonedpath = NULL; char *token = NULL; @@ -376,7 +376,7 @@ int uv_exepath(char* buffer, size_t* size) { token = strtok(clonedpath, ":"); while (token != NULL) { snprintf(trypath, sizeof(trypath) - 1, "%s/%s", token, args); - if (realpath(trypath, abspath) == abspath) { + if (realpath(trypath, abspath) == abspath) { /* Check the match is executable */ if (access(abspath, X_OK) == 0) { abspath_size = strlen(abspath); @@ -452,7 +452,7 @@ static char *uv__rawname(char *cp) { } -/* +/* * Determine whether given pathname is a directory * Returns 0 if the path is a directory, -1 if not * @@ -472,7 +472,7 @@ static int uv__path_is_a_directory(char* filename) { } -/* +/* * Check whether AHAFS is mounted. * Returns 0 if AHAFS is mounted, or an error code < 0 on failure */ @@ -547,7 +547,7 @@ static int uv__makedir_p(const char *dir) { return mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); } -/* +/* * Creates necessary subdirectories in the AIX Event Infrastructure * file system for monitoring the object specified. * Returns code from mkdir call @@ -665,7 +665,7 @@ static int uv__skip_lines(char **p, int n) { /* * Parse the event occurrence data to figure out what event just occurred * and take proper action. - * + * * The buf is a pointer to the buffer containing the event occurrence data * Returns 0 on success, -1 if unrecoverable error in parsing * @@ -891,9 +891,10 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } + if (buffer == NULL || size == 0) + return -EINVAL; + + buffer[0] = '\0'; return 0; } diff --git a/src/unix/freebsd.c b/src/unix/freebsd.c index adc95235..cba44a3e 100644 --- a/src/unix/freebsd.c +++ b/src/unix/freebsd.c @@ -196,14 +196,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/netbsd.c b/src/unix/netbsd.c index ca48550f..4a9e6cbc 100644 --- a/src/unix/netbsd.c +++ b/src/unix/netbsd.c @@ -147,14 +147,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/openbsd.c b/src/unix/openbsd.c index 8c40bde4..909288cc 100644 --- a/src/unix/openbsd.c +++ b/src/unix/openbsd.c @@ -169,14 +169,24 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return -EINVAL; + if (process_title) { - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) + return -ENOBUFS; + + memcpy(buffer, process_title, len); } else { - if (size > 0) { - buffer[0] = '\0'; - } + len = 0; } + buffer[len] = '\0'; + return 0; } diff --git a/src/unix/proctitle.c b/src/unix/proctitle.c index 19214e5e..08d875f7 100644 --- a/src/unix/proctitle.c +++ b/src/unix/proctitle.c @@ -87,10 +87,13 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (process_title.len > 0) - strncpy(buffer, process_title.str, size); - else if (size > 0) - buffer[0] = '\0'; + if (buffer == NULL || size == 0) + return -EINVAL; + else if (size <= process_title.len) + return -ENOBUFS; + + memcpy(buffer, process_title.str, process_title.len + 1); + buffer[process_title.len] = '\0'; return 0; } diff --git a/src/unix/sunos.c b/src/unix/sunos.c index efadcea7..3e7a7592 100644 --- a/src/unix/sunos.c +++ b/src/unix/sunos.c @@ -542,9 +542,10 @@ int uv_set_process_title(const char* title) { int uv_get_process_title(char* buffer, size_t size) { - if (size > 0) { - buffer[0] = '\0'; - } + if (buffer == NULL || size == 0) + return -EINVAL; + + buffer[0] = '\0'; return 0; } diff --git a/src/win/util.c b/src/win/util.c index 4cebad39..84a0e467 100644 --- a/src/win/util.c +++ b/src/win/util.c @@ -416,6 +416,11 @@ static int uv__get_process_title() { int uv_get_process_title(char* buffer, size_t size) { + size_t len; + + if (buffer == NULL || size == 0) + return UV_EINVAL; + uv__once_init(); EnterCriticalSection(&process_title_lock); @@ -429,7 +434,14 @@ int uv_get_process_title(char* buffer, size_t size) { } assert(process_title); - strncpy(buffer, process_title, size); + len = strlen(process_title) + 1; + + if (size < len) { + LeaveCriticalSection(&process_title_lock); + return UV_ENOBUFS; + } + + memcpy(buffer, process_title, len); LeaveCriticalSection(&process_title_lock); return 0; diff --git a/test/test-process-title.c b/test/test-process-title.c index 42ade441..00f164a4 100644 --- a/test/test-process-title.c +++ b/test/test-process-title.c @@ -41,6 +41,24 @@ static void set_title(const char* title) { } +static void uv_get_process_title_edge_cases() { + char buffer[512]; + int r; + + /* Test a NULL buffer */ + r = uv_get_process_title(NULL, 100); + ASSERT(r == UV_EINVAL); + + /* Test size of zero */ + r = uv_get_process_title(buffer, 0); + ASSERT(r == UV_EINVAL); + + /* Test for insufficient buffer size */ + r = uv_get_process_title(buffer, 1); + ASSERT(r == UV_ENOBUFS); +} + + TEST_IMPL(process_title) { #if defined(__sun) || defined(_AIX) RETURN_SKIP("uv_(get|set)_process_title is not implemented."); @@ -48,6 +66,10 @@ TEST_IMPL(process_title) { /* Check for format string vulnerabilities. */ set_title("%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s"); set_title("new title"); + + /* Check uv_get_process_title() edge cases */ + uv_get_process_title_edge_cases(); + return 0; #endif } From 4b58985370cd6aa13f10b390b7694e891abff974 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Sat, 9 Jul 2016 14:45:32 -0400 Subject: [PATCH 37/43] test: close server before initiating new connection MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/944 Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- test/test-tcp-close-accept.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/test-tcp-close-accept.c b/test/test-tcp-close-accept.c index 0729d46d..e4878398 100644 --- a/test/test-tcp-close-accept.c +++ b/test/test-tcp-close-accept.c @@ -102,6 +102,9 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { uv_close((uv_handle_t*) &tcp_incoming[i], close_cb); } + /* Close server, so no one will connect to it */ + uv_close((uv_handle_t*) &tcp_server, close_cb); + /* Create new fd that should be one of the closed incomings */ ASSERT(0 == uv_tcp_init(loop, &tcp_check)); ASSERT(0 == uv_tcp_connect(&tcp_check_req, @@ -109,9 +112,6 @@ static void read_cb(uv_stream_t* stream, ssize_t nread, const uv_buf_t* buf) { (const struct sockaddr*) &addr, connect_cb)); ASSERT(0 == uv_read_start((uv_stream_t*) &tcp_check, alloc_cb, read_cb)); - - /* Close server, so no one will connect to it */ - uv_close((uv_handle_t*) &tcp_server, close_cb); } static void connection_cb(uv_stream_t* server, int status) { From 00dab91ce58c2399f2db5f484e6f718faba51de6 Mon Sep 17 00:00:00 2001 From: John Barboza Date: Fri, 8 Jul 2016 21:42:13 -0400 Subject: [PATCH 38/43] test: account for multiple handles in one ipc read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/940 Reviewed-By: Ben Noordhuis Reviewed-By: Saúl Ibarra Corretgé --- test/test-ipc-send-recv.c | 129 ++++++++++++++++++++------------------ 1 file changed, 67 insertions(+), 62 deletions(-) diff --git a/test/test-ipc-send-recv.c b/test/test-ipc-send-recv.c index c445483f..133ae901 100644 --- a/test/test-ipc-send-recv.c +++ b/test/test-ipc-send-recv.c @@ -68,8 +68,8 @@ static struct echo_ctx ctx2; /* Used in write2_cb to decide if we need to cleanup or not */ static int is_child_process; static int is_in_process; -static int read_cb_called; -static int recv_cb_called; +static int read_cb_count; +static int recv_cb_count; static int write2_cb_called; @@ -91,43 +91,46 @@ static void recv_cb(uv_stream_t* handle, int r; union handles* recv; - if (++recv_cb_called == 1) { - recv = &ctx.recv; - } else { - recv = &ctx.recv2; - } - pipe = (uv_pipe_t*) handle; ASSERT(pipe == &ctx.channel); - /* Depending on the OS, the final recv_cb can be called after the child - * process has terminated which can result in nread being UV_EOF instead of - * the number of bytes read. Since the other end of the pipe has closed this - * UV_EOF is an acceptable value. */ - if (nread == UV_EOF) { - /* UV_EOF is only acceptable for the final recv_cb call */ - ASSERT(recv_cb_called == 2); - } else { - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); + do { + if (++recv_cb_count == 1) { + recv = &ctx.recv; + } else { + recv = &ctx.recv2; + } - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == ctx.expected_type); + /* Depending on the OS, the final recv_cb can be called after + * the child process has terminated which can result in nread + * being UV_EOF instead of the number of bytes read. Since + * the other end of the pipe has closed this UV_EOF is an + * acceptable value. */ + if (nread == UV_EOF) { + /* UV_EOF is only acceptable for the final recv_cb call */ + ASSERT(recv_cb_count == 2); + } else { + ASSERT(nread >= 0); + ASSERT(uv_pipe_pending_count(pipe) > 0); - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx.channel.loop, &recv->tcp); - else - abort(); - ASSERT(r == 0); + pending = uv_pipe_pending_type(pipe); + ASSERT(pending == ctx.expected_type); - r = uv_accept(handle, &recv->stream); - ASSERT(r == 0); - } + if (pending == UV_NAMED_PIPE) + r = uv_pipe_init(ctx.channel.loop, &recv->pipe, 0); + else if (pending == UV_TCP) + r = uv_tcp_init(ctx.channel.loop, &recv->tcp); + else + abort(); + ASSERT(r == 0); + + r = uv_accept(handle, &recv->stream); + ASSERT(r == 0); + } + } while (uv_pipe_pending_count(pipe) > 0); /* Close after two writes received */ - if (recv_cb_called == 2) { + if (recv_cb_count == 2) { uv_close((uv_handle_t*)&ctx.channel, NULL); } } @@ -186,7 +189,7 @@ static int run_test(int inprocess) { r = uv_run(uv_default_loop(), UV_RUN_DEFAULT); ASSERT(r == 0); - ASSERT(recv_cb_called == 2); + ASSERT(recv_cb_count == 2); if (inprocess) { r = uv_thread_join(&tid); @@ -293,41 +296,43 @@ static void read_cb(uv_stream_t* handle, return; } - if (++read_cb_called == 2) { - recv = &ctx2.recv; - write_req = &ctx2.write_req; - } else { - recv = &ctx2.recv2; - write_req = &ctx2.write_req2; - } - pipe = (uv_pipe_t*) handle; - ASSERT(pipe == &ctx2.channel); - ASSERT(nread >= 0); - ASSERT(1 == uv_pipe_pending_count(pipe)); + do { + if (++read_cb_count == 2) { + recv = &ctx2.recv; + write_req = &ctx2.write_req; + } else { + recv = &ctx2.recv2; + write_req = &ctx2.write_req2; + } - pending = uv_pipe_pending_type(pipe); - ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); + ASSERT(pipe == &ctx2.channel); + ASSERT(nread >= 0); + ASSERT(uv_pipe_pending_count(pipe) > 0); - if (pending == UV_NAMED_PIPE) - r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); - else if (pending == UV_TCP) - r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); - else - abort(); - ASSERT(r == 0); + pending = uv_pipe_pending_type(pipe); + ASSERT(pending == UV_NAMED_PIPE || pending == UV_TCP); - r = uv_accept(handle, &recv->stream); - ASSERT(r == 0); + if (pending == UV_NAMED_PIPE) + r = uv_pipe_init(ctx2.channel.loop, &recv->pipe, 0); + else if (pending == UV_TCP) + r = uv_tcp_init(ctx2.channel.loop, &recv->tcp); + else + abort(); + ASSERT(r == 0); - wrbuf = uv_buf_init(".", 1); - r = uv_write2(write_req, - (uv_stream_t*)&ctx2.channel, - &wrbuf, - 1, - &recv->stream, - write2_cb); - ASSERT(r == 0); + r = uv_accept(handle, &recv->stream); + ASSERT(r == 0); + + wrbuf = uv_buf_init(".", 1); + r = uv_write2(write_req, + (uv_stream_t*)&ctx2.channel, + &wrbuf, + 1, + &recv->stream, + write2_cb); + ASSERT(r == 0); + } while (uv_pipe_pending_count(pipe) > 0); } static void send_recv_start() { From 3a4f2d31550037c96ea0113fe294e4fdc69a1f99 Mon Sep 17 00:00:00 2001 From: liuxiaobo Date: Mon, 4 Jul 2016 17:08:46 +0800 Subject: [PATCH 39/43] unix: fix errno and retval conflict MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We not only check the return value, but also check the errno != 0. Because in rare cases connect() will return -1 but the errno is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227) and actually the tcp three-way handshake is completed. PR-URL: https://github.com/libuv/libuv/pull/936 Reviewed-By: Ben Noordhuis Reviewed-By: Imran Iqbal Reviewed-By: Saúl Ibarra Corretgé --- src/unix/tcp.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/unix/tcp.c b/src/unix/tcp.c index 793e4c7d..46d8cd25 100644 --- a/src/unix/tcp.c +++ b/src/unix/tcp.c @@ -158,11 +158,17 @@ int uv__tcp_connect(uv_connect_t* req, handle->delayed_error = 0; - do + do { + errno = 0; r = connect(uv__stream_fd(handle), addr, addrlen); - while (r == -1 && errno == EINTR); + } while (r == -1 && errno == EINTR); - if (r == -1) { + /* We not only check the return value, but also check the errno != 0. + * Because in rare cases connect() will return -1 but the errno + * is 0 (for example, on Android 4.3, OnePlus phone A0001_12_150227) + * and actually the tcp three-way handshake is completed. + */ + if (r == -1 && errno != 0) { if (errno == EINPROGRESS) ; /* not an error */ else if (errno == ECONNREFUSED) From f001a67e1d68e89a0b59dd7bc63587fba7ed914f Mon Sep 17 00:00:00 2001 From: Michele Caini Date: Tue, 26 Jul 2016 14:24:20 +0200 Subject: [PATCH 40/43] doc: add missing entry in uv_fs_type enum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR-URL: https://github.com/libuv/libuv/pull/958 Reviewed-By: Saúl Ibarra Corretgé --- docs/src/fs.rst | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index f810319c..50c0de46 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -91,7 +91,8 @@ Data types UV_FS_SYMLINK, UV_FS_READLINK, UV_FS_CHOWN, - UV_FS_FCHOWN + UV_FS_FCHOWN, + UV_FS_REALPATH } uv_fs_type; .. c:type:: uv_dirent_t From ff0ae10496da1e0012e79e8980b12a25fd1ea6b2 Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Wed, 20 Jul 2016 14:18:50 +0200 Subject: [PATCH 41/43] unix: preserve loop->data across loop init/done MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Libuv leaves loop->data unchanged in uv_loop_init() and uv_loop_done() on Windows but it clobbered it on UNIX platforms. This commit fixes that inconsistency. PR-URL: https://github.com/libuv/libuv/pull/951 Reviewed-By: Colin Ihrig Reviewed-By: Saúl Ibarra Corretgé --- src/unix/loop.c | 4 ++++ src/uv-common.c | 3 +++ test/test-loop-close.c | 4 ++++ 3 files changed, 11 insertions(+) diff --git a/src/unix/loop.c b/src/unix/loop.c index 92e96f09..bd63c2f9 100644 --- a/src/unix/loop.c +++ b/src/unix/loop.c @@ -28,11 +28,15 @@ #include int uv_loop_init(uv_loop_t* loop) { + void* saved_data; int err; uv__signal_global_once_init(); + saved_data = loop->data; memset(loop, 0, sizeof(*loop)); + loop->data = saved_data; + heap_init((struct heap*) &loop->timer_heap); QUEUE_INIT(&loop->wq); QUEUE_INIT(&loop->active_reqs); diff --git a/src/uv-common.c b/src/uv-common.c index ba264469..434a5029 100644 --- a/src/uv-common.c +++ b/src/uv-common.c @@ -613,6 +613,7 @@ uv_loop_t* uv_loop_new(void) { int uv_loop_close(uv_loop_t* loop) { QUEUE* q; uv_handle_t* h; + void* saved_data; if (!QUEUE_EMPTY(&(loop)->active_reqs)) return UV_EBUSY; @@ -626,7 +627,9 @@ int uv_loop_close(uv_loop_t* loop) { uv__loop_close(loop); #ifndef NDEBUG + saved_data = loop->data; memset(loop, -1, sizeof(*loop)); + loop->data = saved_data; #endif if (loop == default_loop_ptr) default_loop_ptr = NULL; diff --git a/test/test-loop-close.c b/test/test-loop-close.c index 5aec234e..971c9d72 100644 --- a/test/test-loop-close.c +++ b/test/test-loop-close.c @@ -34,7 +34,9 @@ TEST_IMPL(loop_close) { int r; uv_loop_t loop; + loop.data = &loop; ASSERT(0 == uv_loop_init(&loop)); + ASSERT(loop.data == (void*) &loop); uv_timer_init(&loop, &timer_handle); uv_timer_start(&timer_handle, timer_cb, 100, 100); @@ -47,7 +49,9 @@ TEST_IMPL(loop_close) { r = uv_run(&loop, UV_RUN_DEFAULT); ASSERT(r == 0); + ASSERT(loop.data == (void*) &loop); ASSERT(0 == uv_loop_close(&loop)); + ASSERT(loop.data == (void*) &loop); return 0; } From ef6f3e8e8d91b19da2c97005c0c8bda04158b54a Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 9 Jul 2016 10:00:04 +0200 Subject: [PATCH 42/43] win: return UV_EINVAL on bad uv_tty_mode mode arg MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fixes: https://github.com/libuv/libuv/issues/941 PR-URL: https://github.com/libuv/libuv/pull/942 Reviewed-By: Saúl Ibarra Corretgé --- src/win/tty.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/win/tty.c b/src/win/tty.c index 59a991c6..daa303f1 100644 --- a/src/win/tty.c +++ b/src/win/tty.c @@ -297,6 +297,8 @@ int uv_tty_set_mode(uv_tty_t* tty, uv_tty_mode_t mode) { break; case UV_TTY_MODE_IO: return UV_ENOTSUP; + default: + return UV_EINVAL; } if (!SetConsoleMode(tty->handle, flags)) { From f614b43a69693022119807709a62d361b7c5517d Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Sat, 9 Jul 2016 10:02:06 +0200 Subject: [PATCH 43/43] win: simplify memory copy logic in fs.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hopefully shuts up a -Wmaybe-uninitialized warning about the path_len variable. Fixes: https://github.com/libuv/libuv/issues/941 PR-URL: https://github.com/libuv/libuv/pull/942 Reviewed-By: Saúl Ibarra Corretgé --- src/win/fs.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/win/fs.c b/src/win/fs.c index 24c60847..b6d43921 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -204,14 +204,11 @@ INLINE static int fs__capture_path(uv_fs_t* req, const char* path, req->fs.info.new_pathw = NULL; } - if (!copy_path) { - req->path = path; - } else if (path) { + req->path = path; + if (path != NULL && copy_path) { memcpy(pos, path, path_len); assert(path_len == buf_sz - (pos - buf)); req->path = pos; - } else { - req->path = NULL; } req->flags |= UV_FS_FREE_PATHS;