diff --git a/deps/uv/AUTHORS b/deps/uv/AUTHORS index b27d17716a1..48a74db32f6 100644 --- a/deps/uv/AUTHORS +++ b/deps/uv/AUTHORS @@ -131,3 +131,4 @@ Paul Tan Javier Hernández Tonis Tiigi Michael Hudson-Doyle +Helge Deller diff --git a/deps/uv/ChangeLog b/deps/uv/ChangeLog index 3f010a0c3e0..4ba348d571b 100644 --- a/deps/uv/ChangeLog +++ b/deps/uv/ChangeLog @@ -1,4 +1,23 @@ -2014.10.21, Version 0.10.29 (Stable) +2014.12.10, Version 0.10.30 (Stable) + +Changes since version 0.10.29: + +* linux: fix sigmask size arg in epoll_pwait() call (Ben Noordhuis) + +* linux: handle O_NONBLOCK != SOCK_NONBLOCK case (Helge Deller) + +* doc: update project links (Ben Noordhuis) + +* windows: fix compilation of tests (Marc Schlaich) + +* unix: add flag for blocking SIGPROF during poll (Ben Noordhuis) + +* unix, windows: add uv_loop_configure() function (Ben Noordhuis) + +* win: keep a reference to AFD_POLL_INFO in cancel poll (Marc Schlaich) + + +2014.10.21, Version 0.10.29 (Stable), 2d728542d3790183417f8f122a110693cd85db14 Changes since version 0.10.28: diff --git a/deps/uv/README.md b/deps/uv/README.md index 1e1aa25cbd1..5fee16cfe01 100644 --- a/deps/uv/README.md +++ b/deps/uv/README.md @@ -42,13 +42,13 @@ http://nodejs.org/ ## Documentation - * [include/uv.h](https://github.com/joyent/libuv/blob/master/include/uv.h) + * [include/uv.h](https://github.com/libuv/libuv/blob/master/include/uv.h) — API documentation in the form of detailed header comments. * [An Introduction to libuv](http://nikhilm.github.com/uvbook/) — An overview of libuv with tutorials. * [LXJS 2012 talk](http://www.youtube.com/watch?v=nGn60vDSxQ4) - High-level introductory talk about libuv. - * [Tests and benchmarks](https://github.com/joyent/libuv/tree/master/test) - + * [Tests and benchmarks](https://github.com/libuv/libuv/tree/master/test) - API specification and usage examples. ## Build Instructions diff --git a/deps/uv/include/uv-private/uv-win.h b/deps/uv/include/uv-private/uv-win.h index c9ec38ef4ca..e5f2f3b4c8b 100644 --- a/deps/uv/include/uv-private/uv-win.h +++ b/deps/uv/include/uv-private/uv-win.h @@ -474,7 +474,10 @@ RB_HEAD(uv_timer_tree_s, uv_timer_s); /* Used in fast mode */ \ SOCKET peer_socket; \ AFD_POLL_INFO afd_poll_info_1; \ - AFD_POLL_INFO afd_poll_info_2; \ + union { \ + AFD_POLL_INFO* afd_poll_info_ptr; \ + AFD_POLL_INFO afd_poll_info; \ + } afd_poll_info_2; \ /* Used in fast and slow mode. */ \ uv_req_t poll_req_1; \ uv_req_t poll_req_2; \ diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h index 7022bc669fd..be789987bbd 100644 --- a/deps/uv/include/uv.h +++ b/deps/uv/include/uv.h @@ -226,6 +226,16 @@ typedef struct uv_work_s uv_work_t; typedef struct uv_cpu_info_s uv_cpu_info_t; typedef struct uv_interface_address_s uv_interface_address_t; +typedef enum { + /* Block a signal when polling for new events. The second argument to + * uv_loop_configure() is the signal number. + * + * This operation is currently only implemented for SIGPROF signals, + * to suppress unnecessary wakeups when using a sampling profiler. + * Requesting other signals will fail with UV_EINVAL. + */ + UV_LOOP_BLOCK_SIGNAL +} uv_loop_option; typedef enum { UV_RUN_DEFAULT = 0, @@ -264,6 +274,15 @@ UV_EXTERN void uv_loop_delete(uv_loop_t*); */ UV_EXTERN uv_loop_t* uv_default_loop(void); +/* + * Set additional loop options. You should normally call this before the + * first call to uv_run() unless mentioned otherwise. + * + * Returns 0 on success or a UV_E* error code on failure. Be prepared to + * handle UV_ENOSYS; it means the loop option is not supported by the platform. + */ +UV_EXTERN int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...); + /* * This function runs the event loop. It will act differently depending on the * specified mode: diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h index 35aa894a545..003e1a5093b 100644 --- a/deps/uv/src/unix/internal.h +++ b/deps/uv/src/unix/internal.h @@ -111,6 +111,11 @@ enum { UV_TCP_SINGLE_ACCEPT = 0x400 /* Only accept() when idle. */ }; +/* loop flags */ +enum { + UV_LOOP_BLOCK_SIGPROF = 1 +}; + /* core */ int uv__nonblock(int fd, int set); int uv__cloexec(int fd, int set); diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c index 124f4fd5764..b43cc676420 100644 --- a/deps/uv/src/unix/kqueue.c +++ b/deps/uv/src/unix/kqueue.c @@ -56,9 +56,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { unsigned int nevents; unsigned int revents; ngx_queue_t* q; + uv__io_t* w; + sigset_t* pset; + sigset_t set; uint64_t base; uint64_t diff; - uv__io_t* w; int filter; int fflags; int count; @@ -118,6 +120,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->events = w->pevents; } + pset = NULL; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + pset = &set; + sigemptyset(pset); + sigaddset(pset, SIGPROF); + } + assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ @@ -128,6 +137,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { spec.tv_nsec = (timeout % 1000) * 1000000; } + if (pset != NULL) + pthread_sigmask(SIG_BLOCK, pset, NULL); + nfds = kevent(loop->backend_fd, events, nevents, @@ -135,6 +147,9 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { ARRAY_SIZE(events), timeout == -1 ? NULL : &spec); + if (pset != NULL) + pthread_sigmask(SIG_UNBLOCK, pset, NULL); + /* Update loop->time unconditionally. It's tempting to skip the update when * timeout == 0 (i.e. non-blocking poll) but there is no guarantee that the * operating system didn't reschedule our process while in the syscall. diff --git a/deps/uv/src/unix/linux-core.c b/deps/uv/src/unix/linux-core.c index 4846bd3fc71..47938f2b202 100644 --- a/deps/uv/src/unix/linux-core.c +++ b/deps/uv/src/unix/linux-core.c @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -130,6 +131,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { struct uv__epoll_event e; ngx_queue_t* q; uv__io_t* w; + sigset_t* pset; + sigset_t set; uint64_t base; uint64_t diff; int nevents; @@ -180,12 +183,25 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->events = w->pevents; } + pset = NULL; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + pset = &set; + sigemptyset(pset); + sigaddset(pset, SIGPROF); + } + assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ for (;;) { - if (!no_epoll_wait) { + if (no_epoll_wait || pset != NULL) { + nfds = uv__epoll_pwait(loop->backend_fd, + events, + ARRAY_SIZE(events), + timeout, + pset); + } else { nfds = uv__epoll_wait(loop->backend_fd, events, ARRAY_SIZE(events), @@ -194,12 +210,6 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { no_epoll_wait = 1; continue; } - } else { - nfds = uv__epoll_pwait(loop->backend_fd, - events, - ARRAY_SIZE(events), - timeout, - NULL); } /* Update loop->time unconditionally. It's tempting to skip the update when diff --git a/deps/uv/src/unix/linux-syscalls.c b/deps/uv/src/unix/linux-syscalls.c index 06cc5943cf4..c9945438f49 100644 --- a/deps/uv/src/unix/linux-syscalls.c +++ b/deps/uv/src/unix/linux-syscalls.c @@ -21,6 +21,7 @@ #include "linux-syscalls.h" #include +#include #include #include #include @@ -298,7 +299,7 @@ int uv__epoll_pwait(int epfd, nevents, timeout, sigmask, - sizeof(*sigmask)); + _NSIG / 8); #else return errno = ENOSYS, -1; #endif diff --git a/deps/uv/src/unix/linux-syscalls.h b/deps/uv/src/unix/linux-syscalls.h index ba44974a064..62eb5c5a368 100644 --- a/deps/uv/src/unix/linux-syscalls.h +++ b/deps/uv/src/unix/linux-syscalls.h @@ -43,7 +43,7 @@ #if defined(__alpha__) # define UV__O_NONBLOCK 0x4 #elif defined(__hppa__) -# define UV__O_NONBLOCK 0x10004 +# define UV__O_NONBLOCK O_NONBLOCK #elif defined(__mips__) # define UV__O_NONBLOCK 0x80 #elif defined(__sparc__) @@ -59,7 +59,11 @@ #define UV__IN_NONBLOCK UV__O_NONBLOCK #define UV__SOCK_CLOEXEC UV__O_CLOEXEC -#define UV__SOCK_NONBLOCK UV__O_NONBLOCK +#if defined(SOCK_NONBLOCK) +# define UV__SOCK_NONBLOCK SOCK_NONBLOCK +#else +# define UV__SOCK_NONBLOCK UV__O_NONBLOCK +#endif /* epoll flags */ #define UV__EPOLL_CLOEXEC UV__O_CLOEXEC diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c index 75b0702a3ab..a75c9345678 100644 --- a/deps/uv/src/unix/loop.c +++ b/deps/uv/src/unix/loop.c @@ -112,3 +112,15 @@ void uv__loop_delete(uv_loop_t* loop) { loop->watchers = NULL; loop->nwatchers = 0; } + + +int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { + if (option != UV_LOOP_BLOCK_SIGNAL) + return UV_ENOSYS; + + if (va_arg(ap, int) != SIGPROF) + return UV_EINVAL; + + loop->flags |= UV_LOOP_BLOCK_SIGPROF; + return 0; +} diff --git a/deps/uv/src/unix/sunos.c b/deps/uv/src/unix/sunos.c index 9030bfa6b39..0f4b32f4ea9 100644 --- a/deps/uv/src/unix/sunos.c +++ b/deps/uv/src/unix/sunos.c @@ -112,6 +112,8 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { struct timespec spec; ngx_queue_t* q; uv__io_t* w; + sigset_t* pset; + sigset_t set; uint64_t base; uint64_t diff; unsigned int nfds; @@ -119,6 +121,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { int saved_errno; int nevents; int count; + int err; int fd; if (loop->nfds == 0) { @@ -140,6 +143,13 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { w->events = w->pevents; } + pset = NULL; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { + pset = &set; + sigemptyset(pset); + sigaddset(pset, SIGPROF); + } + assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ @@ -155,11 +165,20 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { nfds = 1; saved_errno = 0; - if (port_getn(loop->backend_fd, - events, - ARRAY_SIZE(events), - &nfds, - timeout == -1 ? NULL : &spec)) { + + if (pset != NULL) + pthread_sigmask(SIG_BLOCK, pset, NULL); + + err = port_getn(loop->backend_fd, + events, + ARRAY_SIZE(events), + &nfds, + timeout == -1 ? NULL : &spec); + + if (pset != NULL) + pthread_sigmask(SIG_UNBLOCK, pset, NULL); + + if (err) { /* Work around another kernel bug: port_getn() may return events even * on error. */ diff --git a/deps/uv/src/uv-common.c b/deps/uv/src/uv-common.c index f0792f11759..69da523e6af 100644 --- a/deps/uv/src/uv-common.c +++ b/deps/uv/src/uv-common.c @@ -24,6 +24,7 @@ #include #include +#include #include /* NULL */ #include /* malloc */ #include /* memset */ @@ -434,3 +435,16 @@ void uv_stop(uv_loop_t* loop) { uint64_t uv_now(uv_loop_t* loop) { return loop->time; } + + +int uv_loop_configure(uv_loop_t* loop, uv_loop_option option, ...) { + va_list ap; + int err; + + va_start(ap, option); + /* Any platform-agnostic options should be handled here. */ + err = uv__loop_configure(loop, option, ap); + va_end(ap); + + return err; +} diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h index bbf24859295..ad45f19050f 100644 --- a/deps/uv/src/uv-common.h +++ b/deps/uv/src/uv-common.h @@ -28,6 +28,7 @@ #define UV_COMMON_H_ #include +#include #include #if defined(_MSC_VER) && _MSC_VER < 1600 @@ -77,6 +78,7 @@ int uv__set_artificial_error(uv_loop_t* loop, uv_err_code code); uv_err_t uv__new_sys_error(int sys_error); uv_err_t uv__new_artificial_error(uv_err_code code); +int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap); int uv__tcp_bind(uv_tcp_t* handle, struct sockaddr_in addr); int uv__tcp_bind6(uv_tcp_t* handle, struct sockaddr_in6 addr); diff --git a/deps/uv/src/version.c b/deps/uv/src/version.c index ca96400842b..1b5a1e4cdbb 100644 --- a/deps/uv/src/version.c +++ b/deps/uv/src/version.c @@ -34,7 +34,7 @@ #define UV_VERSION_MAJOR 0 #define UV_VERSION_MINOR 10 -#define UV_VERSION_PATCH 29 +#define UV_VERSION_PATCH 30 #define UV_VERSION_IS_RELEASE 1 diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c index 62d6bf8fbba..74c602fb19e 100644 --- a/deps/uv/src/win/core.c +++ b/deps/uv/src/win/core.c @@ -174,6 +174,11 @@ void uv_loop_delete(uv_loop_t* loop) { } +int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) { + return UV_ENOSYS; +} + + int uv_backend_fd(const uv_loop_t* loop) { return -1; } diff --git a/deps/uv/src/win/poll.c b/deps/uv/src/win/poll.c index 76427b01a4e..5c5c7d80f0d 100644 --- a/deps/uv/src/win/poll.c +++ b/deps/uv/src/win/poll.c @@ -79,7 +79,7 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { handle->mask_events_2 = handle->events; } else if (handle->submitted_events_2 == 0) { req = &handle->poll_req_2; - afd_poll_info = &handle->afd_poll_info_2; + afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0]; handle->submitted_events_2 = handle->events; handle->mask_events_1 = handle->events; handle->mask_events_2 = 0; @@ -118,18 +118,19 @@ static void uv__fast_poll_submit_poll_req(uv_loop_t* loop, uv_poll_t* handle) { static int uv__fast_poll_cancel_poll_req(uv_loop_t* loop, uv_poll_t* handle) { - AFD_POLL_INFO afd_poll_info; + AFD_POLL_INFO* afd_poll_info; DWORD result; - afd_poll_info.Exclusive = TRUE; - afd_poll_info.NumberOfHandles = 1; - afd_poll_info.Timeout.QuadPart = INT64_MAX; - afd_poll_info.Handles[0].Handle = (HANDLE) handle->socket; - afd_poll_info.Handles[0].Status = 0; - afd_poll_info.Handles[0].Events = AFD_POLL_ALL; + afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[1]; + afd_poll_info->Exclusive = TRUE; + afd_poll_info->NumberOfHandles = 1; + afd_poll_info->Timeout.QuadPart = INT64_MAX; + afd_poll_info->Handles[0].Handle = (HANDLE) handle->socket; + afd_poll_info->Handles[0].Status = 0; + afd_poll_info->Handles[0].Events = AFD_POLL_ALL; result = uv_msafd_poll(handle->socket, - &afd_poll_info, + afd_poll_info, uv__get_overlapped_dummy()); if (result == SOCKET_ERROR) { @@ -154,7 +155,7 @@ static void uv__fast_poll_process_poll_req(uv_loop_t* loop, uv_poll_t* handle, handle->submitted_events_1 = 0; mask_events = handle->mask_events_1; } else if (req == &handle->poll_req_2) { - afd_poll_info = &handle->afd_poll_info_2; + afd_poll_info = &handle->afd_poll_info_2.afd_poll_info_ptr[0]; handle->submitted_events_2 = 0; mask_events = handle->mask_events_2; } else { @@ -551,6 +552,12 @@ int uv_poll_init_socket(uv_loop_t* loop, uv_poll_t* handle, handle->poll_req_2.type = UV_POLL_REQ; handle->poll_req_2.data = handle; + handle->afd_poll_info_2.afd_poll_info_ptr = malloc(sizeof(*handle->afd_poll_info_2.afd_poll_info_ptr) * 2); + if (handle->afd_poll_info_2.afd_poll_info_ptr == NULL) { + uv__set_artificial_error(loop, UV_ENOMEM); + return -1; + } + return 0; } @@ -604,5 +611,9 @@ void uv_poll_endgame(uv_loop_t* loop, uv_poll_t* handle) { assert(handle->submitted_events_1 == 0); assert(handle->submitted_events_2 == 0); + if (handle->afd_poll_info_2.afd_poll_info_ptr) { + free(handle->afd_poll_info_2.afd_poll_info_ptr); + handle->afd_poll_info_2.afd_poll_info_ptr = NULL; + } uv__handle_close(handle); } diff --git a/deps/uv/test/test-poll-closesocket.c b/deps/uv/test/test-poll-closesocket.c index 4db74a01f63..28114de07a1 100644 --- a/deps/uv/test/test-poll-closesocket.c +++ b/deps/uv/test/test-poll-closesocket.c @@ -67,8 +67,7 @@ TEST_IMPL(poll_closesocket) { r = ioctlsocket(sock, FIONBIO, &on); ASSERT(r == 0); - r = uv_ip4_addr("127.0.0.1", TEST_PORT, &addr); - ASSERT(r == 0); + addr = uv_ip4_addr("127.0.0.1", TEST_PORT); r = connect(sock, (const struct sockaddr*) &addr, sizeof addr); ASSERT(r != 0);