-
Notifications
You must be signed in to change notification settings - Fork 63
/
Copy pathsigwait.c
98 lines (91 loc) · 2.93 KB
/
sigwait.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
/*
* sigwait.c
*
* Demonstrate use of sigwait() to synchronously handle
* asynchrnous signals within a threaded program.
*/
#include <sys/types.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include "errors.h"
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
int interrupted = 0;
sigset_t signal_set;
/*
* Wait for the SIGINT signal. When it has occurred 5 times, set
* the "interrupted" flag (the main thread's wait predicate) and
* signal a condition variable. The main thread will exit.
*/
void *signal_waiter (void *arg)
{
int sig_number;
int signal_count = 0;
int status;
while (1) {
sigwait (&signal_set, &sig_number);
if (sig_number == SIGINT) {
printf ("Got SIGINT (%d of 5)\n", signal_count+1);
if (++signal_count >= 5) {
status = pthread_mutex_lock (&mutex);
if (status != 0)
err_abort (status, "Lock mutex");
interrupted = 1;
status = pthread_cond_signal (&cond);
if (status != 0)
err_abort (status, "Signal condition");
status = pthread_mutex_unlock (&mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
break;
}
}
}
return NULL;
}
int main (int argc, char *argv[])
{
pthread_t signal_thread_id;
int status;
/*
* Start by masking the "interesting" signal, SIGINT in the
* initial thread. Because all threads inherit the signal mask
* from their creator, all threads in the process will have
* SIGINT masked unless one explicitly unmasks it. The
* semantics of sigwait require that all threads (including
* the thread calling sigwait) have the signal masked, for
* reliable operation. Otherwise, a signal that arrives
* while the sigwaiter is not blocked in sigwait might be
* delivered to another thread.
*/
sigemptyset (&signal_set);
sigaddset (&signal_set, SIGINT);
status = pthread_sigmask (SIG_BLOCK, &signal_set, NULL);
if (status != 0)
err_abort (status, "Set signal mask");
/*
* Create the sigwait thread.
*/
status = pthread_create (&signal_thread_id, NULL,
signal_waiter, NULL);
if (status != 0)
err_abort (status, "Create sigwaiter");
/*
* Wait for the sigwait thread to receive SIGINT and signal
* the condition variable.
*/
status = pthread_mutex_lock (&mutex);
if (status != 0)
err_abort (status, "Lock mutex");
while (!interrupted) {
status = pthread_cond_wait (&cond, &mutex);
if (status != 0)
err_abort (status, "Wait for interrupt");
}
status = pthread_mutex_unlock (&mutex);
if (status != 0)
err_abort (status, "Unlock mutex");
printf ("Main terminating with SIGINT\n");
return 0;
}