blob: 693172986d55c08bccb01cc0fdad1a689e9ba192 [file] [log] [blame]
plars865695b2001-08-27 22:15:12 +00001/*
2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11 *
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
18 *
19 * You should have received a copy of the GNU General Public License along
Wanlong Gaofed96412012-10-24 10:10:29 +080020 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
plars865695b2001-08-27 22:15:12 +000022 *
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
25 *
26 * http://www.sgi.com
27 *
28 * For further information regarding this notice, see:
29 *
30 * http://oss.sgi.com/projects/GenInfo/NoticeExplan/
31 *
32 */
vapierb8a44eb2009-08-28 14:10:16 +000033/* $Id: sigrelse01.c,v 1.14 2009/08/28 14:10:16 vapier Exp $ */
plars865695b2001-08-27 22:15:12 +000034/*****************************************************************************
35 * OS Test - Silicon Graphics, Inc. Eagan, Minnesota
subrata_modak4bb656a2009-02-26 12:02:09 +000036 *
plars865695b2001-08-27 22:15:12 +000037 * TEST IDENTIFIER : sigrelse01 Releasing held signals.
subrata_modak4bb656a2009-02-26 12:02:09 +000038 *
plars865695b2001-08-27 22:15:12 +000039 * PARENT DOCUMENT : sgrtds01 sigrelse system call
subrata_modak4bb656a2009-02-26 12:02:09 +000040 *
plars865695b2001-08-27 22:15:12 +000041 * AUTHOR : Bob Clark
42 * : Rewrote 12/92 by Richard Logan
subrata_modak4bb656a2009-02-26 12:02:09 +000043 *
plars865695b2001-08-27 22:15:12 +000044 * CO-PILOT : Dave Baumgartner
subrata_modak4bb656a2009-02-26 12:02:09 +000045 *
plars865695b2001-08-27 22:15:12 +000046 * DATE STARTED : 10/08/86
subrata_modak4bb656a2009-02-26 12:02:09 +000047 *
plars865695b2001-08-27 22:15:12 +000048 * TEST ITEMS
subrata_modak4bb656a2009-02-26 12:02:09 +000049 *
plars865695b2001-08-27 22:15:12 +000050 * 1. sigrelse turns on the receipt of signals held by sighold.
subrata_modak4bb656a2009-02-26 12:02:09 +000051 *
plars865695b2001-08-27 22:15:12 +000052 * SPECIAL PROCEDURAL REQUIRMENTS
53 * None
subrata_modak4bb656a2009-02-26 12:02:09 +000054 *
plars865695b2001-08-27 22:15:12 +000055 * DETAILED DESCRIPTION
56 * set up pipe for parent/child communications
57 * fork off a child process
subrata_modak4bb656a2009-02-26 12:02:09 +000058 *
plars865695b2001-08-27 22:15:12 +000059 * parent():
60 * set up for unexpected signals
61 * wait for child to send ready message over pipe
62 * send all catchable signals to child process
63 * send alarm signal to speed up timeout
64 * wait for child to terminate and check exit value
subrata_modak4bb656a2009-02-26 12:02:09 +000065 *
plars865695b2001-08-27 22:15:12 +000066 * if exit value is EXIT_OK
67 * get message from pipe (contains array of signal counters)
68 * loop through array of signal counters and record any
69 * signals which were not caught once.
70 * record PASS or FAIL depending on what was found in the array.
subrata_modak4bb656a2009-02-26 12:02:09 +000071 *
plars865695b2001-08-27 22:15:12 +000072 * else if exit is SIG_CAUGHT then BROK (signal caught
73 * before released)
74 * else if exit is WRITE_BROK then BROK (write() to pipe failed)
75 * else if exit is HANDLE_ERR then BROK (error in child's
76 * signal handler)
77 * else unexpected exit value - BROK
subrata_modak4bb656a2009-02-26 12:02:09 +000078 *
plars865695b2001-08-27 22:15:12 +000079 * child():
80 * phase 1:
81 * set up to catch all catchable signals (exit SIG_CAUGHT
82 * if caught)
83 * hold each signal with sighold()
84 * send parent ready message if setup went ok.
85 * wait for signals to arrive - timeout if they don't
subrata_modak4bb656a2009-02-26 12:02:09 +000086 *
plars865695b2001-08-27 22:15:12 +000087 * phase 2:
88 * release each signal and wait a second for the handler to
89 * catch it.
subrata_modak4bb656a2009-02-26 12:02:09 +000090 * (the handler will record each signal it catches in an array
plars865695b2001-08-27 22:15:12 +000091 * and exit HANDLE_ERR if an error occurs)
subrata_modak4bb656a2009-02-26 12:02:09 +000092 *
plars865695b2001-08-27 22:15:12 +000093 * send array of counters back to parent for processing.
94 * exit EXIT_OK
95 * NOTES
96 * since child is executing system calls under test, no
97 * system call times are printed.
subrata_modak4bb656a2009-02-26 12:02:09 +000098 *
plars865695b2001-08-27 22:15:12 +000099***************************************************************************/
Garrett Cooper2c282152010-12-16 00:55:50 -0800100
plars865695b2001-08-27 22:15:12 +0000101#include <sys/types.h>
102#include <sys/wait.h>
Garrett Cooper09d00362011-01-28 02:02:33 -0800103#include <errno.h>
104#include <fcntl.h>
105#include <signal.h>
106#include <stdlib.h>
107#include <string.h>
108#include <time.h>
109#include <unistd.h>
plars865695b2001-08-27 22:15:12 +0000110#include "test.h"
Garrett Cooper09d00362011-01-28 02:02:33 -0800111#include "safe_macros.h"
plars865695b2001-08-27 22:15:12 +0000112
113#ifdef __linux__
114/* glibc2.2 definition needs -D_XOPEN_SOURCE, which breaks other things. */
subrata_modak56207ce2009-03-23 13:35:39 +0000115extern int sighold(int __sig);
116extern int sigrelse(int __sig);
plars865695b2001-08-27 22:15:12 +0000117#endif
118
robbiew90e8baf2003-09-25 15:44:20 +0000119/* Needed for NPTL */
robbiew94350592003-04-29 17:05:41 +0000120#define SIGCANCEL 32
121#define SIGTIMER 33
robbiew94350592003-04-29 17:05:41 +0000122
Mike Frysingerc57fba52014-04-09 18:56:30 -0400123void setup(void);
124void cleanup(void);
125static void parent(void);
126static void child(void);
Mike Frysingere61ddba2014-04-09 23:24:32 -0400127static void timeout(int sig);
Mike Frysingerc57fba52014-04-09 18:56:30 -0400128static int setup_sigs(void);
129static void handler(int sig);
130static void wait_a_while(void);
131static char *read_pipe(int fd);
132static int write_pipe(int fd, char *msg);
133static int set_timeout(void);
134static void clear_timeout(void);
135static void getout(void);
plars865695b2001-08-27 22:15:12 +0000136int choose_sig(int sig);
137
138#define TRUE 1
139#define FALSE 0
140
141#ifndef DEBUG
142#define DEBUG 0
143#endif
144
subrata_modak56207ce2009-03-23 13:35:39 +0000145#define CHILD_EXIT(VAL) ((VAL >> 8) & 0377) /* exit value of child process */
plars865695b2001-08-27 22:15:12 +0000146#define CHILD_SIG(VAL) (VAL & 0377) /* signal value of child proc */
147
148#define MAXMESG 512 /* the size of the message string */
149
150#define READY "ready" /* signal to parent that child is set up */
151
152#define TIMEOUT 30 /* time (sec) used in the alarm calls */
153
154/* child exit values */
155#define EXIT_OK 0
156#define SIG_CAUGHT 8
157#define WRITE_BROK 16
158#define HANDLE_ERR 32
159
subrata_modak56207ce2009-03-23 13:35:39 +0000160int TST_TOTAL = 1; /* number of test items */
plars865695b2001-08-27 22:15:12 +0000161
162char *TCID = "sigrelse01"; /* test case identifier */
163static char mesg[MAXMESG]; /* message buffer for tst_res */
164static int pid; /* process id of child */
subrata_modak56207ce2009-03-23 13:35:39 +0000165static int pipe_fd[2]; /* file descriptors for pipe parent read */
plars865695b2001-08-27 22:15:12 +0000166static int pipe_fd2[2]; /* file descriptors for pipe child read */
167static int phase; /* flag for phase1 or phase2 of */
168 /* signal handler */
169static int sig_caught; /* flag TRUE if signal caught */
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800170 /* (see wait_a_while ()) */
plars865695b2001-08-27 22:15:12 +0000171
172/* ensure that NUMSIGS is defined. */
173#ifndef NUMSIGS
174#define NUMSIGS NSIG
175#endif
176
177/* array of counters for signals caught by handler() */
178static int sig_array[NUMSIGS];
179
plars865695b2001-08-27 22:15:12 +0000180/***********************************************************************
181 * M A I N
182 ***********************************************************************/
subrata_modak56207ce2009-03-23 13:35:39 +0000183int main(int argc, char **argv)
plars865695b2001-08-27 22:15:12 +0000184{
Cyril Hrubis89af32a2012-10-24 16:39:11 +0200185 int lc;
Cyril Hrubis0b9589f2014-05-27 17:40:33 +0200186 const char *msg;
plars865695b2001-08-27 22:15:12 +0000187
subrata_modak56207ce2009-03-23 13:35:39 +0000188 /* gcc -Wall complains about sig_caught not being ref'd because of the
189 external declarations. */
190 sig_caught = FALSE;
plars865695b2001-08-27 22:15:12 +0000191
subrata_modak56207ce2009-03-23 13:35:39 +0000192 /*
193 * parse standard options
194 */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800195 if ((msg = parse_opts(argc, argv, NULL, NULL)) != NULL) {
subrata_modak56207ce2009-03-23 13:35:39 +0000196 tst_brkm(TBROK, NULL, "OPTION PARSING ERROR - %s", msg);
Garrett Cooper2c282152010-12-16 00:55:50 -0800197
subrata_modak56207ce2009-03-23 13:35:39 +0000198 }
robbiewd34d5812005-07-11 22:28:09 +0000199#ifdef UCLINUX
subrata_modak56207ce2009-03-23 13:35:39 +0000200 maybe_run_child(&child, "dd", &pipe_fd[1], &pipe_fd2[0]);
robbiewd34d5812005-07-11 22:28:09 +0000201#endif
202
subrata_modak56207ce2009-03-23 13:35:39 +0000203 /*
204 * perform global setup for test
205 */
206 setup();
plars865695b2001-08-27 22:15:12 +0000207
subrata_modak56207ce2009-03-23 13:35:39 +0000208 for (lc = 0; TEST_LOOPING(lc); lc++) {
plars865695b2001-08-27 22:15:12 +0000209
Caspar Zhangd59a6592013-03-07 14:59:12 +0800210 tst_count = 0;
subrata_modak56207ce2009-03-23 13:35:39 +0000211
212 /*
213 * fork off a child process
214 */
215 if ((pid = FORK_OR_VFORK()) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800216 tst_brkm(TBROK | TERRNO, cleanup, "fork() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000217
218 } else if (pid > 0) {
219 parent();
220
221 } else {
222#ifdef UCLINUX
223 if (self_exec(argv[0], "dd", pipe_fd[1], pipe_fd2[0]) <
224 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800225 tst_brkm(TBROK | TERRNO, cleanup,
226 "self_exec() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000227 }
228#else
229 child();
230#endif
231 }
232
Garrett Cooper2c282152010-12-16 00:55:50 -0800233 }
plars865695b2001-08-27 22:15:12 +0000234
subrata_modak56207ce2009-03-23 13:35:39 +0000235 cleanup();
Garrett Cooper1e6f5a62010-12-19 09:58:10 -0800236 tst_exit();
plars865695b2001-08-27 22:15:12 +0000237
subrata_modak56207ce2009-03-23 13:35:39 +0000238} /* end main */
plars865695b2001-08-27 22:15:12 +0000239
240/****************************************************************************
241 * parent() : wait for "ready" from child, send signals to child, wait for
242 * child to exit and report what happened.
243 ***************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400244static void parent(void)
plars865695b2001-08-27 22:15:12 +0000245{
subrata_modak56207ce2009-03-23 13:35:39 +0000246 int term_stat; /* child return status */
247 int rv; /* function return value */
248 int sig; /* current signal number */
249 char *str; /* string returned from read_pipe() */
250 int *array; /* pointer to sig_array returned from child */
251 int fail = FALSE; /* flag indicating test item failure */
252 char big_mesg[MAXMESG * 6]; /* storage for big failure message */
253 int caught_sigs;
plars865695b2001-08-27 22:15:12 +0000254
subrata_modak56207ce2009-03-23 13:35:39 +0000255 /* wait for "ready" message from child */
plars865695b2001-08-27 22:15:12 +0000256 if ((str = read_pipe(pipe_fd[0])) == NULL) {
subrata_modak56207ce2009-03-23 13:35:39 +0000257 /* read_pipe() failed. */
vapierb8a44eb2009-08-28 14:10:16 +0000258 tst_brkm(TBROK, getout, "%s", mesg);
plars865695b2001-08-27 22:15:12 +0000259 }
260
subrata_modak56207ce2009-03-23 13:35:39 +0000261 if (strcmp(str, READY) != 0) {
262 /* child setup did not go well */
vapierb8a44eb2009-08-28 14:10:16 +0000263 tst_brkm(TBROK, getout, "%s", str);
subrata_modak56207ce2009-03-23 13:35:39 +0000264 }
plars865695b2001-08-27 22:15:12 +0000265
subrata_modak56207ce2009-03-23 13:35:39 +0000266 /*
267 * send signals to child and see if it holds them
268 */
plars865695b2001-08-27 22:15:12 +0000269
subrata_modak56207ce2009-03-23 13:35:39 +0000270 for (sig = 1; sig < NUMSIGS; sig++) {
271 if (choose_sig(sig)) {
272 if (kill(pid, sig) < 0) {
273 if (errno == ESRCH) {
vapierb8a44eb2009-08-28 14:10:16 +0000274 if (kill(pid, SIGTERM) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800275 tst_brkm(TBROK | TERRNO, getout,
276 "kill(%d, %d) and kill(%d, SIGTERM) failed",
277 pid, sig, pid);
vapierb8a44eb2009-08-28 14:10:16 +0000278 else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800279 tst_brkm(TBROK | TERRNO, getout,
280 "kill(%d, %d) failed, but kill(%d, SIGTERM) worked",
281 pid, sig, pid);
vapierb8a44eb2009-08-28 14:10:16 +0000282 } else
Wanlong Gao354ebb42012-12-07 10:10:04 +0800283 tst_brkm(TBROK | TERRNO, getout,
284 "kill(%d, %d) failed", pid,
285 sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000286 }
287 }
288 }
plars865695b2001-08-27 22:15:12 +0000289
subrata_modak56207ce2009-03-23 13:35:39 +0000290 if (write_pipe(pipe_fd2[1], READY) < 0) {
Wanlong Gao354ebb42012-12-07 10:10:04 +0800291 tst_brkm(TBROK | TERRNO, getout,
292 "Unable to tell child to go, write to pipe failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000293 }
294
295 /*
296 * child is now releasing signals, wait and check exit value
297 */
vapierb8a44eb2009-08-28 14:10:16 +0000298 if (wait(&term_stat) < 0)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800299 tst_brkm(TBROK | TERRNO, getout, "wait() failed");
subrata_modak56207ce2009-03-23 13:35:39 +0000300
301 /* check child's signal exit value */
vapierb8a44eb2009-08-28 14:10:16 +0000302 if ((sig = CHILD_SIG(term_stat)) != 0)
subrata_modak56207ce2009-03-23 13:35:39 +0000303 /* the child was zapped by a signal */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800304 tst_brkm(TBROK, cleanup, "Unexpected signal %d killed child",
305 sig);
subrata_modak56207ce2009-03-23 13:35:39 +0000306
307 /* get child exit value */
308
309 rv = CHILD_EXIT(term_stat);
310
311 switch (rv) {
312 case EXIT_OK:
313 /* sig_array sent back on pipe, check it out */
314 if ((array = (int *)read_pipe(pipe_fd[0])) == NULL) {
315 /* read_pipe() failed. */
vapierb8a44eb2009-08-28 14:10:16 +0000316 tst_resm(TBROK, "%s", mesg);
subrata_modak56207ce2009-03-23 13:35:39 +0000317 break;
318 }
319#if DEBUG > 1
320 for (sig = 1; sig < NUMSIGS; sig++) {
321 printf("array[%d] = %d\n", sig, array[sig]);
322 }
323#endif
324 caught_sigs = 0;
325 for (sig = 1; sig < NUMSIGS; sig++) {
326 if (choose_sig(sig)) {
327 if (array[sig] != 1) {
328 /* sig was not caught or caught too many times */
329 (void)sprintf(mesg,
330 "\tsignal %d caught %d times (expected 1).\n",
331 sig, array[sig]);
332 (void)strcat(big_mesg, mesg);
333 fail = TRUE;
334 } else {
335 caught_sigs++;
336 }
337 }
338 } /* endfor */
339
340 if (fail == TRUE)
vapierb8a44eb2009-08-28 14:10:16 +0000341 tst_resm(TFAIL, "%s", big_mesg);
subrata_modak56207ce2009-03-23 13:35:39 +0000342 else
343 tst_resm(TPASS,
344 "sigrelse() released all %d signals under test.",
345 caught_sigs);
346 break;
347
348 case TBROK:
349 /* get BROK message from pipe */
350 if ((str = read_pipe(pipe_fd[0])) == NULL) {
351 /* read_pipe() failed. */
vapierb8a44eb2009-08-28 14:10:16 +0000352 tst_resm(TBROK, "%s", mesg);
subrata_modak56207ce2009-03-23 13:35:39 +0000353 break;
354 }
355
356 /* call tst_res: str contains the message */
vapierb8a44eb2009-08-28 14:10:16 +0000357 tst_resm(TBROK, "%s", str);
subrata_modak56207ce2009-03-23 13:35:39 +0000358 break;
359 case SIG_CAUGHT:
360 /* a signal was caught before it was released */
361 tst_resm(TBROK, "A signal was caught before being released.");
362 break;
363 case WRITE_BROK:
364 /* the write() call failed in child's write_pipe */
365 tst_resm(TBROK, "write() pipe failed for child.");
366 break;
367 case HANDLE_ERR:
368 /* more than one signal tried to be handled at the same time */
369 tst_resm(TBROK, "Error occured in signal handler.");
370 break;
371 default:
vapierb8a44eb2009-08-28 14:10:16 +0000372 tst_resm(TBROK, "Unexpected exit code %d from child", rv);
subrata_modak56207ce2009-03-23 13:35:39 +0000373 break;
374 }
375
subrata_modak56207ce2009-03-23 13:35:39 +0000376} /* end of parent */
plars865695b2001-08-27 22:15:12 +0000377
378/****************************************************************************
379 * child() : hold signals, notify parent and wait for parent to send signals.
380 * If none were caught (sighold worked), release the signals one at a time
381 * and wait for them to be caught. Send results back to parent
382 * for processing.
383 ***************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400384static void child(void)
plars865695b2001-08-27 22:15:12 +0000385{
subrata_modak56207ce2009-03-23 13:35:39 +0000386 int rv; /* return value from sighold() and sigrelse() */
387 int sig; /* signal value */
388 int exit_val; /* exit value to send to parent */
389 char note[MAXMESG]; /* message buffer for pipe */
390 char *str;
plars865695b2001-08-27 22:15:12 +0000391
subrata_modak56207ce2009-03-23 13:35:39 +0000392 phase = 1; /* tell handler that we do not want to catch signals */
plars865695b2001-08-27 22:15:12 +0000393
subrata_modak56207ce2009-03-23 13:35:39 +0000394 /* set note to READY and if an error occurs, overwrite it */
395 (void)strcpy(note, READY);
plars865695b2001-08-27 22:15:12 +0000396
subrata_modak56207ce2009-03-23 13:35:39 +0000397 /* set alarm in case something hangs */
398 if (set_timeout() < 0) {
399 /* an error occured - put mesg in note and send it back to parent */
400 (void)strcpy(note, mesg);
plars865695b2001-08-27 22:15:12 +0000401
subrata_modak56207ce2009-03-23 13:35:39 +0000402 } else if (setup_sigs() < 0) {
403 /* an error occured - put mesg in note and send it back to parent */
404 (void)strcpy(note, mesg);
plars865695b2001-08-27 22:15:12 +0000405
subrata_modak56207ce2009-03-23 13:35:39 +0000406 } else {
407 /* all set up to catch signals, now hold them */
408
409 for (sig = 1; sig < NUMSIGS; sig++) {
410 if (choose_sig(sig)) {
411 if ((rv = sighold(sig)) != 0) {
412 /* THEY say sighold ALWAYS returns 0 */
413 (void)sprintf(note,
414 "sighold did not return 0. rv:%d",
415 rv);
416 break;
417 }
418 }
419 }
420
421 }
422
423 /*
424 * send note to parent (if not READY, parent will BROK) and
425 * wait for parent to send signals. The timeout clock is set so
426 * that we will not wait forever - if sighold() did its job, we
427 * will not receive the signals. If sighold() blew it we will
428 * catch a signal and the interrupt handler will exit with a
429 * value of SIG_CAUGHT.
430 */
431 if (write_pipe(pipe_fd[1], note) < 0) {
432 /*
433 * write_pipe() failed. Set exit value to WRITE_BROK to let
434 * parent know what happened
435 */
436 clear_timeout();
437 exit(WRITE_BROK);
438 }
439
440 /*
441 * if we get to this point, all signals have been held and the
442 * timer has expired. Now what we want to do is release each
443 * signal and see if we catch it. If we catch all signals,
444 * sigrelse passed, else it failed.
445 */
446
447 phase = 2; /* let handler know we are now expecting signals */
448
449#if DEBUG > 0
450 printf("child: PHASE II\n");
451#endif
452
453 /* assume success and overwrite exit_val if an error occurs */
454 exit_val = EXIT_OK;
455
456#if DEBUG > 0
457 printf("child: pid=%d waiting for parent's ready...\n", getpid());
458#endif
459
460 /*
461 * wait for parent to tell us that sigals were all sent
462 */
463
464 /* wait for "ready" message from parent */
465 if ((str = read_pipe(pipe_fd2[0])) == NULL) {
466 /* read_pipe() failed. */
467 printf(" child: read_pipe failed\n");
468 exit(TBROK);
469 }
470
471 if (strcmp(str, READY) != 0) {
472 /* parent/pipe problem */
473 printf("child: didn't proper ready message\n");
474 exit(TBROK);
475 }
plars865695b2001-08-27 22:15:12 +0000476
477 for (sig = 1; sig < NUMSIGS; sig++) {
subrata_modak56207ce2009-03-23 13:35:39 +0000478 if (choose_sig(sig)) {
plars865695b2001-08-27 22:15:12 +0000479
subrata_modak56207ce2009-03-23 13:35:39 +0000480 /* all set up, release and catch a signal */
plars865695b2001-08-27 22:15:12 +0000481
subrata_modak56207ce2009-03-23 13:35:39 +0000482 sig_caught = FALSE; /* handler sets it to TRUE when caught */
plars865695b2001-08-27 22:15:12 +0000483#if DEBUG > 1
subrata_modak56207ce2009-03-23 13:35:39 +0000484 printf("child: releasing sig %d...\n", sig);
plars865695b2001-08-27 22:15:12 +0000485#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000486 if ((rv = sigrelse(sig)) != 0) {
487 /* THEY say sigrelse ALWAYS returns 0 */
488 (void)sprintf(note,
489 "sigrelse did not return 0. rv:%d",
490 rv);
491 exit_val = TBROK;
492 break;
493 }
plars865695b2001-08-27 22:15:12 +0000494
subrata_modak56207ce2009-03-23 13:35:39 +0000495 /* give signal handler some time to process signal */
Wanlong Gao354ebb42012-12-07 10:10:04 +0800496 wait_a_while();
subrata_modak56207ce2009-03-23 13:35:39 +0000497 }
498
499 } /* endfor */
500
501 /*
502 * If we are error free so far...
503 * check the sig_array array for one occurence of
504 * each of the catchable signals. If this is true,
505 * then PASS, otherwise FAIL.
506 */
507
508 if (exit_val == EXIT_OK) {
509 (void)memcpy(note, (char *)sig_array, sizeof(sig_array));
plars865695b2001-08-27 22:15:12 +0000510 }
511
subrata_modak56207ce2009-03-23 13:35:39 +0000512 /* send note to parent and exit */
513 if (write_pipe(pipe_fd[1], note) < 0) {
514 /*
515 * write_pipe() failed. Set exit value to WRITE_BROK to let
516 * parent know what happened
517 */
518 exit(WRITE_BROK);
519 }
plars865695b2001-08-27 22:15:12 +0000520
subrata_modak56207ce2009-03-23 13:35:39 +0000521 exit(exit_val);
plars865695b2001-08-27 22:15:12 +0000522
subrata_modak56207ce2009-03-23 13:35:39 +0000523} /* end of child */
Garrett Cooper2c282152010-12-16 00:55:50 -0800524
plars865695b2001-08-27 22:15:12 +0000525/*****************************************************************************
526 * setup_sigs() : set child up to catch all signals. If there is
527 * trouble, write message in mesg and return -1, else return 0.
528 * The signal handler has two functions depending on which phase
529 * of the test we are in. The first section is executed after the
530 * signals have been held (should not ever be used). The second
531 * section is executed after the signals have been released (should
532 * be executed for each signal).
533 ****************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400534static int setup_sigs(void)
plars865695b2001-08-27 22:15:12 +0000535{
subrata_modak56207ce2009-03-23 13:35:39 +0000536 int sig;
plars865695b2001-08-27 22:15:12 +0000537
subrata_modak56207ce2009-03-23 13:35:39 +0000538 /* set up signal handler routine */
539 for (sig = 1; sig < NUMSIGS; sig++) {
540 if (choose_sig(sig)) {
541 if (signal(sig, handler) == SIG_ERR) {
542 /* set up mesg to send back to parent */
543 (void)sprintf(mesg,
544 "signal() failed for signal %d. error:%d %s.",
545 sig, errno, strerror(errno));
546 return (-1);
547 }
548 }
plars865695b2001-08-27 22:15:12 +0000549 }
subrata_modak56207ce2009-03-23 13:35:39 +0000550 return 0;
plars865695b2001-08-27 22:15:12 +0000551
subrata_modak56207ce2009-03-23 13:35:39 +0000552} /* end of setup_sigs */
subrata_modakbdbaec52009-02-26 12:14:51 +0000553
plars865695b2001-08-27 22:15:12 +0000554/*****************************************************************************
555 * handler() : child's interrupt handler for all signals. The phase variable
556 * is set in the child process indicating what action is to be taken.
557 * The phase 1 section will be run if the child process catches a signal
558 * after the signal has been held resulting in a test item BROK.
559 * The parent detects this situation by a child exit value of SIG_CAUGHT.
560 * The phase 2 section will be run if the child process catches a
561 * signal after the signal has been released. All signals must be
562 * caught in order for a PASS.
563 ****************************************************************************/
Garrett Cooper09d00362011-01-28 02:02:33 -0800564static void handler(int sig)
plars865695b2001-08-27 22:15:12 +0000565{
subrata_modak56207ce2009-03-23 13:35:39 +0000566 static int s = 0; /* semaphore so that we don't handle 2 */
567 /* sigs at once */
plars865695b2001-08-27 22:15:12 +0000568#if DEBUG > 1
subrata_modak56207ce2009-03-23 13:35:39 +0000569 printf("child: handler phase%d: caught signal %d.\n", phase, sig);
plars865695b2001-08-27 22:15:12 +0000570#endif
571
subrata_modak56207ce2009-03-23 13:35:39 +0000572 if (phase == 1) {
573 /* exit the child process with a value of -1 */
574 exit(SIG_CAUGHT);
plars865695b2001-08-27 22:15:12 +0000575
subrata_modak56207ce2009-03-23 13:35:39 +0000576 } else {
577 /* phase 2 (error if s gets incremented twice) */
578 ++s;
plars865695b2001-08-27 22:15:12 +0000579
subrata_modak56207ce2009-03-23 13:35:39 +0000580 if (s > 1) {
581 exit(HANDLE_ERR);
582 }
583
584 /* increment the array element for this signal */
585 ++sig_array[sig];
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800586 sig_caught = TRUE; /* flag for wait_a_while () */
subrata_modak56207ce2009-03-23 13:35:39 +0000587 --s;
plars865695b2001-08-27 22:15:12 +0000588 }
589
subrata_modak56207ce2009-03-23 13:35:39 +0000590 return;
plars865695b2001-08-27 22:15:12 +0000591
subrata_modak56207ce2009-03-23 13:35:39 +0000592} /* end of handler */
plars865695b2001-08-27 22:15:12 +0000593
594/*****************************************************************************
595 * read_pipe() : read data from pipe and return in buf. If an error occurs
596 * put message in mesg and return NULL. Note: this routine sets a
597 * timeout signal in case the pipe is blocked.
598 ****************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400599static char *read_pipe(int fd)
plars865695b2001-08-27 22:15:12 +0000600{
subrata_modak56207ce2009-03-23 13:35:39 +0000601 static char buf[MAXMESG]; /* buffer for pipe read */
602 int ret;
plars865695b2001-08-27 22:15:12 +0000603
604#if DEBUG > 0
subrata_modak56207ce2009-03-23 13:35:39 +0000605 printf("read_pipe: pid=%d waiting...\n", getpid());
subrata_modak4bb656a2009-02-26 12:02:09 +0000606#endif
plars865695b2001-08-27 22:15:12 +0000607
subrata_modak56207ce2009-03-23 13:35:39 +0000608 /* set timeout alarm in case the pipe is blocked */
609 if (set_timeout() < 0) {
610 /* an error occured, message in mesg */
611 return NULL;
612 }
plars865695b2001-08-27 22:15:12 +0000613
subrata_modak56207ce2009-03-23 13:35:39 +0000614 ret = -1;
615 while (ret == -1) { /* while empty reads */
616 if ((ret = read(fd, buf, MAXMESG)) == 0) {
617 (void)sprintf(mesg, "read() pipe failed. error:%d %s.",
618 errno, strerror(errno));
subrata_modakbdbaec52009-02-26 12:14:51 +0000619
subrata_modak56207ce2009-03-23 13:35:39 +0000620 clear_timeout();
621 return NULL;
622 }
623 }
624 clear_timeout();
plars865695b2001-08-27 22:15:12 +0000625
626#if DEBUG > 0
subrata_modak56207ce2009-03-23 13:35:39 +0000627 printf("read_pipe: pid=%d received: %s.\n", getpid(), buf);
plars865695b2001-08-27 22:15:12 +0000628#endif
subrata_modak56207ce2009-03-23 13:35:39 +0000629 return (buf);
plars865695b2001-08-27 22:15:12 +0000630
subrata_modak56207ce2009-03-23 13:35:39 +0000631} /* end of read_pipe */
plars865695b2001-08-27 22:15:12 +0000632
633/*****************************************************************************
634 * write_pipe(msg) : write msg to pipe. If it fails, put message in
635 * mesg and return -1, else return 0.
636 ****************************************************************************/
Garrett Cooper09d00362011-01-28 02:02:33 -0800637static int write_pipe(int fd, char *msg)
plars865695b2001-08-27 22:15:12 +0000638{
639
640#if DEBUG > 0
641 printf("write_pipe: pid=%d, sending %s.\n", getpid(), msg);
642#endif
643
subrata_modak56207ce2009-03-23 13:35:39 +0000644 if (write(fd, msg, MAXMESG) < 0) {
645 (void)sprintf(mesg, "write() pipe failed. error:%d %s.",
646 errno, strerror(errno));
subrata_modakbdbaec52009-02-26 12:14:51 +0000647
subrata_modak56207ce2009-03-23 13:35:39 +0000648 return (-1);
649 }
650 return 0;
plars865695b2001-08-27 22:15:12 +0000651
subrata_modak56207ce2009-03-23 13:35:39 +0000652} /* end of write_pipe */
plars865695b2001-08-27 22:15:12 +0000653
654/*****************************************************************************
655 * set_timeout() : set alarm to signal process after the period of time
656 * indicated by TIMEOUT. If the signal occurs, the routine timeout()
657 * will be executed. If all goes ok, return 0, else load message
658 * into mesg and return -1.
659 ****************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400660static int set_timeout(void)
plars865695b2001-08-27 22:15:12 +0000661{
subrata_modak56207ce2009-03-23 13:35:39 +0000662 if (signal(SIGALRM, timeout) == SIG_ERR) {
663 (void)sprintf(mesg,
664 "signal() failed for signal %d. error:%d %s.",
665 SIGALRM, errno, strerror(errno));
666 return (-1);
667 }
plars865695b2001-08-27 22:15:12 +0000668
subrata_modak56207ce2009-03-23 13:35:39 +0000669 (void)alarm(TIMEOUT);
670 return 0;
plars865695b2001-08-27 22:15:12 +0000671
subrata_modak56207ce2009-03-23 13:35:39 +0000672} /* end of set_timeout */
plars865695b2001-08-27 22:15:12 +0000673
674/*****************************************************************************
675 * clear_timeout() : turn off the alarm so that SIGALRM will not get sent.
676 ****************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400677static void clear_timeout(void)
plars865695b2001-08-27 22:15:12 +0000678{
subrata_modak56207ce2009-03-23 13:35:39 +0000679 (void)alarm(0);
plars865695b2001-08-27 22:15:12 +0000680
subrata_modak56207ce2009-03-23 13:35:39 +0000681} /* end of clear_timeout */
plars865695b2001-08-27 22:15:12 +0000682
683/*****************************************************************************
subrata_modak4bb656a2009-02-26 12:02:09 +0000684 * timeout() : this routine is executed when the SIGALRM signal is
plars865695b2001-08-27 22:15:12 +0000685 * caught. It does nothing but return - the read() on the pipe
686 * will fail.
687 ****************************************************************************/
Mike Frysingere61ddba2014-04-09 23:24:32 -0400688static void timeout(int sig)
plars865695b2001-08-27 22:15:12 +0000689{
690#if DEBUG > 0
691 printf("timeout: pid=%d sigalrm caught.\n", getpid());
692#endif
693}
subrata_modakbdbaec52009-02-26 12:14:51 +0000694
plars865695b2001-08-27 22:15:12 +0000695/*****************************************************************************
Garrett Cooperdf3eb162010-11-28 22:44:32 -0800696 * wait_a_while () : wait a while before returning.
plars865695b2001-08-27 22:15:12 +0000697 ****************************************************************************/
Mike Frysingerc57fba52014-04-09 18:56:30 -0400698static void wait_a_while(void)
plars865695b2001-08-27 22:15:12 +0000699{
subrata_modak56207ce2009-03-23 13:35:39 +0000700 long btime;
plars865695b2001-08-27 22:15:12 +0000701
Mike Frysingere61ddba2014-04-09 23:24:32 -0400702 btime = time(NULL);
703 while (time(NULL) - btime < TIMEOUT) {
subrata_modak56207ce2009-03-23 13:35:39 +0000704 if (sig_caught == TRUE)
705 break;
706 }
subrata_modak56207ce2009-03-23 13:35:39 +0000707} /* end of wait_a_while */
plars865695b2001-08-27 22:15:12 +0000708
Mike Frysingerc57fba52014-04-09 18:56:30 -0400709static void getout(void)
plars865695b2001-08-27 22:15:12 +0000710{
vapierb8a44eb2009-08-28 14:10:16 +0000711 if (pid > 0 && kill(pid, SIGKILL) < 0)
712 tst_resm(TWARN, "kill(%d, SIGKILL) failed", pid);
subrata_modak56207ce2009-03-23 13:35:39 +0000713 cleanup();
plars865695b2001-08-27 22:15:12 +0000714
subrata_modak56207ce2009-03-23 13:35:39 +0000715} /* end of getout */
plars865695b2001-08-27 22:15:12 +0000716
717#ifdef VAX
Garrett Cooper09d00362011-01-28 02:02:33 -0800718static int sighold(int signo)
plars865695b2001-08-27 22:15:12 +0000719{
subrata_modak43337a32009-02-26 11:43:51 +0000720 return 0;
plars865695b2001-08-27 22:15:12 +0000721}
722
subrata_modak56207ce2009-03-23 13:35:39 +0000723static int sigrelse(signo)
plars865695b2001-08-27 22:15:12 +0000724int signo;
725{
subrata_modak43337a32009-02-26 11:43:51 +0000726 return 0;
plars865695b2001-08-27 22:15:12 +0000727}
728#endif
729
Garrett Cooper09d00362011-01-28 02:02:33 -0800730int choose_sig(int sig)
plars865695b2001-08-27 22:15:12 +0000731{
subrata_modak56207ce2009-03-23 13:35:39 +0000732 switch (sig) {
plars865695b2001-08-27 22:15:12 +0000733
734 case SIGKILL:
735 case SIGSTOP:
736 case SIGTSTP:
737 case SIGCONT:
738 case SIGALRM:
robbiew94350592003-04-29 17:05:41 +0000739 case SIGCANCEL:
740 case SIGTIMER:
plars865695b2001-08-27 22:15:12 +0000741#ifdef SIGNOBDM
742 case SIGNOBDM:
743#endif
744#ifdef SIGTTIN
745 case SIGTTIN:
746#endif
747#ifdef SIGTTOU
748 case SIGTTOU:
749#endif
750#ifdef SIGPTINTR
751 case SIGPTINTR:
752#endif
753#ifdef SIGSWAP
754 case SIGSWAP:
755#endif
756 return 0;
757
subrata_modak56207ce2009-03-23 13:35:39 +0000758 }
plars865695b2001-08-27 22:15:12 +0000759
Garrett Cooper09d00362011-01-28 02:02:33 -0800760 return 1;
plars865695b2001-08-27 22:15:12 +0000761
Garrett Cooper09d00362011-01-28 02:02:33 -0800762}
plars865695b2001-08-27 22:15:12 +0000763
Mike Frysingerc57fba52014-04-09 18:56:30 -0400764void setup(void)
plars865695b2001-08-27 22:15:12 +0000765{
Garrett Cooper2c282152010-12-16 00:55:50 -0800766
subrata_modak56207ce2009-03-23 13:35:39 +0000767 tst_sig(FORK, DEF_HANDLER, cleanup);
plars865695b2001-08-27 22:15:12 +0000768
subrata_modak56207ce2009-03-23 13:35:39 +0000769 TEST_PAUSE;
plars865695b2001-08-27 22:15:12 +0000770
subrata_modak56207ce2009-03-23 13:35:39 +0000771 tst_tmpdir();
plars865695b2001-08-27 22:15:12 +0000772
subrata_modak56207ce2009-03-23 13:35:39 +0000773 /* set up pipe for parent/child communications */
Garrett Cooper09d00362011-01-28 02:02:33 -0800774 SAFE_PIPE(cleanup, pipe_fd);
plars865695b2001-08-27 22:15:12 +0000775
subrata_modak56207ce2009-03-23 13:35:39 +0000776 /*
777 * Cause the read to return 0 once EOF is encountered and the
778 * read to return -1 if pipe is empty.
779 */
780 if (fcntl(pipe_fd[0], F_SETFL, O_NONBLOCK) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800781 tst_brkm(TBROK | TERRNO, cleanup,
782 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
plars865695b2001-08-27 22:15:12 +0000783
subrata_modak56207ce2009-03-23 13:35:39 +0000784 /* set up pipe for parent/child communications */
Garrett Cooper09d00362011-01-28 02:02:33 -0800785 SAFE_PIPE(cleanup, pipe_fd2);
plars865695b2001-08-27 22:15:12 +0000786
subrata_modak56207ce2009-03-23 13:35:39 +0000787 /*
788 * Cause the read to return 0 once EOF is encountered and the
789 * read to return -1 if pipe is empty.
790 */
791 if (fcntl(pipe_fd2[0], F_SETFL, O_NONBLOCK) == -1)
Wanlong Gao354ebb42012-12-07 10:10:04 +0800792 tst_brkm(TBROK | TERRNO, cleanup,
793 "fcntl(Fds[0], F_SETFL, O_NONBLOCK) failed");
Garrett Cooper2c282152010-12-16 00:55:50 -0800794}
plars865695b2001-08-27 22:15:12 +0000795
Mike Frysingerc57fba52014-04-09 18:56:30 -0400796void cleanup(void)
plars865695b2001-08-27 22:15:12 +0000797{
subrata_modak56207ce2009-03-23 13:35:39 +0000798 tst_rmdir();
plars865695b2001-08-27 22:15:12 +0000799
Garrett Cooper09d00362011-01-28 02:02:33 -0800800}