1*50cc4e53Smpi /*	$OpenBSD: sigsuspend.c,v 1.1 2020/09/16 14:04:30 mpi Exp $	*/
2*50cc4e53Smpi /*
3*50cc4e53Smpi  *	Written by Artur Grabowski <art@openbsd.org> 2005, Public domain.
4*50cc4e53Smpi  */
5*50cc4e53Smpi 
6*50cc4e53Smpi #include <stdlib.h>
7*50cc4e53Smpi #include <signal.h>
8*50cc4e53Smpi #include <string.h>
9*50cc4e53Smpi #include <unistd.h>
10*50cc4e53Smpi #include <err.h>
11*50cc4e53Smpi #include <sys/types.h>
12*50cc4e53Smpi #include <sys/wait.h>
13*50cc4e53Smpi 
14*50cc4e53Smpi sig_atomic_t gotusr1;
15*50cc4e53Smpi sig_atomic_t gotusr2;
16*50cc4e53Smpi 
17*50cc4e53Smpi void
usr1handler(int signo)18*50cc4e53Smpi usr1handler(int signo)
19*50cc4e53Smpi {
20*50cc4e53Smpi 	gotusr1 = 1;
21*50cc4e53Smpi }
22*50cc4e53Smpi 
23*50cc4e53Smpi void
usr2handler(int signo)24*50cc4e53Smpi usr2handler(int signo)
25*50cc4e53Smpi {
26*50cc4e53Smpi 	gotusr2 = 1;
27*50cc4e53Smpi }
28*50cc4e53Smpi 
29*50cc4e53Smpi int
main()30*50cc4e53Smpi main()
31*50cc4e53Smpi {
32*50cc4e53Smpi 	sigset_t set, oset;
33*50cc4e53Smpi 	struct sigaction sa;
34*50cc4e53Smpi 	pid_t pid, ppid;
35*50cc4e53Smpi 	int status;
36*50cc4e53Smpi 
37*50cc4e53Smpi 	ppid = getpid();
38*50cc4e53Smpi 
39*50cc4e53Smpi 	memset(&sa, 0, sizeof(sa));
40*50cc4e53Smpi 	sigemptyset(&sa.sa_mask);
41*50cc4e53Smpi 	sa.sa_handler = usr1handler;
42*50cc4e53Smpi 	if (sigaction(SIGUSR1, &sa, NULL))
43*50cc4e53Smpi 		err(1, "sigaction(USR1)");
44*50cc4e53Smpi 
45*50cc4e53Smpi 	sa.sa_handler = usr2handler;
46*50cc4e53Smpi 	if (sigaction(SIGUSR2, &sa, NULL))
47*50cc4e53Smpi 		err(1, "sigaction(USR2)");
48*50cc4e53Smpi 
49*50cc4e53Smpi 	/*
50*50cc4e53Smpi 	 * Set the procmask to mask the early USR1 the child will send us.
51*50cc4e53Smpi 	 */
52*50cc4e53Smpi 	sigemptyset(&set);
53*50cc4e53Smpi 	sigaddset(&set, SIGUSR1);
54*50cc4e53Smpi 	sigaddset(&set, SIGUSR2);
55*50cc4e53Smpi 	if (sigprocmask(SIG_BLOCK, &set, &oset))
56*50cc4e53Smpi 		err(1, "sigprocmask");
57*50cc4e53Smpi 
58*50cc4e53Smpi 	switch((pid = fork())) {
59*50cc4e53Smpi 	case 0:
60*50cc4e53Smpi 		/*
61*50cc4e53Smpi 		 * In the child.
62*50cc4e53Smpi 		 */
63*50cc4e53Smpi 
64*50cc4e53Smpi 		kill(ppid, SIGUSR1);	/* Tell the parent we're ready. */
65*50cc4e53Smpi 
66*50cc4e53Smpi 		sigemptyset(&set);
67*50cc4e53Smpi 		sigaddset(&set, SIGUSR2);
68*50cc4e53Smpi 		sigsuspend(&set);
69*50cc4e53Smpi 
70*50cc4e53Smpi 		/*
71*50cc4e53Smpi 		 * Check that sigsuspend didn't change the signal mask.
72*50cc4e53Smpi 		 */
73*50cc4e53Smpi 		if (sigprocmask(SIG_SETMASK, NULL, &oset))
74*50cc4e53Smpi 			err(1, "sigprocmask");
75*50cc4e53Smpi 		if (!sigismember(&oset, SIGUSR1) ||
76*50cc4e53Smpi 		    !sigismember(&oset, SIGUSR2))
77*50cc4e53Smpi 			errx(1, "sigprocmask is bad");
78*50cc4e53Smpi 
79*50cc4e53Smpi 		/* Check that we got the sigusr1 that we expected. */
80*50cc4e53Smpi 		if (!gotusr1)
81*50cc4e53Smpi 			errx(1, "didn't get usr1");
82*50cc4e53Smpi 		if (gotusr2)
83*50cc4e53Smpi 			errx(1, "got incorrect usr2");
84*50cc4e53Smpi 
85*50cc4e53Smpi 		sigemptyset(&set);
86*50cc4e53Smpi 		sigaddset(&set, SIGUSR1);
87*50cc4e53Smpi 		sigsuspend(&set);
88*50cc4e53Smpi 
89*50cc4e53Smpi 		if (!gotusr2)
90*50cc4e53Smpi 			errx(1, "didn't get usr2");
91*50cc4e53Smpi 
92*50cc4e53Smpi 		_exit(0);
93*50cc4e53Smpi 	case -1:
94*50cc4e53Smpi 		err(1, "fork");
95*50cc4e53Smpi 	default:
96*50cc4e53Smpi 		/*
97*50cc4e53Smpi 		 * In the parent.
98*50cc4e53Smpi 		 * Waiting for the initial USR1 that tells us the child
99*50cc4e53Smpi 		 * is ready.
100*50cc4e53Smpi 		 */
101*50cc4e53Smpi 		while (gotusr1 == 0)
102*50cc4e53Smpi 			sigsuspend(&oset);
103*50cc4e53Smpi 
104*50cc4e53Smpi 		/*
105*50cc4e53Smpi 		 * Check that sigsuspend didn't change the signal mask.
106*50cc4e53Smpi 		 */
107*50cc4e53Smpi 		if (sigprocmask(SIG_SETMASK, NULL, &oset))
108*50cc4e53Smpi 			err(1, "sigprocmask");
109*50cc4e53Smpi 		if (!sigismember(&oset, SIGUSR1) ||
110*50cc4e53Smpi 		    !sigismember(&oset, SIGUSR2))
111*50cc4e53Smpi 			errx(1, "sigprocmask is bad");
112*50cc4e53Smpi 
113*50cc4e53Smpi 		/*
114*50cc4e53Smpi 		 * Deliberately send USR2 first to confuse.
115*50cc4e53Smpi 		 */
116*50cc4e53Smpi 		kill(pid, SIGUSR2);
117*50cc4e53Smpi 		kill(pid, SIGUSR1);
118*50cc4e53Smpi 
119*50cc4e53Smpi 		if (waitpid(pid, &status, 0) != pid)
120*50cc4e53Smpi 			err(1, "waitpid");
121*50cc4e53Smpi 
122*50cc4e53Smpi 		if (WIFEXITED(status))
123*50cc4e53Smpi 			exit(WEXITSTATUS(status));
124*50cc4e53Smpi 		exit(1);
125*50cc4e53Smpi 	}
126*50cc4e53Smpi 	/* NOTREACHED */
127*50cc4e53Smpi }
128*50cc4e53Smpi 
129*50cc4e53Smpi 
130