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
17static void
18act_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
32static void *
33thread(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
54int
55main(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