X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2Ffatal-signal.c;h=c726a0cb5f7545acd342f0e555dbd7ebe8b03ac3;hb=d6913e92bfd13a918b19223fb676e9c0f136400e;hp=ea78012dd941bd05806f3dacab5bea891ea8981b;hpb=40b33d9d6c32cd1afac372a5da2b002aac5a881d;p=gnulib.git diff --git a/lib/fatal-signal.c b/lib/fatal-signal.c index ea78012dd..c726a0cb5 100644 --- a/lib/fatal-signal.c +++ b/lib/fatal-signal.c @@ -1,5 +1,5 @@ /* Emergency actions in case of a fatal signal. - Copyright (C) 2003 Free Software Foundation, Inc. + Copyright (C) 2003-2004 Free Software Foundation, Inc. Written by Bruno Haible , 2003. This program is free software; you can redistribute it and/or modify @@ -50,10 +50,11 @@ SIGSTKFLT - because it is more similar to SIGFPE, SIGSEGV, SIGBUS, SIGSYS - because it is more similar to SIGABRT, SIGSEGV, SIGPWR - because it of too special use, + SIGRTMIN...SIGRTMAX - because they are reserved for application use. plus SIGXCPU, SIGXFSZ - because they are quite similar to SIGTERM. */ -static const int fatal_signals[] = +static int fatal_signals[] = { /* ISO C 99 signals. */ #ifdef SIGINT @@ -81,15 +82,50 @@ static const int fatal_signals[] = #define num_fatal_signals (SIZEOF (fatal_signals) - 1) +/* Eliminate signals whose signal handler is SIG_IGN. */ + +static void +init_fatal_signals (void) +{ + static bool fatal_signals_initialized = false; + if (!fatal_signals_initialized) + { +#if HAVE_SIGACTION + size_t i; + + for (i = 0; i < num_fatal_signals; i++) + { + struct sigaction action; + + if (sigaction (fatal_signals[i], NULL, &action) >= 0 + && action.sa_handler == SIG_IGN) + fatal_signals[i] = -1; + } +#endif + + fatal_signals_initialized = true; + } +} + /* ========================================================================= */ -/* The registered cleanup actions. */ typedef void (*action_t) (void); -static action_t static_actions[32]; -static action_t * volatile actions = static_actions; -static size_t volatile actions_count = 0; + +/* Type of an entry in the actions array. + The 'action' field is accessed from within the fatal_signal_handler(), + therefore we mark it as 'volatile'. */ +typedef struct +{ + volatile action_t action; +} +actions_entry_t; + +/* The registered cleanup actions. */ +static actions_entry_t static_actions[32]; +static actions_entry_t * volatile actions = static_actions; +static sig_atomic_t volatile actions_count = 0; static size_t actions_allocated = SIZEOF (static_actions); @@ -100,7 +136,8 @@ uninstall_handlers () size_t i; for (i = 0; i < num_fatal_signals; i++) - signal (fatal_signals[i], SIG_DFL); + if (fatal_signals[i] >= 0) + signal (fatal_signals[i], SIG_DFL); } @@ -117,12 +154,15 @@ fatal_signal_handler (int sig) break; n--; actions_count = n; - action = actions[n]; + action = actions[n].action; /* Execute the action. */ action (); } - /* Now execute the signal's default action. */ + /* Now execute the signal's default action. + If signal() blocks the signal being delivered for the duration of the + signal handler's execution, the re-raised signal is delivered when this + handler returns; otherwise it is delivered already during raise(). */ uninstall_handlers (); #if HAVE_RAISE raise (sig); @@ -139,7 +179,8 @@ install_handlers () size_t i; for (i = 0; i < num_fatal_signals; i++) - signal (fatal_signals[i], &fatal_signal_handler); + if (fatal_signals[i] >= 0) + signal (fatal_signals[i], &fatal_signal_handler); } @@ -151,6 +192,7 @@ at_fatal_signal (action_t action) static bool cleanup_initialized = false; if (!cleanup_initialized) { + init_fatal_signals (); install_handlers (); cleanup_initialized = true; } @@ -160,19 +202,24 @@ at_fatal_signal (action_t action) /* Extend the actions array. Note that we cannot use xrealloc(), because then the cleanup() function could access an already deallocated array. */ - action_t *old_actions = actions; + actions_entry_t *old_actions = actions; size_t new_actions_allocated = 2 * actions_allocated; - action_t *new_actions = - xmalloc (new_actions_allocated * sizeof (action_t)); + actions_entry_t *new_actions = + xmalloc (new_actions_allocated * sizeof (actions_entry_t)); - memcpy (new_actions, actions, actions_allocated * sizeof (action_t)); + memcpy (new_actions, old_actions, + actions_allocated * sizeof (actions_entry_t)); actions = new_actions; actions_allocated = new_actions_allocated; /* Now we can free the old actions array. */ if (old_actions != static_actions) free (old_actions); } - actions[actions_count] = action; + /* The two uses of 'volatile' in the types above (and ISO C 99 section + 5.1.2.3.(5)) ensure that we increment the actions_count only after + the new action has been written to the memory location + actions[actions_count]. */ + actions[actions_count].action = action; actions_count++; } @@ -192,14 +239,18 @@ init_fatal_signal_set () { size_t i; + init_fatal_signals (); + sigemptyset (&fatal_signal_set); for (i = 0; i < num_fatal_signals; i++) - sigaddset (&fatal_signal_set, fatal_signals[i]); + if (fatal_signals[i] >= 0) + sigaddset (&fatal_signal_set, fatal_signals[i]); fatal_signal_set_initialized = true; } } +/* Temporarily delay the catchable fatal signals. */ void block_fatal_signals () { @@ -207,6 +258,7 @@ block_fatal_signals () sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL); } +/* Stop delaying the catchable fatal signals. */ void unblock_fatal_signals () {