sigwait() resumed by ignored signal

Bug #431813 reported by Angelo Borsotti on 2009-09-17
8
This bug affects 1 person
Affects Status Importance Assigned to Milestone
glibc (Ubuntu)
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(SIGHUP,&sa,NULL) < 0){
        perror("sigaction error");
        return 1;
    }
    sigset_t mask;
    sigemptyset(&mask);
    sigaddset(&mask,SIGHUP);
    sigprocmask(SIG_BLOCK,&mask,NULL);
    int sig = 0;
    sigwait(&mask,&sig);
    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)
Colin Watson (cjwatson) wrote :

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>
#include <unistd.h>
int main(int argc, char *argv[]) {
    struct sigaction sa;
    sa.sa_flags = 0;
    sa.sa_handler = SIG_IGN;
    sigaction(SIGHUP, &sa, NULL);
    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;
    sigprocmask(SIG_SETMASK, NULL, &mask);
    sigsuspend(&mask);

Hi,

thank you for your quich reply. I understand what you write. I would rather
then explain the behaviour of sigwait() telling that it overrides the
disposition
of the signals specified in its argument, or that sets a new disposition for
it.
This preserves the correctness of the use of the word "ignore" ("to refuse
to take notice of" -Merrian-Webster dictionary) in the man pages, which
would not otherwise
be the case stating that the program takes notice of something it is not
told to do.

Thank you
-Angelo Borsotti

Colin Watson (cjwatson) wrote :

sigwait neither overrides signal dispositions nor does it set new
dispositions; it simply disregards the dispositions altogether. It's at
a different layer.

Hi,

I know, sigwait() does not change the disposition set by sigaction(), but
from the user's point takes precedence over it. "Override" means
"prevail over". Isn't it the correct word to explain what it does?

-Angelo

To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers