81 printf ("Continuing thread %d.\n", i);
82 status = thd_continue (threads[i]);
83 if (status != 0)
84 err_abort (status, "Continue thread");
85 }
86
87 pthread_exit (NULL); /* Let threads finish */
88 }
■ susp.c part 5 sampleprogram
6.6.4 sigwait and sigwaitinfo
int sigwait (const sigset_t *set, int *sig);
#ifdef _POSIX_REALTIME_SIGNALS
int sigwaitinfo (const sigset_t *set, siginfo_t *info);
int sigtimedwait (const sigset_t *set, siginfo_t *info, const struct timespec *timeout);
#endif
Always use sigwait
to work with asynchronous signals within threaded code.
Pthreads adds a function to allow threaded programs to deal with "asynchronous" signals synchronously. That is, instead of allowing a signal to interrupt a thread at some arbitrary point, a thread can choose to receive a signal synchronously. It does this by calling sigwait
, or one of sigwait's siblings.
The signals for which you sigwait
must be masked in the sigwaiting thread,and should usually be masked in all threads.
The sigwait
function takes a signal set as its argument, and returns a signal number when any signal in that set occurs. You can create a thread that waits for some signal, for example, SIGINT, and causes some application activity when it occurs. The non-obvious rule is that the signals for which you wait must be masked before calling sigwait
. In fact, you should ideally mask these signals in main, at the start of the program. Because signal masks are inherited by threads you create, all threads will (by default) have the signal masked. This ensures that the signal will never be delivered to any thread except the one that calls sigwait
.
Signals are delivered only once. If two threads are blocked in sigwait
, only one of them will receive a signal that's sent to the process. This means you can't, for example, have two independent subsystems using sigwait
that catch SIGINT. It also means that the signal will not be caught by sigwait
in one thread and also delivered to some signal-catching function in another thread. That's not so bad, since you couldn't do that in the old nonthreaded model either — only one signal action can be active at a time.
While sigwait
, a Pthreads function, reports errors by returning an error number, its siblings, sigwaitinfo
and sigtimedwait
, were added to POSIX prior to Pthreads, and use the older errno
mechanism. This is confusing and awkward, and that is unfortunate. The problem is that they deal with the additional information supplied by the POSIX realtime signals option (
Both sigwaitinfo
and sigtimedwait
return the realtime signal information, siginfo_t
, for signals received. In addition, sigtimedwait
allows the caller to specify that sigtimedwait
should return with the error EAGAIN in the event that none of the selected signals is received within the specified interval.
The sigwait.c program creates a "sigwait thread" that handles SIGINT.
23-41 The signal_waiter thread repeatedly calls sigwait, waiting for a SIGINT signal. It counts five occurrences of SIGINT (printing a message each time), and then signals a condition variable on which main is waiting. At that time, main will exit.
61-65 The main program begins by masking SIGINT. Because all threads inherit their initial signal mask from their creator, SIGINT will be masked in all threads. This prevents SIGINT from being delivered at any time except when the signal_ waiter thread is blocked in sigwait and ready to receive the signal.
■ sigwait.c
1 #include
2 #include
3 #include
4 #include
5 #include "errors.h"
6
7 pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
8 pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
9 int interrupted = 0;
10 sigset_t signal set;
12 /*
13 * Wait for the SIGINT signal. When it has occurred 5 times, set the