1 /*
2 * Copyright (c) 2003, Intel Corporation. All rights reserved.
3 * Created by: salwan.searty REMOVE-THIS AT intel DOT com
4 * This file is licensed under the GPL license. For the full content
5 * of this license, see the COPYING file at the top level of this
6 * source tree.
7
8 Assumption: The test assumes that this program is run under normal conditions,
9 and not when the processor and other resources are too stressed.
10
11 This program tries to verify two things:
12
13 1. sigsuspend() replaces the original signal mask (containing SIGUSR1)
14 with the new signal mask (containing SIGUSR2.) This can be accomplished
15 by having the child call sigsuspend, and then have the parent send the
16 child a SIGUSR2 signal. The signal should remain pending while as long
17 as the child is suspended. How do we verify that a signal is pending?
18 Well, if it wasn't for the fact that the child is suspended, we could
19 have easily called the sigpending() from the child process. Because
20 the child is suspended, we have to somehow verify that the signal is
21 pending using only the parent process. This is acheived by having the
22 parent send the child another signal, one that will cause the child to
23 resume execution. If the SIGUSR2 is only delivered after sigsuspend
24 returns, then that means that SIGUSR2 has in fact been pending while
25 the child was suspended, and therefore that proves that sigsuspend()
26 did successfully temporarily replace the original signal mask with one
27 containing only SIGUSR2.
28
29 2. The child process is suspended until the parent process delivers
30 SIGUSR1. We verify this using the following rationale: Via the 3 seconds of
31 sleep at the very start of the parent section of the code, the parent
32 process allowed for enough time for the child process to complete execution
33 and get to the "return 2" line at the very end of the child's code, but the
34 parent didn't allow for any time in which the child may have been suspended.
35 Because the child did receive the signal that the parent later sent before
36 the child finished executing, that had to have meant that the child was
37 suspended for a while during it's execution.
38
39 */
40
41 #include <signal.h>
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <unistd.h>
47 #include "posixtest.h"
48
49 static int SIGUSR1_called = 0;
50 static int SIGUSR2_called = 0;
51
handler(int signo)52 static void handler(int signo)
53 {
54 if (signo == SIGUSR1) {
55 printf("SIGUSR1 called. Inside handler\n");
56 SIGUSR1_called = 1;
57 if (SIGUSR2_called == 1) {
58 exit(1);
59 }
60 } else if (signo == SIGUSR2) {
61 printf("SIGUSR2 called. Inside handler\n");
62 SIGUSR2_called = 1;
63 if (SIGUSR1_called == 1)
64 exit(0);
65 else
66 exit(1);
67 }
68 }
69
main(void)70 int main(void)
71 {
72 pid_t pid;
73 pid = fork();
74
75 if (pid == 0) {
76 /* child */
77
78 sigset_t tempmask, originalmask;
79
80 struct sigaction act;
81
82 act.sa_handler = handler;
83 act.sa_flags = 0;
84 sigemptyset(&act.sa_mask);
85
86 sigemptyset(&tempmask);
87 sigaddset(&tempmask, SIGUSR2);
88
89 if (sigaction(SIGUSR1, &act, 0) == -1) {
90 perror
91 ("Unexpected error while attempting to pre-conditions");
92 return PTS_UNRESOLVED;
93 }
94
95 if (sigaction(SIGUSR2, &act, 0) == -1) {
96 perror
97 ("Unexpected error while attempting to pre-conditions");
98 return PTS_UNRESOLVED;
99 }
100
101 sigemptyset(&originalmask);
102 sigaddset(&originalmask, SIGUSR1);
103 sigprocmask(SIG_SETMASK, &originalmask, NULL);
104
105 printf("suspending child\n");
106 if (sigsuspend(&tempmask) != -1)
107 perror("sigsuspend error");
108
109 printf("returned from suspend\n");
110 sleep(1);
111 return 2;
112
113 } else {
114 int s;
115 int exit_status;
116
117 /* parent */
118 sleep(3);
119
120 printf("parent sending child a SIGUSR2 signal\n");
121 kill(pid, SIGUSR2);
122
123 if (SIGUSR2_called == 1) {
124 printf
125 ("Test FAILED: sigsuspend did not add SIGUSR2 to the temporary mask\n");
126 return PTS_FAIL;
127 }
128 printf("parent sending child a SIGUSR1 signal\n");
129 kill(pid, SIGUSR1);
130
131 if (wait(&s) == -1) {
132 perror("Unexpected error while setting up test "
133 "pre-conditions");
134 return PTS_UNRESOLVED;
135 }
136
137 if (!WIFEXITED(s)) {
138 printf("Test FAILED: Did not exit normally\n");
139 return PTS_FAIL;
140 }
141
142 exit_status = WEXITSTATUS(s);
143
144 printf("Exit status from child is %d\n", exit_status);
145
146 if (exit_status == 1) {
147 printf
148 ("Test UNRESOLVED: Either sigsuspend did not successfully block SIGUSR2, OR sigsuspend returned before handling the signal SIGUSR1\n");
149 return PTS_UNRESOLVED;
150 }
151
152 if (exit_status == 2) {
153 printf
154 ("Test FAILED: sigsuspend did not suspend the child\n");
155 return PTS_FAIL;
156 }
157
158 printf("Test PASSED\n");
159 return PTS_PASS;
160 }
161 }
162