1 /* $OpenBSD: pthread_kill.c,v 1.5 2016/05/10 04:04:34 guenther Exp $ */
2 /* PUBLIC DOMAIN Oct 2002 <marc@snafu.org> */
3 
4 /*
5  * Verify that pthread_kill does the right thing, i.e. the signal
6  * is delivered to the correct thread and proper signal processing
7  * is performed.
8  */
9 
10 #include <signal.h>
11 #include <stdio.h>
12 #include <unistd.h>
13 #include <stdlib.h>
14 
15 #include "test.h"
16 
17 static void
18 act_handler(int signal, siginfo_t *siginfo, void *context)
19 {
20 	struct sigaction sa;
21 	char buf[200];
22 
23 	CHECKe(sigaction(SIGUSR1, NULL, &sa));
24 	ASSERT(sa.sa_handler == SIG_DFL);
25 	ASSERT(siginfo != NULL);
26 	snprintf(buf, sizeof buf,
27 	    "act_handler: signal %d, siginfo %p, context %p\n",
28 	    signal, siginfo, context);
29 	write(STDOUT_FILENO, buf, strlen(buf));
30 }
31 
32 static void *
33 thread(void * arg)
34 {
35 	sigset_t run_mask;
36 	sigset_t suspender_mask;
37 
38 	/* wait for sigusr1 */
39 	SET_NAME(arg);
40 
41 	/* Run with all signals blocked, then suspend for SIGUSR1 */
42 	sigfillset(&run_mask);
43 	CHECKe(sigprocmask(SIG_SETMASK, &run_mask, NULL));
44 	sigfillset(&suspender_mask);
45 	sigdelset(&suspender_mask, SIGUSR1);
46 	for (;;) {
47 		sigsuspend(&suspender_mask);
48 		ASSERT(errno == EINTR);
49 		printf("Thread %s woke up\n", (char*) arg);
50 	}
51 
52 }
53 
54 int
55 main(int argc, char **argv)
56 {
57 	pthread_t thread1;
58 	pthread_t thread2;
59 	struct sigaction act;
60 
61 	act.sa_sigaction = act_handler;
62 	sigemptyset(&act.sa_mask);
63 	act.sa_flags = SA_SIGINFO | SA_RESETHAND | SA_NODEFER;
64 	CHECKe(sigaction(SIGUSR1, &act, NULL));
65 	CHECKr(pthread_create(&thread1, NULL, thread, "T1"));
66 	CHECKr(pthread_create(&thread2, NULL, thread, "T2"));
67 	sleep(1);
68 
69 	/* Signal handler should run once, both threads should awaken */
70 	CHECKe(kill(getpid(), SIGUSR1));
71 	sleep(1);
72 
73 	/* Signal handler run once, only T1 should awaken */
74 	CHECKe(sigaction(SIGUSR1, &act, NULL));
75 	CHECKr(pthread_kill(thread1, SIGUSR1));
76 	sleep(1);
77 
78 	/* Signal handler run once, only T2 should awaken */
79 	CHECKe(sigaction(SIGUSR1, &act, NULL));
80 	CHECKr(pthread_kill(thread2, SIGUSR1));
81 	sleep(1);
82 
83 	SUCCEED;
84 }
85