linux: fix epoll_pwait() sigmask size calculation

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, <signal.h> or <asm/signal.h>.
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é <saghul@gmail.com>
This commit is contained in:
Ben Noordhuis 2014-12-25 14:11:55 +01:00
parent a6d3d5a0f5
commit 751ac48baa
7 changed files with 52 additions and 15 deletions

View File

@ -159,6 +159,7 @@ test_run_tests_SOURCES = test/blackhole-server.c \
test/test-loop-close.c \ test/test-loop-close.c \
test/test-loop-stop.c \ test/test-loop-stop.c \
test/test-loop-time.c \ test/test-loop-time.c \
test/test-loop-configure.c \
test/test-multiple-listen.c \ test/test-multiple-listen.c \
test/test-mutexes.c \ test/test-mutexes.c \
test/test-osx-select.c \ test/test-osx-select.c \

View File

@ -33,7 +33,6 @@
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/sysinfo.h> #include <sys/sysinfo.h>
#include <unistd.h> #include <unistd.h>
#include <signal.h>
#include <fcntl.h> #include <fcntl.h>
#include <time.h> #include <time.h>
@ -142,8 +141,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
struct uv__epoll_event e; struct uv__epoll_event e;
QUEUE* q; QUEUE* q;
uv__io_t* w; uv__io_t* w;
sigset_t* pset; uint64_t sigmask;
sigset_t set;
uint64_t base; uint64_t base;
uint64_t diff; uint64_t diff;
int nevents; int nevents;
@ -194,24 +192,21 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
w->events = w->pevents; w->events = w->pevents;
} }
pset = NULL; sigmask = 0;
if (loop->flags & UV_LOOP_BLOCK_SIGPROF) { if (loop->flags & UV_LOOP_BLOCK_SIGPROF)
pset = &set; sigmask |= 1 << (SIGPROF - 1);
sigemptyset(pset);
sigaddset(pset, SIGPROF);
}
assert(timeout >= -1); assert(timeout >= -1);
base = loop->time; base = loop->time;
count = 48; /* Benchmarks suggest this gives the best throughput. */ count = 48; /* Benchmarks suggest this gives the best throughput. */
for (;;) { for (;;) {
if (no_epoll_wait || pset != NULL) { if (no_epoll_wait || sigmask) {
nfds = uv__epoll_pwait(loop->backend_fd, nfds = uv__epoll_pwait(loop->backend_fd,
events, events,
ARRAY_SIZE(events), ARRAY_SIZE(events),
timeout, timeout,
pset); sigmask);
} else { } else {
nfds = uv__epoll_wait(loop->backend_fd, nfds = uv__epoll_wait(loop->backend_fd,
events, events,

View File

@ -321,15 +321,15 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events, struct uv__epoll_event* events,
int nevents, int nevents,
int timeout, int timeout,
const sigset_t* sigmask) { uint64_t sigmask) {
#if defined(__NR_epoll_pwait) #if defined(__NR_epoll_pwait)
return syscall(__NR_epoll_pwait, return syscall(__NR_epoll_pwait,
epfd, epfd,
events, events,
nevents, nevents,
timeout, timeout,
sigmask, &sigmask,
_NSIG / 8); sizeof(sigmask));
#else #else
return errno = ENOSYS, -1; return errno = ENOSYS, -1;
#endif #endif

View File

@ -131,7 +131,7 @@ int uv__epoll_pwait(int epfd,
struct uv__epoll_event* events, struct uv__epoll_event* events,
int nevents, int nevents,
int timeout, int timeout,
const sigset_t* sigmask); uint64_t sigmask);
int uv__eventfd2(unsigned int count, int flags); int uv__eventfd2(unsigned int count, int flags);
int uv__inotify_init(void); int uv__inotify_init(void);
int uv__inotify_init1(int flags); int uv__inotify_init1(int flags);

View File

@ -29,6 +29,7 @@ TEST_DECLARE (loop_close)
TEST_DECLARE (loop_stop) TEST_DECLARE (loop_stop)
TEST_DECLARE (loop_update_time) TEST_DECLARE (loop_update_time)
TEST_DECLARE (loop_backend_timeout) TEST_DECLARE (loop_backend_timeout)
TEST_DECLARE (loop_configure)
TEST_DECLARE (default_loop_close) TEST_DECLARE (default_loop_close)
TEST_DECLARE (barrier_1) TEST_DECLARE (barrier_1)
TEST_DECLARE (barrier_2) TEST_DECLARE (barrier_2)
@ -313,6 +314,7 @@ TASK_LIST_START
TEST_ENTRY (loop_stop) TEST_ENTRY (loop_stop)
TEST_ENTRY (loop_update_time) TEST_ENTRY (loop_update_time)
TEST_ENTRY (loop_backend_timeout) TEST_ENTRY (loop_backend_timeout)
TEST_ENTRY (loop_configure)
TEST_ENTRY (default_loop_close) TEST_ENTRY (default_loop_close)
TEST_ENTRY (barrier_1) TEST_ENTRY (barrier_1)
TEST_ENTRY (barrier_2) TEST_ENTRY (barrier_2)

View File

@ -0,0 +1,38 @@
/* Copyright (c) 2014, Ben Noordhuis <info@bnoordhuis.nl>
*
* 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;
}

1
uv.gyp
View File

@ -315,6 +315,7 @@
'test/test-loop-close.c', 'test/test-loop-close.c',
'test/test-loop-stop.c', 'test/test-loop-stop.c',
'test/test-loop-time.c', 'test/test-loop-time.c',
'test/test-loop-configure.c',
'test/test-walk-handles.c', 'test/test-walk-handles.c',
'test/test-watcher-cross-stop.c', 'test/test-watcher-cross-stop.c',
'test/test-multiple-listen.c', 'test/test-multiple-listen.c',