xref: /third_party/ltp/lib/tst_sig.c (revision f08c3bdf)
1/*
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
20 * with this program; if not, write the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
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
33/* $Id: tst_sig.c,v 1.13 2009/08/28 09:29:01 vapier Exp $ */
34
35/*****************************************************************************
36	OS Testing  - Silicon Graphics, Inc.
37
38	FUNCTION IDENTIFIER : tst_sig  Set up for unexpected signals.
39
40	AUTHOR          : David D. Fenner
41
42	CO-PILOT        : Bill Roske
43
44	DATE STARTED    : 06/06/90
45
46	This module may be linked with c-modules requiring unexpected
47	signal handling.  The parameters to tst_sig are as follows:
48
49		fork_flag - set to FORK or NOFORK depending upon whether the
50			calling program executes a fork() system call.  It
51			is normally the case that the calling program treats
52			SIGCHLD as an expected signal if fork() is being used.
53
54		handler - a pointer to the unexpected signal handler to
55			be executed after an unexpected signal has been
56			detected.  If handler is set to DEF_HANDLER, a
57			default handler is used.  This routine should be
58			declared as function returning an int.
59
60		cleanup - a pointer to a cleanup routine to be executed
61			by the unexpected signal handler before tst_exit is
62			called.  This parameter is set to NULL if no cleanup
63			routine is required.  An external variable, T_cleanup
64			is set so that other user-defined handlers have
65			access to the cleanup routine.  This routine should be
66			declared as returning type void.
67
68***************************************************************************/
69
70#include <errno.h>
71#include <string.h>
72#include <signal.h>
73#include <unistd.h>
74#include "test.h"
75#include "lapi/signal.h"
76
77#define MAXMESG 150		/* size of mesg string sent to tst_res */
78
79static void (*T_cleanup) ();
80
81static void def_handler();	/* default signal handler */
82static void (*tst_setup_signal(int, void (*)(int))) (int);
83
84/****************************************************************************
85 * tst_sig() : set-up to catch unexpected signals.  fork_flag is set to NOFORK
86 *    if SIGCHLD is to be an "unexpected signal", otherwise it is set to
87 *    FORK.  cleanup points to a cleanup routine to be executed before
88 *    tst_exit is called (cleanup is set to NULL if no cleanup is desired).
89 *    handler is a pointer to the signal handling routine (if handler is
90 *    set to NULL, a default handler is used).
91 ***************************************************************************/
92
93void tst_sig(int fork_flag, void (*handler) (), void (*cleanup) ())
94{
95	int sig;
96#ifdef _SC_SIGRT_MIN
97	long sigrtmin, sigrtmax;
98#endif
99
100	/*
101	 * save T_cleanup and handler function pointers
102	 */
103	T_cleanup = cleanup;	/* used by default handler */
104
105	if (handler == DEF_HANDLER) {
106		/* use default handler */
107		handler = def_handler;
108	}
109#ifdef _SC_SIGRT_MIN
110	sigrtmin = sysconf(_SC_SIGRT_MIN);
111	sigrtmax = sysconf(_SC_SIGRT_MAX);
112#endif
113
114	/*
115	 * now loop through all signals and set the handlers
116	 */
117
118	for (sig = 1; sig < NSIG; sig++) {
119		/*
120		 * SIGKILL is never unexpected.
121		 * SIGCHLD is only unexpected when
122		 *    no forking is being done.
123		 * SIGINFO is used for file quotas and should be expected
124		 */
125
126#ifdef _SC_SIGRT_MIN
127		if (sig >= sigrtmin && sig <= sigrtmax)
128			continue;
129#endif
130
131		switch (sig) {
132		case SIGKILL:
133		case SIGSTOP:
134		case SIGCONT:
135#if !defined(_SC_SIGRT_MIN) && defined(__SIGRTMIN) && defined(__SIGRTMAX)
136			/* Ignore all real-time signals */
137		case __SIGRTMIN:
138		case __SIGRTMIN + 1:
139		case __SIGRTMIN + 2:
140		case __SIGRTMIN + 3:
141		case __SIGRTMIN + 4:
142		case __SIGRTMIN + 5:
143		case __SIGRTMIN + 6:
144		case __SIGRTMIN + 7:
145		case __SIGRTMIN + 8:
146		case __SIGRTMIN + 9:
147		case __SIGRTMIN + 10:
148		case __SIGRTMIN + 11:
149		case __SIGRTMIN + 12:
150		case __SIGRTMIN + 13:
151		case __SIGRTMIN + 14:
152		case __SIGRTMIN + 15:
153/* __SIGRTMIN is 37 on HPPA rather than 32 *
154 * as on i386, etc.                        */
155#if !defined(__hppa__)
156		case __SIGRTMAX - 15:
157		case __SIGRTMAX - 14:
158		case __SIGRTMAX - 13:
159		case __SIGRTMAX - 12:
160		case __SIGRTMAX - 11:
161#endif
162		case __SIGRTMAX - 10:
163		case __SIGRTMAX - 9:
164		case __SIGRTMAX - 8:
165		case __SIGRTMAX - 7:
166		case __SIGRTMAX - 6:
167		case __SIGRTMAX - 5:
168		case __SIGRTMAX - 4:
169		case __SIGRTMAX - 3:
170		case __SIGRTMAX - 2:
171		case __SIGRTMAX - 1:
172		case __SIGRTMAX:
173#endif
174#ifdef SIGSWAP
175		case SIGSWAP:
176#endif /* SIGSWAP */
177
178#ifdef SIGCKPT
179		case SIGCKPT:
180#endif
181#ifdef SIGRESTART
182		case SIGRESTART:
183#endif
184			/*
185			 * pthread-private signals SIGPTINTR and SIGPTRESCHED.
186			 * Setting a handler for these signals is disallowed when
187			 * the binary is linked against libpthread.
188			 */
189#ifdef SIGPTINTR
190		case SIGPTINTR:
191#endif /* SIGPTINTR */
192#ifdef SIGPTRESCHED
193		case SIGPTRESCHED:
194#endif /* SIGPTRESCHED */
195#ifdef _SIGRESERVE
196		case _SIGRESERVE:
197#endif
198#ifdef _SIGDIL
199		case _SIGDIL:
200#endif
201#ifdef _SIGCANCEL
202		case _SIGCANCEL:
203#endif
204#ifdef _SIGGFAULT
205		case _SIGGFAULT:
206#endif
207			break;
208
209		case SIGCHLD:
210			if (fork_flag == FORK)
211				continue;
212
213		default:
214			if (tst_setup_signal(sig, handler) == SIG_ERR)
215				tst_resm(TWARN | TERRNO,
216					 "signal failed for signal %d", sig);
217			break;
218		}
219	}
220}
221
222/****************************************************************************
223 * def_handler() : default signal handler that is invoked when
224 *      an unexpected signal is caught.
225 ***************************************************************************/
226
227static void def_handler(int sig)
228{
229	/*
230	 * Break remaining test cases, do any cleanup, then exit
231	 */
232	tst_brkm(TBROK, T_cleanup,
233		 "unexpected signal %s(%d) received (pid = %d).",
234		 tst_strsig(sig), sig, getpid());
235}
236
237/*
238 * tst_setup_signal - A function like signal(), but we have
239 *                    control over its personality.
240 */
241static void (*tst_setup_signal(int sig, void (*handler) (int))) (int) {
242	struct sigaction my_act, old_act;
243	int ret;
244
245	my_act.sa_handler = handler;
246	my_act.sa_flags = SA_RESTART;
247	sigemptyset(&my_act.sa_mask);
248
249	ret = sigaction(sig, &my_act, &old_act);
250
251	if (ret == 0)
252		return old_act.sa_handler;
253	else
254		return SIG_ERR;
255}
256