OpenSolaris

Printable Version Enter a New Search
Bug ID 6565817
Synopsis sigwait can't wait for SIGTSTP
State 10-Fix Delivered (Fix available in build)
Category:Subcategory kernel:syscall
Keywords
Responsible Engineer Roger Faulkner
Reported Against snv_65
Duplicate Of
Introduced In solaris_2.3
Commit to Fix snv_114
Fixed In snv_114
Release Fixed solaris_nevada(snv_114)
Related Bugs 6817526 , 6845184 , 6857047 , 6861646
Submit Date 5-June-2007
Last Update Date 6-May-2009
Description
A user on an opesolaris forum reported that sigwait does not work for SIGTSTP:

#define _POSIX_PTHREAD_SEMANTICS 1

#include <signal.h>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <stdio.h>

static sigset_t    initSigMask;

int
main(int argc, char *argv[])
{
    pthread_t pth1;
    int rc;
    int k;

    if (argv[1] == NULL) {
        fprintf(stderr, "Usage: %s signal\n", argv[0]);
        exit(1);
    }
    rc = sigemptyset(&initSigMask);
    rc = sigaddset(&initSigMask,atoi(argv[1] ));
    printf("kill -%d %d\n", atoi(argv[1]), getpid());
    rc = sigprocmask(SIG_BLOCK,&initSigMask,NULL);

    while(1) {
       rc = sigwait(&initSigMask,&k);
       fprintf(stderr,"k = %d %d %d\n",k,errno,rc);
   }
}

When run as

sigwait 24

it still stops with SIGTSTP.

When run with other signals like SIGINT, it properly handles
the signal:
^Ck = 2 0 0
^Ck = 2 0 0
^Ck = 2 0 0
^Ck = 2 0 0
^\Quit (core dumped)

Some applications clearly need to handle SIGTSTP (e.g., to restore terminal
settings); it appears that such is not possible with sigwait().
Work Around
Set up a dummy signal handler for the job control signal
that is to be accepted by sigwait() (it will never be invoked
so long as the signal is blocked everywhere except in the
invocation of sigwait()):

static void
intr(int sig)
{
}
...
        (void) signal(SIGTSTP, intr);
...
        (void) sigaddset(&sigmask, SIGTSTP);
        sigwait(&sigmask, &sig);
Comments
The test case for the changes described here is the
attached 'sigwait.c' file.

Compile like this:

cc -O -o sigwait sigwait.c

Run like this:

$ ./sigwait
usage: sigwait -[cdi]
    -c: set all job control signals to be caught
    -d: set all job control signal actions to default
    -i: set all job control signal actions to ignore
  then loop, accepting all job control signals via sigwait()

For example:

$ ./sigwait -i
kill me:
  kill -STOP 137919
  kill -TSTP 137919
  kill -CONT 137919
  kill -TTIN 137919
  kill -TTOU 137919

Then from another session, perform the actions requested
and you will see the expected responses:

sig = 24 (SIGTSTP)  errno = 0  rc = 0
sig = 25 (SIGCONT)  errno = 0  rc = 0
sig = 26 (SIGTTIN)  errno = 0  rc = 0
sig = 27 (SIGTTOU)  errno = 0  rc = 0

The responses will be the same, regardless of which option
(-c, -d, or -i) is used.

The behavior is the same on a Linux machine and on a Solaris
machine with the fix applied.