2 * (c) Copyright 1992 by Panagiotis Tsirigotis
3 * (c) Sections Copyright 1998-2001 by Rob Braun
4 * All rights reserved. The file named COPYRIGHT specifies the terms
5 * and conditions for redistribution.
10 #if defined(HAVE_STRSIGNAL)
13 #include <sys/types.h>
22 #include <sys/ioctl.h>
23 #ifdef HAVE_SYS_FILIO_H
24 #include <sys/filio.h>
36 #include "internals.h"
40 * XXX: here we assume that in the case that NO_POSIX_TYPES is not defined
41 * (i.e. the system has posix types) the sigset_t is also typedef'd
42 * to 'int'. Our goal is to work with systems that have defined
43 * sigset_t but do not yet support the posix signal interface.
45 typedef int sigset_t ;
49 void (*sa_handler)(int) ;
53 #endif /* NO_POSIX_TYPES */
55 static void my_handler( int sig );
56 static void general_handler( int sig );
58 typedef void sigfunc( int );
60 #define SIGSET_NULL ((sigset_t *)0)
61 #define SIGVEC_NULL ((struct sigvec *)0)
62 #define SIGACTION_NULL ((struct sigaction *)0)
67 #define sigmask( sig ) ( 1 << ( (sig) -1 ) )
68 typedef int (*sighandler_type)() ;
70 #define sigsetmask( x )
71 #endif /* NO_SIGVEC */
73 #define sigsuspend( set ) sigpause( *set )
74 #define sigemptyset( set ) (*set) = 0
75 #define sigaddset( set, sig ) ( ( (*set) |= sigmask( sig ) ), 0 )
76 #define sigismember( set, sig ) ( ( (*set) & sigmask( sig ) ) != 0 )
79 * Only works for SIG_SETMASK and SIG_UNBLOCK. Also oset must be NULL.
81 int sigprocmask( int how, sigset_t *set, sigset_t *oset )
83 if ( how == SIG_BLOCK || oset != NULL )
85 msg( LOG_ERR, "sigprocmask",
86 "Bad args: how = %d, oset = %p", how, oset ) ;
90 if ( how == SIG_SETMASK )
92 (void) sigsetmask( *set ) ;
96 if ( how == SIG_UNBLOCK )
98 int current_mask = sigblock( 0 ) ;
100 (void) sigsetmask( current_mask & ~*set ) ;
108 * NOTE: This is not a complete imitation of sigaction; in particular it
109 * expects that sap is never NULL and that osap is always NULL.
111 int sigaction( int sig, struct sigaction *sap, struct sigaction *osap )
113 if ( sap == NULL || osap != NULL )
115 msg( LOG_ERR, "sigaction", "Bad args: sap = %p, osap = %p", sap, osap ) ;
123 sv.sv_handler = sap->sa_handler ;
124 sv.sv_mask = sap->sa_mask ;
125 sv.sv_flags = sap->sa_flags ;
127 return( sigvec( sig, &sv, SIGVEC_NULL ) ) ;
129 #else /* NO_SIGVEC */
131 sighandler_type new_handler ;
133 new_handler = sa.sa_handler ;
134 return( signal( sig, new_handler ) ? 0 : -1 ) ;
136 #endif /* ! NO_SIGVEC */
139 #endif /* NO_POSIX_SIGS */
143 * reset_sigs is the list of signals that we need to reset to SIG_DFL.
144 * Currently, these are the signals whose actions we set to SIG_IGN.
145 * In general, we should also include any signals that have a handler
146 * that does anything other than setting a flag. We need to do this
147 * in case such a signal occurs while a forked process is providing
148 * an internal service.
150 static sigset_t reset_sigs ;
153 * nsig is equal to the greatest signal number supported plus 1
159 * When this function returns FAILED, we check the errno to determine
160 * if it failed because the signal number specified was invalid.
161 * This allows us to determine the number of supported signals.
163 static status_e handle_signal( int sig )
165 struct sigaction sa ;
166 sigfunc *sig_handler ;
172 case RECONFIG_HARD_SIG:
173 case OLD_RECONFIG_HARD_SIG:
174 case TERMINATION_SIG:
176 case CONSISTENCY_CHECK_SIG:
177 case SERVER_EXIT_SIG:
179 sig_handler = my_handler ;
190 * We may receive a SIGPIPE when handling an internal stream
191 * service and the other end closes the connection.
192 * We only care about internal services that don't require forking.
195 sig_handler = SIG_IGN ;
196 sigaddset( &reset_sigs, sig ) ;
201 return( OK ) ; /* we can't catch these two */
204 * If the following two cases are included, SIGSEGV and SIGBUS will
205 * cause core dumps. We want that to happen when we are debugging
206 * xinetd (i.e. DEBUG is defined) and we are not debugging the
207 * signal recovery code (i.e. DEBUG_SIGNALS is not defined).
211 #if defined( DEBUG ) && !defined( DEBUG_SIGNALS )
214 sig_handler = general_handler ;
222 sig_handler = general_handler ;
225 sigemptyset( &sa.sa_mask ) ;
226 sa.sa_handler = sig_handler ;
227 return( ( sigaction( sig, &sa, SIGACTION_NULL ) == -1 ) ? FAILED : OK ) ;
232 * Install signal handlers for all signals that can be caught.
233 * This implies that no core dumps are generated by default.
235 status_e signal_init(void)
238 const char *func = "install_signal_handlers" ;
240 sigemptyset( &reset_sigs ) ;
242 if ( pipe(signals_pending) ||
243 fcntl(signals_pending[0], F_SETFD, FD_CLOEXEC) ||
244 fcntl(signals_pending[1], F_SETFD, FD_CLOEXEC) ) {
245 msg( LOG_CRIT, func, "Failed to create signal pipe: %m" );
249 for ( sig = 1 ;; sig++ )
250 if ( handle_signal( sig ) == FAILED ) {
251 if ( errno == EINVAL )
259 "Failed to install signal handler for signal %s: %m",
267 #define MAX_SIGNAL_COUNT 50
268 #define MAX_INTERVAL_SIGNAL_COUNT 10
269 #define SIGNAL_INTERVAL 1 /* second */
271 * This function handles SIGSEGV and SIGBUS.
272 * Emergency action is taken if a certain number (MAX_SIGNAL_COUNT) of
273 * these signals is received over the lifetime of the program OR
274 * if a certain number (MAX_INTERVAL_SIGNAL_COUNT) of these signals
275 * is received within a certain time interval (SIGNAL_INTERVAL).
277 * The action depends on the type of the emergency:
278 * Case 1: MAX_INTERVAL_SIGNAL_COUNT is exceeded
279 * If a setjmp environment is available, do a longjmp, otherwise exit
280 * Case 2: MAX_SIGNAL_COUNT is exceeded
283 * NOTE: We try to send a message to the log only once to avoid
284 * looping in this function (in case there is a bug in msg())
286 static void bad_signal(void)
288 static time_t interval_start ;
289 static volatile int interval_signal_count ;
290 static volatile int total_signal_count ;
291 time_t current_time ;
292 const char *func = "bad_signal" ;
294 total_signal_count++ ;
295 if ( total_signal_count == MAX_SIGNAL_COUNT )
298 "Received %d bad signals. Exiting...", total_signal_count ) ;
301 else if ( total_signal_count > MAX_SIGNAL_COUNT )
302 _exit( 1 ) ; /* in case of a problem in exit(3) */
304 (void) time( ¤t_time ) ;
306 if ( interval_signal_count > 0 &&
307 current_time - interval_start <= SIGNAL_INTERVAL )
309 interval_signal_count++ ;
310 if ( interval_signal_count == MAX_INTERVAL_SIGNAL_COUNT )
312 if ( ps.rws.env_is_valid )
314 interval_start = current_time ;
315 interval_signal_count = 1 ;
316 msg( LOG_ERR, func, "Resetting..." ) ;
317 siglongjmp( ps.rws.env, 1 ) ;
321 "Received %d signals in %d seconds. Exiting...",
322 interval_signal_count, SIGNAL_INTERVAL ) ;
325 else if ( interval_signal_count > MAX_INTERVAL_SIGNAL_COUNT )
326 _exit( 1 ) ; /* shouldn't happen */
330 interval_start = current_time ;
331 interval_signal_count = 1 ;
335 char *sig_name( int sig )
337 static char signame_buf[ 30 ] ;
339 #if defined(HAVE_STRSIGNAL)
340 /* Use strsignal and remove the old sys_siglist stuff */
342 return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1,
343 "%d (%s)", sig, strsignal(sig) ) ) ;
345 #if defined(HAVE_SYS_SIGLIST)
347 return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1,
348 "%d (%s)", sig, sys_siglist[sig] ) ) ;
351 return( strx_sprint( signame_buf, sizeof( signame_buf ) - 1, "%d", sig ) ) ;
356 * For SIGSEGV and SIGBUS we invoke the bad_signal() function
358 * For other signals, we just log the fact that they occured.
359 * SIGINT is a special case since in debug.on mode, it will
363 static void general_handler( int sig )
366 const char *func = "general_handler" ;
369 * Do this here to catch problems like SIGSEGV in msg()
371 sigemptyset( &badsigs ) ;
372 sigaddset( &badsigs, sig ) ;
373 (void) sigprocmask( SIG_UNBLOCK, &badsigs, SIGSET_NULL ) ;
379 msg( LOG_CRIT, func, "(%d) Unexpected signal: %s",
380 getpid(), sig_name( sig ) ) ;
383 /* Generate a core dump */
384 signal(SIGABRT, SIG_DFL);
392 msg( LOG_NOTICE, func, "Unexpected signal %s", sig_name( sig ) ) ;
393 if ( debug.on && sig == SIGINT )
400 * The job of this function is to write the signal received to the
401 * pipe of pending signals, which is in the main select loop.
403 static void my_handler( int sig )
406 int saved_errno = errno;
408 unsigned char sig_byte;
409 if (signals_pending[1] < 0) return;
410 if (sig >= 256) return;
414 ret_val = write(signals_pending[1], &sig_byte, 1);
415 } while (ret_val == -1 && errno == EINTR);
417 if (signals_pending[1] < 0) return;
420 ret_val = write(signals_pending[1], &sig, sizeof(int));
421 } while (ret_val == -1 && errno == EINTR);
428 * Reset all signals to default action. Reset the signal mask
430 * This function is invoked from a forked process. That is why we
431 * invoke _exit instead of exit (to avoid the possible stdio buffer flushes)
433 void signal_default_state(void)
438 for ( sig = 1 ; sig < nsig ; sig++ )
439 if ( sigismember( &reset_sigs, sig ) == 1 )
440 if ( signal( sig, SIG_DFL ) == SIG_ERR )
442 msg( LOG_ERR, "reset_signals",
443 "signal failed for signal %s: %m", sig_name( sig ) ) ;
448 sigemptyset( &empty ) ;
449 (void) sigprocmask( SIG_SETMASK, &empty, SIGSET_NULL ) ;
452 void check_pipe(void)
460 const char *func = "check_pipe";
462 if (signals_pending[0] < 0) return;
464 if( ioctl(signals_pending[0], FIONREAD, &i) != 0 ) {
465 msg(LOG_ERR, func, "Can't get the number of pending signals: %m");
476 ret_val = read(signals_pending[0], &sig, sizeof(sig));
477 } while (ret_val == -1 && errno == EINTR);
478 if (ret_val != sizeof(sig) ) {
479 msg(LOG_ERR, func, "Error retrieving pending signal: %m");
484 msg(LOG_DEBUG, func, "Got signal %s", sig_name(sig));
488 case SERVER_EXIT_SIG: child_exit(); break;
489 case RECONFIG_HARD_SIG: hard_reconfig(); break;
490 case OLD_RECONFIG_HARD_SIG: hard_reconfig(); break;
491 case TERMINATION_SIG: terminate_program(); break;
492 case STATE_DUMP_SIG: dump_internal_state(); break;
493 case CONSISTENCY_CHECK_SIG: user_requested_check(); break;
494 case QUIT_SIG: quit_program(); break;
496 msg(LOG_ERR, func, "unexpected signal: %s in signal pipe",