1thr_sigsetmask(3C) Standard C Library Functions thr_sigsetmask(3C)
2
3
4
6 thr_sigsetmask - change or examine calling thread's signal mask
7
9 cc -mt [ flag... ] file... [ library... ]
10 #include <thread.h>
11 #include <signal.h>
12
13 int thr_sigsetmask(int how, const sigset_t *set, sigset_t *oset);
14
15
17 The thr_sigsetmask() function changes or examines a calling thread's
18 signal mask. Each thread has its own signal mask. A new thread inherits
19 the calling thread's signal mask and priority; however, pending signals
20 are not inherited. Signals pending for a new thread will be empty.
21
22
23 If the value of the argument set is not NULL, set points to a set of
24 signals that can modify the currently blocked set. If the value of set
25 is NULL, the value of how is insignificant and the thread's signal mask
26 is unmodified; thus, thr_sigsetmask() can be used to inquire about the
27 currently blocked signals.
28
29
30 The value of the argument how specifies the method in which the set is
31 changed and takes one of the following values:
32
33 SIG_BLOCK set corresponds to a set of signals to block. They are
34 added to the current signal mask.
35
36
37 SIG_UNBLOCK set corresponds to a set of signals to unblock. These
38 signals are deleted from the current signal mask.
39
40
41 SIG_SETMASK set corresponds to the new signal mask. The current sig‐
42 nal mask is replaced by set.
43
44
45
46 If the value of oset is not NULL, it points to the location where the
47 previous signal mask is stored.
48
50 Upon successful completion, the thr_sigsetmask() function returns 0.
51 Otherwise, it returns a non-zero value.
52
54 The thr_sigsetmask() function will fail if:
55
56 EINVAL The value of how is not defined and oset is NULL.
57
58
60 Example 1 Create a default thread that can serve as a signal
61 catcher/handler with its own signal mask.
62
63
64 The following example shows how to create a default thread that can
65 serve as a signal catcher/handler with its own signal mask. new will
66 have a different value from the creator's signal mask.
67
68
69
70 As POSIX threads and Solaris threads are fully compatible even within
71 the same process, this example uses pthread_create(3C) if you execute
72 a.out 0, or thr_create(3C) if you execute a.out 1.
73
74
75
76 In this example:
77
78
79 o The sigemptyset(3C) function initializes a null signal set,
80 new. The sigaddset(3C) function packs the signal, SIGINT,
81 into that new set.
82
83 o Either pthread_sigmask() or thr_sigsetmask() is used to mask
84 the signal, SIGINT (CTRL-C), from the calling thread, which
85 is main(). The signal is masked to guarantee that only the
86 new thread will receive this signal.
87
88 o pthread_create() or thr_create() creates the signal-handling
89 thread.
90
91 o Using pthread_join(3C) or thr_join(3C), main() then waits
92 for the termination of that signal-handling thread, whose ID
93 number is user_threadID. Then main() will sleep(3C) for 2
94 seconds, after which the program terminates.
95
96 o The signal-handling thread, handler:
97
98 o Assigns the handler interrupt() to handle the signal
99 SIGINT by the call to sigaction(2).
100
101 o Resets its own signal set to not block the signal, SIG‐
102 INT.
103
104 o Sleeps for 8 seconds to allow time for the user to
105 deliver the signal SIGINT by pressing the CTRL-C.
106
107 /* cc thisfile.c -lthread -lpthread */
108 #define _REENTRANT /* basic first 3-lines for threads */
109 #include <pthread.h>
110 #include <thread.h>
111
112 thread_t user_threadID;
113 sigset_t new;
114 void *handler(), interrupt();
115
116 int
117 main( int argc, char *argv[] ){
118 test_argv(argv[1]);
119
120 sigemptyset(&new);
121 sigaddset(&new, SIGINT);
122 switch(*argv[1]) {
123
124 case '0': /* POSIX */
125 pthread_sigmask(SIG_BLOCK, &new, NULL);
126 pthread_create(&user_threadID, NULL, handler, argv[1]);
127 pthread_join(user_threadID, NULL);
128 break;
129
130 case '1': /* Solaris */
131 thr_sigsetmask(SIG_BLOCK, &new, NULL);
132 thr_create(NULL, 0, handler, argv[1], 0, &user_threadID);
133 thr_join(user_threadID, NULL, NULL);
134 break;
135 } /* switch */
136
137 printf("thread handler, # %d, has exited\n",user_threadID);
138 sleep(2);
139 printf("main thread, # %d is done\n", thr_self());
140 return (0)
141 } /* end main */
142
143 struct sigaction act;
144
145 void *
146 handler(char *argv1)
147 {
148 act.sa_handler = interrupt;
149 sigaction(SIGINT, &act, NULL);
150 switch(*argv1){
151 case '0': /* POSIX */
152 pthread_sigmask(SIG_UNBLOCK, &new, NULL);
153 break;
154 case '1': /* Solaris */
155 thr_sigsetmask(SIG_UNBLOCK, &new, NULL);
156 break;
157 }
158 printf("\n Press CTRL-C to deliver SIGINT signal to the process\n");
159 sleep(8); /* give user time to hit CTRL-C */
160 return (NULL)
161 }
162
163 void
164 interrupt(int sig)
165 {
166 printf("thread %d caught signal %d\n", thr_self(), sig);
167 }
168
169 void test_argv(char argv1[]) {
170 if(argv1 == NULL) {
171 printf("use 0 as arg1 to use thr_create();\n \
172 or use 1 as arg1 to use pthread_create()\n");
173 exit(NULL);
174 }
175 }
176
177
178
179 In the last example, the handler thread served as a signal-handler
180 while also taking care of activity of its own (in this case, sleeping,
181 although it could have been some other activity). A thread could be
182 completely dedicated to signal-handling simply by waiting for the
183 delivery of a selected signal by blocking with sigwait(2). The two sub‐
184 routines in the previous example, handler() and interrupt(), could
185 have been replaced with the following routine:
186
187
188 void *
189 handler(void *ignore)
190 { int signal;
191 printf("thread %d waiting for you to press the CTRL-C keys\n",
192 thr_self());
193 sigwait(&new, &signal);
194 printf("thread %d has received the signal %d \n", thr_self(), signal);
195 }
196 /*pthread_create() and thr_create() would use NULL instead of
197 argv[1] for the arg passed to handler() */
198
199
200
201 In this routine, one thread is dedicated to catching and handling the
202 signal specified by the set new, which allows main() and all of its
203 other sub-threads, created after pthread_sigmask() or thr_sigsetmask()
204 masked that signal, to continue uninterrupted. Any use of sigwait(2)
205 should be such that all threads block the signals passed to sigwait(2)
206 at all times. Only the thread that calls sigwait() will get the sig‐
207 nals. The call to sigwait(2) takes two arguments.
208
209
210
211 For this type of background dedicated signal-handling routine, a
212 Solaris daemon thread can be used by passing the argument THR_DAEMON to
213 thr_create().
214
215
217 See attributes(5) for descriptions of the following attributes:
218
219
220
221
222 ┌─────────────────────────────┬──────────────────────────────┐
223 │ ATTRIBUTE TYPE │ ATTRIBUTE VALUE │
224 ├─────────────────────────────┼──────────────────────────────┤
225 │MT-Level │MT-Safe and Async-Signal-Safe │
226 └─────────────────────────────┴──────────────────────────────┘
227
229 sigaction(2), sigprocmask(2), sigwait(2), cond_wait(3C), pthread_can‐
230 cel(3C), pthread_create(3C), pthread_join(3C), pthread_self(3C),
231 sigaddset(3C), sigemptyset(3C), sigsetops(3C), sleep(3C),
232 attributes(5), cancellation(5), standards(5)
233
235 It is not possible to block signals that cannot be caught or ignored
236 (see sigaction(2)). It is also not possible to block or unblock SIGCAN‐
237 CEL, as SIGCANCEL is reserved for the implementation of POSIX thread
238 cancellation (see pthread_cancel(3C) and cancellation(5)). This
239 restriction is quietly enforced by the standard C library.
240
241
242 Using sigwait(2) in a dedicated thread allows asynchronously generated
243 signals to be managed synchronously; however, sigwait(2) should never
244 be used to manage synchronously generated signals.
245
246
247 Synchronously generated signals are exceptions that are generated by a
248 thread and are directed at the thread causing the exception. Since sig‐
249 wait() blocks waiting for signals, the blocking thread cannot receive a
250 synchronously generated signal.
251
252
253 Calling thesigprocmask(2) function will be the same as if thr_sigset‐
254 mask() or pthread_sigmask() has been called. POSIX leaves the semantics
255 of the call to sigprocmask(2) unspecified in a multi-threaded process,
256 so programs that care about POSIX portability should not depend on this
257 semantic.
258
259
260 If a signal is delivered while a thread is waiting on a condition
261 variable, the cond_wait(3C) function will be interrupted and the han‐
262 dler will be executed. The state of the lock protecting the condition
263 variable is undefined while the thread is executing the signal handler.
264
265
266 Signals that are generated synchronously should not be masked. If such
267 a signal is blocked and delivered, the receiving process is killed.
268
269
270
271SunOS 5.11 23 Mar 2005 thr_sigsetmask(3C)