2 * Copyright (c) 1998 Daniel M. Eischen <eischen@vigrid.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Daniel M. Eischen.
16 * 4. Neither the name of the author nor the names of any co-contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY DANIEL M. EISCHEN AND CONTRIBUTORS ``AS IS''
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 * $FreeBSD: src/lib/libc_r/test/sigsuspend_d.c,v 1.1.2.1 2000/07/17 22:18:32 jasone Exp $
33 * $DragonFly: src/lib/libc_r/test/sigsuspend_d.c,v 1.2 2003/06/17 04:26:48 dillon Exp $
45 #include <pthread_np.h>
48 static int sigcounts
[NSIG
+ 1];
49 static int sigfifo
[NSIG
+ 1];
50 static int fifo_depth
= 0;
51 static sigset_t suspender_mask
;
52 static pthread_t suspender_tid
;
56 sigsuspender (void *arg
)
58 int save_count
, status
, i
;
61 /* Run with all signals blocked. */
62 sigfillset (&run_mask
);
63 sigprocmask (SIG_SETMASK
, &run_mask
, NULL
);
65 /* Allow these signals to wake us up during a sigsuspend. */
66 sigfillset (&suspender_mask
); /* Default action */
67 sigdelset (&suspender_mask
, SIGINT
); /* terminate */
68 sigdelset (&suspender_mask
, SIGHUP
); /* terminate */
69 sigdelset (&suspender_mask
, SIGQUIT
); /* create core image */
70 sigdelset (&suspender_mask
, SIGURG
); /* ignore */
71 sigdelset (&suspender_mask
, SIGIO
); /* ignore */
72 sigdelset (&suspender_mask
, SIGUSR2
); /* terminate */
74 while (sigcounts
[SIGINT
] == 0) {
75 save_count
= sigcounts
[SIGUSR2
];
77 status
= sigsuspend (&suspender_mask
);
78 if ((status
== 0) || (errno
!= EINTR
)) {
79 fprintf (stderr
, "Unable to suspend for signals, "
80 "errno %d, return value %d\n",
84 for (i
= 0; i
< fifo_depth
; i
++)
85 fprintf (stderr
, "Sigsuspend woke up by signal %d\n",
96 sighandler (int signo
)
98 sigset_t set
, suspend_set
;
101 if ((signo
>= 0) && (signo
<= NSIG
))
105 * If we are running on behalf of the suspender thread,
106 * ensure that we have the correct mask set.
108 self
= pthread_self ();
109 if (self
== suspender_tid
) {
110 sigfifo
[fifo_depth
] = signo
;
113 " -> Suspender thread signal handler caught signal %d\n",
116 /* Get the current signal mask. */
117 sigprocmask (SIG_SETMASK
, NULL
, &set
);
119 /* The handler should run with the current signal masked. */
120 suspend_set
= suspender_mask
;
121 sigaddset(&suspend_set
, signo
);
123 if (memcmp(&set
, &suspend_set
, sizeof(set
)))
125 " >>> FAIL: sigsuspender signal handler running "
126 "with incorrect mask.\n");
130 " -> Main thread signal handler caught signal %d\n",
136 send_thread_signal (pthread_t tid
, int signo
)
138 if (pthread_kill (tid
, signo
) != 0) {
139 fprintf (stderr
, "Unable to send thread signal, errno %d.\n",
147 send_process_signal (int signo
)
149 if (kill (getpid (), signo
) != 0) {
150 fprintf (stderr
, "Unable to send process signal, errno %d.\n",
157 int main (int argc
, char *argv
[])
159 pthread_attr_t pattr
;
161 struct sigaction act
;
165 /* Initialize our signal counts. */
166 memset ((void *) sigcounts
, 0, NSIG
* sizeof (int));
168 /* Ignore signal SIGIO. */
169 sigemptyset (&act
.sa_mask
);
170 sigaddset (&act
.sa_mask
, SIGIO
);
171 act
.sa_handler
= SIG_IGN
;
173 sigaction (SIGIO
, &act
, NULL
);
175 /* Install a signal handler for SIGURG. */
176 sigemptyset (&act
.sa_mask
);
177 sigaddset (&act
.sa_mask
, SIGURG
);
178 act
.sa_handler
= sighandler
;
179 act
.sa_flags
= SA_RESTART
;
180 sigaction (SIGURG
, &act
, NULL
);
182 /* Install a signal handler for SIGXCPU */
183 sigemptyset (&act
.sa_mask
);
184 sigaddset (&act
.sa_mask
, SIGXCPU
);
185 sigaction (SIGXCPU
, &act
, NULL
);
187 /* Get our current signal mask. */
188 sigprocmask (SIG_SETMASK
, NULL
, &oldset
);
190 /* Mask out SIGUSR1 and SIGUSR2. */
192 sigaddset (&newset
, SIGUSR1
);
193 sigaddset (&newset
, SIGUSR2
);
194 sigprocmask (SIG_SETMASK
, &newset
, NULL
);
196 /* Install a signal handler for SIGUSR1 */
197 sigemptyset (&act
.sa_mask
);
198 sigaddset (&act
.sa_mask
, SIGUSR1
);
199 sigaction (SIGUSR1
, &act
, NULL
);
201 /* Install a signal handler for SIGUSR2 */
202 sigemptyset (&act
.sa_mask
);
203 sigaddset (&act
.sa_mask
, SIGUSR2
);
204 sigaction (SIGUSR2
, &act
, NULL
);
207 * Initialize the thread attribute.
209 if ((pthread_attr_init (&pattr
) != 0) ||
210 (pthread_attr_setdetachstate (&pattr
,
211 PTHREAD_CREATE_JOINABLE
) != 0)) {
212 fprintf (stderr
, "Unable to initialize thread attributes.\n");
217 * Create the sigsuspender thread.
219 if (pthread_create (&suspender_tid
, &pattr
, sigsuspender
, NULL
) != 0) {
220 fprintf (stderr
, "Unable to create thread, errno %d.\n", errno
);
224 pthread_set_name_np (suspender_tid
, "sigsuspender");
228 * Verify that an ignored signal doesn't cause a wakeup.
229 * We don't have a handler installed for SIGIO.
231 send_thread_signal (suspender_tid
, SIGIO
);
233 send_process_signal (SIGIO
);
235 if (sigcounts
[SIGIO
] != 0)
236 fprintf (stderr
, "FAIL: sigsuspend wakes up for ignored signal "
240 * Verify that a signal with a default action of ignore, for
241 * which we have a signal handler installed, will release a
244 send_thread_signal (suspender_tid
, SIGURG
);
246 send_process_signal (SIGURG
);
248 if (sigcounts
[SIGURG
] != 2)
250 "FAIL: sigsuspend doesn't wake up for SIGURG.\n");
253 * Verify that a SIGUSR2 signal will release a sigsuspended
256 send_thread_signal (suspender_tid
, SIGUSR2
);
258 send_process_signal (SIGUSR2
);
260 if (sigcounts
[SIGUSR2
] != 2)
262 "FAIL: sigsuspend doesn't wake up for SIGUSR2.\n");
265 * Verify that a signal, blocked in both the main and
266 * sigsuspender threads, does not cause the signal handler
269 send_thread_signal (suspender_tid
, SIGUSR1
);
271 send_process_signal (SIGUSR1
);
273 if (sigcounts
[SIGUSR1
] != 0)
274 fprintf (stderr
, "FAIL: signal hander called for SIGUSR1.\n");
277 * Verify that we can still kill the process for a signal
278 * not being waited on by sigwait.
280 send_process_signal (SIGPIPE
);
281 fprintf (stderr
, "FAIL: SIGPIPE did not terminate process.\n");
284 * Wait for the thread to finish.
286 pthread_join (suspender_tid
, &exit_status
);