sigwait() resumed by ignored signal
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
glibc (Ubuntu) |
New
|
Undecided
|
Unassigned |
Bug Description
A program that sets the disposition of a signal to ignore (SIG_IGN) should not
be affected by the ignored signals. However, this is not the case when it calls
sigwait().
Compile and run this program file (sigwait.c):
#include <stdio.h>
#include <signal.h>
int main(int argc, char* argv[]){
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
if (sigaction(
return 1;
}
sigset_t mask;
sigemptyset
sigaddset(
sigprocmask
int sig = 0;
sigwait(
printf("got %d\n",sig);
}
$ gcc sigwait.c
$ ./a.out
Then send it a SIGHUP signal (e.g. kill -HUP pid from another terminal). The result is:
got 1
I.e. the program, instead of ignoring the signal, is waked up by it. Apparently, sigwait()
seems to handle an ignored signal as if it was not ignored.
Found in Ubuntu 9.04
affects: | ubuntu → glibc (Ubuntu) |
I understand that this is probably inconvenient for you otherwise you wouldn't have filed the bug, but as far as I can tell this is actually behaving as specified.
SIG_IGN doesn't mean "this signal no longer exists as far as this process is concerned"; it means "upon receiving this signal, take no action". Take an example program like this:
#include <signal.h> SIGHUP, &sa, NULL);
#include <unistd.h>
int main(int argc, char *argv[]) {
struct sigaction sa;
sa.sa_flags = 0;
sa.sa_handler = SIG_IGN;
sigaction(
pause();
return 0;
}
If you strace that and send it SIGHUP from another terminal, you'll see that it still receives the signal; it just does nothing with it. By the same token, sigwait() gives you a pending signal, without regard for the *action* that would be taken upon receiving that signal.
By contrast, sigsuspend()'s specification explicitly says that it waits for "delivery of a signal whose action is either to execute a signal-catching function or to terminate the process" (sigwait()'s specification does not have this restriction). So, maybe you could use code more like the following?
sigset_t mask; (SIG_SETMASK, NULL, &mask); &mask);
sigprocmask
sigsuspend(