1/*
2* Copyright (c) 2004, Bull S.A..  All rights reserved.
3* Created by: Sebastien Decugis
4
5* This program is free software; you can redistribute it and/or modify it
6* under the terms of version 2 of the GNU General Public License as
7* published by the Free Software Foundation.
8*
9* This program is distributed in the hope that it would be useful, but
10* WITHOUT ANY WARRANTY; without even the implied warranty of
11* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12*
13* You should have received a copy of the GNU General Public License along
14* with this program; if not, write the Free Software Foundation, Inc.,
15* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
16
17* This sample test aims to check the following assertion:
18*
19* The child process is created with no pending signal
20
21* The steps are:
22* -> block SIGUSR1 and SIGUSR2
23* -> send those signals and wait they are pending
24* -> fork
25* -> check the signals are blocked but not pending in the new process.
26
27* The test fails if the signals are pending or if
28* they are not blocked (this counters assertion 2).
29
30*/
31
32/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
33#define _POSIX_C_SOURCE 200112L
34
35#include <pthread.h>
36#include <stdarg.h>
37#include <stdio.h>
38#include <stdlib.h>
39#include <string.h>
40#include <unistd.h>
41
42#include <sys/wait.h>
43#include <errno.h>
44
45#include <signal.h>
46
47#include "../testfrmw/testfrmw.h"
48#include "../testfrmw/testfrmw.c"
49
50#ifndef VERBOSE
51#define VERBOSE 1
52#endif
53
54int main(void)
55{
56	int ret, status;
57	pid_t child, ctl;
58
59	sigset_t mask, pending;
60
61	output_init();
62
63	/* block SIGUSR1 and SIGUSR2 */
64	ret = sigemptyset(&mask);
65
66	if (ret != 0) {
67		UNRESOLVED(errno, "Failed to initialize signal set");
68	}
69
70	ret = sigaddset(&mask, SIGUSR1);
71
72	if (ret != 0) {
73		UNRESOLVED(errno, "Failed to add SIGUSR1 to signal set");
74	}
75
76	ret = sigaddset(&mask, SIGUSR2);
77
78	if (ret != 0) {
79		UNRESOLVED(errno, "Failed to add SIGUSR2 to signal set");
80	}
81
82	ret = sigprocmask(SIG_BLOCK, &mask, NULL);
83
84	if (ret != 0) {
85		UNRESOLVED(errno, "Sigprocmask failed");
86	}
87
88	/* Make the signals pending */
89	ret = kill(getpid(), SIGUSR1);
90
91	if (ret != 0) {
92		UNRESOLVED(errno, "failed to kill with SIGUSR1");
93	}
94
95	ret = kill(getpid(), SIGUSR2);
96
97	if (ret != 0) {
98		UNRESOLVED(errno, "failed to kill with SIGUSR2");
99	}
100
101	do {
102		ret = sigpending(&pending);
103
104		if (ret != 0) {
105			UNRESOLVED(errno,
106				   "failed to examine pending signal set");
107		}
108
109		ret = sigismember(&pending, SIGUSR1);
110
111		if (ret < 0) {
112			UNRESOLVED(errno,
113				   "Unable to check signal USR1 presence");
114		}
115
116		if (ret == 1) {
117			ret = sigismember(&pending, SIGUSR2);
118
119			if (ret < 0) {
120				UNRESOLVED(errno,
121					   "Unable to check signal USR2 presence");
122			}
123		}
124	}
125	while (ret != 1);
126
127#if VERBOSE > 0
128
129	output("SIGUSR1 and SIGUSR2 are pending, we can fork\n");
130
131#endif
132
133	/* Create the child */
134	child = fork();
135
136	if (child == -1) {
137		UNRESOLVED(errno, "Failed to fork");
138	}
139
140	/* child */
141	if (child == 0) {
142		/* Examine the current blocked signal set. USR1 & USR2 shall be present */
143		ret = sigprocmask(0, NULL, &mask);
144
145		if (ret != 0) {
146			UNRESOLVED(errno, "Sigprocmask failed in child");
147		}
148
149		ret = sigismember(&mask, SIGUSR1);
150
151		if (ret < 0) {
152			UNRESOLVED(errno,
153				   "Unable to check signal USR1 presence");
154		}
155
156		if (ret == 0) {
157			FAILED
158			    ("The new process does not mask SIGUSR1 as its parent");
159		}
160
161		ret = sigismember(&mask, SIGUSR2);
162
163		if (ret < 0) {
164			UNRESOLVED(errno,
165				   "Unable to check signal USR2 presence");
166		}
167
168		if (ret == 0) {
169			FAILED
170			    ("The new process does not mask SIGUSR2 as its parent");
171		}
172#if VERBOSE > 0
173		output("SIGUSR1 and SIGUSR2 are blocked in child\n");
174
175#endif
176
177		/* Examine pending signals */
178		ret = sigpending(&pending);
179
180		if (ret != 0) {
181			UNRESOLVED(errno,
182				   "failed to examine pending signal set in child");
183		}
184
185		ret = sigismember(&pending, SIGUSR1);
186
187		if (ret < 0) {
188			UNRESOLVED(errno,
189				   "Unable to check signal USR1 presence");
190		}
191
192		if (ret != 0) {
193			FAILED
194			    ("The new process was created with SIGUSR1 pending");
195		}
196
197		ret = sigismember(&pending, SIGUSR2);
198
199		if (ret < 0) {
200			UNRESOLVED(errno,
201				   "Unable to check signal USR2 presence");
202		}
203
204		if (ret != 0) {
205			FAILED
206			    ("The new process was created with SIGUSR2 pending");
207		}
208#if VERBOSE > 0
209		output("SIGUSR1 and SIGUSR2 are not pending in child\n");
210
211#endif
212
213		/* We're done */
214		exit(PTS_PASS);
215	}
216
217	/* Parent joins the child */
218	ctl = waitpid(child, &status, 0);
219
220	if (ctl != child) {
221		UNRESOLVED(errno, "Waitpid returned the wrong PID");
222	}
223
224	if (!WIFEXITED(status) || (WEXITSTATUS(status) != PTS_PASS)) {
225		FAILED("Child exited abnormally");
226	}
227
228#if VERBOSE > 0
229
230	output("Test passed\n");
231
232#endif
233
234	PASSED;
235}
236