global/signal_handler: use poll(2) instead of select(2)

Starting with commit 61a298c39c we delay the
signal handler setup until after lots of other initialization has happened,
which can result in us having very large (>1024) open fds, which will
break the FD_SET macros for select(2).  Use poll(2) instead.

Fixes: #5722
Signed-off-by: Sage Weil <sage@inktank.com>
Reviewed-by: Yehuda Sadeh <yehuda@inktank.com>
This commit is contained in:
Sage Weil 2013-07-23 21:27:50 -07:00
parent 4183b74b00
commit 8e4a78f169
2 changed files with 39 additions and 10 deletions

View File

@ -19,6 +19,7 @@
#include "global/pidfile.h"
#include "global/signal_handler.h"
#include <poll.h>
#include <signal.h>
#include <sstream>
#include <stdlib.h>
@ -189,25 +190,23 @@ struct SignalHandler : public Thread {
// thread entry point
void *entry() {
while (!stop) {
// create fd set
fd_set rfds;
FD_ZERO(&rfds);
FD_SET(pipefd[0], &rfds);
int max_fd = pipefd[0];
// build fd list
struct pollfd fds[33];
lock.Lock();
int num_fds = 0;
for (unsigned i=0; i<32; i++) {
if (handlers[i]) {
int fd = handlers[i]->pipefd[0];
FD_SET(fd, &rfds);
if (fd > max_fd)
max_fd = fd;
fds[num_fds].fd = handlers[i]->pipefd[0];
fds[num_fds].events = POLLIN | POLLOUT | POLLERR;
fds[num_fds].revents = 0;
++num_fds;
}
}
lock.Unlock();
// wait for data on any of those pipes
int r = select(max_fd + 1, &rfds, NULL, NULL, NULL);
int r = poll(fds, num_fds, -1);
if (stop)
break;
if (r > 0) {

View File

@ -110,3 +110,33 @@ TEST(SignalHandler, Multiple)
unregister_async_signal_handler(SIGUSR2, testhandler);
shutdown_async_signal_handler();
}
/*
TEST(SignalHandler, MultipleBigFd)
{
int ret;
for (int i = 0; i < 1500; i++)
::open(".", O_RDONLY);
reset();
init_async_signal_handler();
register_async_signal_handler(SIGUSR1, testhandler);
register_async_signal_handler(SIGUSR2, testhandler);
ASSERT_TRUE(usr1 == false);
ASSERT_TRUE(usr2 == false);
ret = kill(getpid(), SIGUSR1);
ASSERT_EQ(ret, 0);
ret = kill(getpid(), SIGUSR2);
ASSERT_EQ(ret, 0);
sleep(1);
ASSERT_TRUE(usr1 == true);
ASSERT_TRUE(usr2 == true);
unregister_async_signal_handler(SIGUSR1, testhandler);
unregister_async_signal_handler(SIGUSR2, testhandler);
shutdown_async_signal_handler();
}
*/