OSDN Git Service

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