base: Clean up signal handling

The PollEvent class dynamically installs a SIGIO and SIGALRM handler
when a file handler is registered. Most signal handlers currently get
registered in the initSignals() function. This changeset moves the
SIGIO/SIGALRM handlers to initSignals() to live with the other signal
handlers. The original code installs SIGIO and SIGALRM with the
SA_RESTART option to prevent syscalls from returning EINTR. This
changeset consistently uses this flag for all signal handlers to
ensure that other signals that trigger asynchronous behavior (e.g.,
statistics dumping) do not cause undesirable EINTR returns.
This commit is contained in:
Andreas Sandberg 2013-11-29 14:35:36 +01:00
parent 2823982a3c
commit 9c57d5b5a6
3 changed files with 48 additions and 75 deletions

View file

@ -109,7 +109,6 @@ PollQueue::PollQueue()
PollQueue::~PollQueue()
{
removeHandler();
for (int i = 0; i < num_fds; i++)
setupAsyncIO(poll_fds[0].fd, false);
@ -170,7 +169,6 @@ PollQueue::schedule(PollEvent *event)
max_size *= 2;
} else {
max_size = 16;
setupHandler();
}
poll_fds = new pollfd[max_size];
@ -197,10 +195,6 @@ PollQueue::service()
}
}
struct sigaction PollQueue::oldio;
struct sigaction PollQueue::oldalrm;
bool PollQueue::handler = false;
void
PollQueue::setupAsyncIO(int fd, bool set)
{
@ -221,59 +215,3 @@ PollQueue::setupAsyncIO(int fd, bool set)
if (fcntl(fd, F_SETFL, flags) == -1)
panic("Could not set up async IO");
}
void
PollQueue::setupHandler()
{
struct sigaction act;
act.sa_handler = handleIO;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction(SIGIO, &act, &oldio) == -1)
panic("could not do sigaction");
act.sa_handler = handleALRM;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
if (sigaction(SIGALRM, &act, &oldalrm) == -1)
panic("could not do sigaction");
alarm(1);
handler = true;
}
void
PollQueue::removeHandler()
{
if (sigaction(SIGIO, &oldio, NULL) == -1)
panic("could not remove handler");
if (sigaction(SIGIO, &oldalrm, NULL) == -1)
panic("could not remove handler");
}
void
PollQueue::handleIO(int sig)
{
if (sig != SIGIO)
panic("Wrong Handler");
async_event = true;
async_io = true;
}
void
PollQueue::handleALRM(int sig)
{
if (sig != SIGALRM)
panic("Wrong Handler");
async_event = true;
async_alarm = true;
alarm(1);
}

View file

@ -83,17 +83,8 @@ class PollQueue
void schedule(PollEvent *event);
void service();
protected:
static bool handler;
static struct sigaction oldio;
static struct sigaction oldalrm;
public:
static void setupAsyncIO(int fd, bool set);
static void handleIO(int);
static void handleALRM(int);
static void removeHandler();
static void setupHandler();
};
extern PollQueue pollQueue;

View file

@ -96,6 +96,37 @@ abortHandler(int sigtype)
ccprintf(cerr, "Program aborted at cycle %d\n", curTick());
}
// Handle SIGIO
static void
ioHandler(int sigtype)
{
async_event = true;
async_io = true;
}
// Handle SIGALRM
static void
alrmHandler(int sigtype)
{
async_event = true;
async_alarm = true;
alarm(1);
}
static void
installSignalHandler(int signal, void (*handler)(int sigtype))
{
struct sigaction sa;
memset(&sa, 0, sizeof(sa));
sigemptyset(&sa.sa_mask);
sa.sa_handler = handler;
sa.sa_flags = SA_RESTART;
if (sigaction(signal, &sa, NULL) == -1)
panic("Failed to setup handler for signal %i\n", signal);
}
/*
* M5 can do several special things when various signals are sent.
* None are mandatory.
@ -111,16 +142,29 @@ initSignals()
signal(SIGTRAP, SIG_IGN);
// Dump intermediate stats
signal(SIGUSR1, dumpStatsHandler);
installSignalHandler(SIGUSR1, dumpStatsHandler);
// Dump intermediate stats and reset them
signal(SIGUSR2, dumprstStatsHandler);
installSignalHandler(SIGUSR2, dumprstStatsHandler);
// Exit cleanly on Interrupt (Ctrl-C)
signal(SIGINT, exitNowHandler);
installSignalHandler(SIGINT, exitNowHandler);
// Print out cycle number on abort
signal(SIGABRT, abortHandler);
installSignalHandler(SIGABRT, abortHandler);
// Install a SIGIO handler to handle asynchronous file IO. See the
// PollQueue class.
installSignalHandler(SIGIO, ioHandler);
// Setup an alarm handler that triggers every second. This
// triggers a PollQueue service just like a SIGIO. It is
// /probably/ used to work around a bug in the poll queue (likely
// a race between setting up a asynchronous IO and data becoming
// available), but its use isn't documented anywhere.
// TODO: Find out why this is needed and fix the original bug.
installSignalHandler(SIGALRM, alrmHandler);
alarm(1);
}
// The python library is totally messed up with respect to constness,