From 751ac48baaa481202ae321af6f2842c2acf32cdc Mon Sep 17 00:00:00 2001 From: Ben Noordhuis Date: Thu, 25 Dec 2014 14:11:55 +0100 Subject: [PATCH] linux: fix epoll_pwait() sigmask size calculation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Revisit the fix from commit b705b53. The problem with using sigset_t and _NSIG is that the size of sigset_t and the value of _NSIG depend on what headers libuv picks up first, or . With the former, sizeof(sigset_t) = 128; with the latter, it's 8. Simply sidestep the issue by calculating the signal mask as a 64 bits integer, without using sigset_t or _NSIG. PR-URL: https://github.com/libuv/libuv/pull/83 Reviewed-By: Saúl Ibarra Corretgé --- Makefile.am | 1 + src/unix/linux-core.c | 17 ++++++----------- src/unix/linux-syscalls.c | 6 +++--- src/unix/linux-syscalls.h | 2 +- test/test-list.h | 2 ++ test/test-loop-configure.c | 38 ++++++++++++++++++++++++++++++++++++++ uv.gyp | 1 + 7 files changed, 52 insertions(+), 15 deletions(-) create mode 100644 test/test-loop-configure.c diff --git a/Makefile.am b/Makefile.am index daada8a2..16a7da40 100644 --- a/Makefile.am +++ b/Makefile.am @@ -159,6 +159,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \ test/test-loop-close.c \ test/test-loop-stop.c \ test/test-loop-time.c \ + test/test-loop-configure.c \ test/test-multiple-listen.c \ test/test-mutexes.c \ test/test-osx-select.c \ diff --git a/src/unix/linux-core.c b/src/unix/linux-core.c index a2145b0f..4ff1a848 100644 --- a/src/unix/linux-core.c +++ b/src/unix/linux-core.c @@ -33,7 +33,6 @@ #include #include #include -#include #include #include @@ -142,8 +141,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) { struct uv__epoll_event e; QUEUE* q; uv__io_t* w; - sigset_t* pset; - sigset_t set; + uint64_t sigmask; uint64_t base; uint64_t diff; int nevents; @@ -194,24 +192,21 @@ 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); - } + sigmask = 0; + if (loop->flags & UV_LOOP_BLOCK_SIGPROF) + sigmask |= 1 << (SIGPROF - 1); assert(timeout >= -1); base = loop->time; count = 48; /* Benchmarks suggest this gives the best throughput. */ for (;;) { - if (no_epoll_wait || pset != NULL) { + if (no_epoll_wait || sigmask) { nfds = uv__epoll_pwait(loop->backend_fd, events, ARRAY_SIZE(events), timeout, - pset); + sigmask); } else { nfds = uv__epoll_wait(loop->backend_fd, events, diff --git a/src/unix/linux-syscalls.c b/src/unix/linux-syscalls.c index e036fad5..7bf2c0f8 100644 --- a/src/unix/linux-syscalls.c +++ b/src/unix/linux-syscalls.c @@ -321,15 +321,15 @@ int uv__epoll_pwait(int epfd, struct uv__epoll_event* events, int nevents, int timeout, - const sigset_t* sigmask) { + uint64_t sigmask) { #if defined(__NR_epoll_pwait) return syscall(__NR_epoll_pwait, epfd, events, nevents, timeout, - sigmask, - _NSIG / 8); + &sigmask, + sizeof(sigmask)); #else return errno = ENOSYS, -1; #endif diff --git a/src/unix/linux-syscalls.h b/src/unix/linux-syscalls.h index fd6bb486..6f249b72 100644 --- a/src/unix/linux-syscalls.h +++ b/src/unix/linux-syscalls.h @@ -131,7 +131,7 @@ int uv__epoll_pwait(int epfd, struct uv__epoll_event* events, int nevents, int timeout, - const sigset_t* sigmask); + uint64_t sigmask); int uv__eventfd2(unsigned int count, int flags); int uv__inotify_init(void); int uv__inotify_init1(int flags); diff --git a/test/test-list.h b/test/test-list.h index 2c307d5c..9c888554 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -29,6 +29,7 @@ TEST_DECLARE (loop_close) TEST_DECLARE (loop_stop) TEST_DECLARE (loop_update_time) TEST_DECLARE (loop_backend_timeout) +TEST_DECLARE (loop_configure) TEST_DECLARE (default_loop_close) TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_2) @@ -313,6 +314,7 @@ TASK_LIST_START TEST_ENTRY (loop_stop) TEST_ENTRY (loop_update_time) TEST_ENTRY (loop_backend_timeout) + TEST_ENTRY (loop_configure) TEST_ENTRY (default_loop_close) TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_2) diff --git a/test/test-loop-configure.c b/test/test-loop-configure.c new file mode 100644 index 00000000..d057c1ed --- /dev/null +++ b/test/test-loop-configure.c @@ -0,0 +1,38 @@ +/* Copyright (c) 2014, Ben Noordhuis + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include "uv.h" +#include "task.h" + +static void timer_cb(uv_timer_t* handle) { + uv_close((uv_handle_t*) handle, NULL); +} + + +TEST_IMPL(loop_configure) { + uv_timer_t timer_handle; + uv_loop_t loop; + ASSERT(0 == uv_loop_init(&loop)); +#ifdef _WIN32 + ASSERT(UV_ENOSYS == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, 0)); +#else + ASSERT(0 == uv_loop_configure(&loop, UV_LOOP_BLOCK_SIGNAL, SIGPROF)); +#endif + ASSERT(0 == uv_timer_init(&loop, &timer_handle)); + ASSERT(0 == uv_timer_start(&timer_handle, timer_cb, 10, 0)); + ASSERT(0 == uv_run(&loop, UV_RUN_DEFAULT)); + ASSERT(0 == uv_loop_close(&loop)); + return 0; +} diff --git a/uv.gyp b/uv.gyp index caad9704..45af6a1f 100644 --- a/uv.gyp +++ b/uv.gyp @@ -315,6 +315,7 @@ 'test/test-loop-close.c', 'test/test-loop-stop.c', 'test/test-loop-time.c', + 'test/test-loop-configure.c', 'test/test-walk-handles.c', 'test/test-watcher-cross-stop.c', 'test/test-multiple-listen.c',