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., 59
15* Temple Place - Suite 330, Boston MA 02111-1307, USA.
16
17
18* This sample test aims to check the following assertion:
19*
20* The child process is created with no pending signal
21
22* The steps are:
23* -> block SIGUSR1 and SIGUSR2
24* -> send those signals and wait they are pending
25* -> fork
26* -> check the signals are blocked but not pending in the new process.
27
28* The test fails if the signals are pending or if
29* they are not blocked (this counters assertion 2).
30
31*/
32
33
34/* We are testing conformance to IEEE Std 1003.1, 2003 Edition */
35#define _POSIX_C_SOURCE 200112L
36
37/********************************************************************************************/
38/****************************** standard includes *****************************************/
39/********************************************************************************************/
40#include <pthread.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #include <unistd.h>
46
47#include <sys/wait.h>
48 #include <errno.h>
49
50#include <signal.h>
51
52/********************************************************************************************/
53/******************************   Test framework   *****************************************/
54/********************************************************************************************/
55#include "testfrmw.h"
56 #include "testfrmw.c"
57/* This header is responsible for defining the following macros:
58 * UNRESOLVED(ret, descr);
59 *    where descr is a description of the error and ret is an int (error code for example)
60 * FAILED(descr);
61 *    where descr is a short text saying why the test has failed.
62 * PASSED();
63 *    No parameter.
64 *
65 * Both three macros shall terminate the calling process.
66 * The testcase shall not terminate in any other maneer.
67 *
68 * The other file defines the functions
69 * void output_init()
70 * void output(char * string, ...)
71 *
72 * Those may be used to output information.
73 */
74
75/********************************************************************************************/
76/********************************** Configuration ******************************************/
77/********************************************************************************************/
78#ifndef VERBOSE
79#define VERBOSE 1
80#endif
81
82/********************************************************************************************/
83/***********************************    Test case   *****************************************/
84/********************************************************************************************/
85
86/* The main test function. */
87int main( int argc, char * argv[] )
88{
89	int ret, status;
90	pid_t child, ctl;
91
92	sigset_t mask, pending;
93
94	/* Initialize output */
95	output_init();
96
97	/* block SIGUSR1 and SIGUSR2 */
98	ret = sigemptyset( &mask );
99
100	if ( ret != 0 )
101	{
102		UNRESOLVED( errno, "Failed to initialize signal set" );
103	}
104
105	ret = sigaddset( &mask, SIGUSR1 );
106
107	if ( ret != 0 )
108	{
109		UNRESOLVED( errno, "Failed to add SIGUSR1 to signal set" );
110	}
111
112	ret = sigaddset( &mask, SIGUSR2 );
113
114	if ( ret != 0 )
115	{
116		UNRESOLVED( errno, "Failed to add SIGUSR2 to signal set" );
117	}
118
119	ret = sigprocmask( SIG_BLOCK, &mask, NULL );
120
121	if ( ret != 0 )
122	{
123		UNRESOLVED( errno, "Sigprocmask failed" );
124	}
125
126	/* Make the signals pending */
127	ret = kill( getpid(), SIGUSR1 );
128
129	if ( ret != 0 )
130	{
131		UNRESOLVED( errno, "failed to kill with SIGUSR1" );
132	}
133
134	ret = kill( getpid(), SIGUSR2 );
135
136	if ( ret != 0 )
137	{
138		UNRESOLVED( errno, "failed to kill with SIGUSR2" );
139	}
140
141	do
142	{
143		ret = sigpending( &pending );
144
145		if ( ret != 0 )
146		{
147			UNRESOLVED( errno, "failed to examine pending signal set" );
148		}
149
150		ret = sigismember( &pending, SIGUSR1 );
151
152		if ( ret < 0 )
153		{
154			UNRESOLVED( errno, "Unable to check signal USR1 presence" );
155		}
156
157		if ( ret == 1 )
158		{
159			ret = sigismember( &pending, SIGUSR2 );
160
161			if ( ret < 0 )
162			{
163				UNRESOLVED( errno, "Unable to check signal USR2 presence" );
164			}
165		}
166	}
167	while ( ret != 1 );
168
169#if VERBOSE > 0
170
171	output( "SIGUSR1 and SIGUSR2 are pending, we can fork\n" );
172
173#endif
174
175	/* Create the child */
176	child = fork();
177
178	if ( child == ( pid_t ) - 1 )
179	{
180		UNRESOLVED( errno, "Failed to fork" );
181	}
182
183	/* child */
184	if ( child == ( pid_t ) 0 )
185	{
186		/* Examine the current blocked signal set. USR1 & USR2 shall be present */
187		ret = sigprocmask( 0, NULL, &mask );
188
189		if ( ret != 0 )
190		{
191			UNRESOLVED( errno, "Sigprocmask failed in child" );
192		}
193
194		ret = sigismember( &mask, SIGUSR1 );
195
196		if ( ret < 0 )
197		{
198			UNRESOLVED( errno, "Unable to check signal USR1 presence" );
199		}
200
201		if ( ret == 0 )
202		{
203			FAILED( "The new process does not mask SIGUSR1 as its parent" );
204		}
205
206		ret = sigismember( &mask, SIGUSR2 );
207
208		if ( ret < 0 )
209		{
210			UNRESOLVED( errno, "Unable to check signal USR2 presence" );
211		}
212
213		if ( ret == 0 )
214		{
215			FAILED( "The new process does not mask SIGUSR2 as its parent" );
216		}
217
218#if VERBOSE > 0
219		output( "SIGUSR1 and SIGUSR2 are blocked in child\n" );
220
221#endif
222
223		/* Examine pending signals */
224		ret = sigpending( &pending );
225
226		if ( ret != 0 )
227		{
228			UNRESOLVED( errno, "failed to examine pending signal set in child" );
229		}
230
231		ret = sigismember( &pending, SIGUSR1 );
232
233		if ( ret < 0 )
234		{
235			UNRESOLVED( errno, "Unable to check signal USR1 presence" );
236		}
237
238		if ( ret != 0 )
239		{
240			FAILED( "The new process was created with SIGUSR1 pending" );
241		}
242
243		ret = sigismember( &pending, SIGUSR2 );
244
245		if ( ret < 0 )
246		{
247			UNRESOLVED( errno, "Unable to check signal USR2 presence" );
248		}
249
250		if ( ret != 0 )
251		{
252			FAILED( "The new process was created with SIGUSR2 pending" );
253		}
254
255#if VERBOSE > 0
256		output( "SIGUSR1 and SIGUSR2 are not pending in child\n" );
257
258#endif
259
260		/* We're done */
261		exit( PTS_PASS );
262	}
263
264	/* Parent joins the child */
265	ctl = waitpid( child, &status, 0 );
266
267	if ( ctl != child )
268	{
269		UNRESOLVED( errno, "Waitpid returned the wrong PID" );
270	}
271
272	if ( ( !WIFEXITED( status ) ) || ( WEXITSTATUS( status ) != PTS_PASS ) )
273	{
274		FAILED( "Child exited abnormally" );
275	}
276
277	/* Test passed */
278#if VERBOSE > 0
279
280	output( "Test passed\n" );
281
282#endif
283
284	PASSED;
285}
286
287
288