sigwait() resumed by ignored signal

Bug #431813 reported by Angelo Borsotti
8
This bug affects 1 person
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(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)
Revision history for this message
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);

Revision history for this message
Angelo Borsotti (angelo-borsotti) wrote : Re: [Bug 431813] Re: sigwait() resumed by ignored signal

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

Revision history for this message
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.

Revision history for this message
Angelo Borsotti (angelo-borsotti) wrote :

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  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.