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.