Fix raise(3) so it works in signal handlers.

We could special-case raise(3) in non-threaded programs, but the more
conservative course is to make pthread_kill(3) work in signal handlers
at the cost of a race shared by other C libraries.

Change-Id: I59fb23d03bdabf403435e731704b33acdf3e0234
This commit is contained in:
Elliott Hughes
2013-02-21 11:22:23 -08:00
parent ccd403161c
commit fae89fc404
4 changed files with 64 additions and 14 deletions

View File

@@ -76,6 +76,25 @@ static void TestSigSet2(Fn fn) {
ASSERT_EQ(0, errno);
}
class ScopedSignalHandler {
public:
ScopedSignalHandler(int signal_number, void (*handler)(int)) : signal_number_(signal_number) {
sigemptyset(&action_.sa_mask);
action_.sa_flags = 0;
action_.sa_handler = handler;
sigaction(signal_number_, &action_, &old_action_);
}
~ScopedSignalHandler() {
sigaction(signal_number_, &old_action_, NULL);
}
private:
struct sigaction action_;
struct sigaction old_action_;
const int signal_number_;
};
TEST(signal, sigismember_invalid) {
TestSigSet2(sigismember);
}
@@ -102,16 +121,25 @@ TEST(signal, raise_invalid) {
ASSERT_EQ(EINVAL, errno);
}
static void raise_in_signal_handler_helper(int signal_number) {
ASSERT_EQ(SIGALRM, signal_number);
static int count = 0;
if (++count == 1) {
raise(SIGALRM);
}
}
TEST(signal, raise_in_signal_handler) {
ScopedSignalHandler ssh(SIGALRM, raise_in_signal_handler_helper);
raise(SIGALRM);
}
static void HandleSIGALRM(int signal_number) {
ASSERT_EQ(SIGALRM, signal_number);
}
TEST(signal, sigwait) {
struct sigaction action;
sigemptyset(&action.sa_mask);
action.sa_flags = 0;
action.sa_handler = HandleSIGALRM;
sigaction(SIGALRM, &action, NULL);
ScopedSignalHandler ssh(SIGALRM, HandleSIGALRM);
sigset_t wait_set;
sigemptyset(&wait_set);