+2003-10-06 Bruno Haible <bruno@clisp.org>
+
+ * modules/fatal-signal: New file.
+ * MODULES.html.sh (func_all_modules): Add fatal-signal.
+
2003-10-05 Paul Eggert <eggert@twinsun.com>
* README: Rework advice for preventing empty .o files.
2003-10-01 Simon Josefsson <jas@extundo.com>
- * MODULES.html.sh: Move gethostname from section 'based on' to section
- 'lacking' POSIX:2001.
+ * MODULES.html.sh (func_all_modules): Move gethostname from section
+ 'based on' to section 'lacking' POSIX:2001.
2003-09-27 Oskar Liljeblad <oskar@osk.mine.nu>
func_module vasprintf
func_end_table
+ element="Signal handling <signal.h>"
+ element=`printf "%s" "$element" | sed -e "$sed_lt" -e "$sed_gt"`
+ func_section_wrap ansic_ext_signal
+ func_wrap H3
+ func_echo "$element"
+
+ func_begin_table
+ func_module fatal-signal
+ func_end_table
+
element="Command-line arguments"
element=`printf "%s" "$element" | sed -e "$sed_lt" -e "$sed_gt"`
func_section_wrap ansic_ext_argv
+2003-10-06 Bruno Haible <bruno@clisp.org>
+
+ * fatal-signal.h: New file, from GNU gettext.
+ * fatal-signal.c: New file, from GNU gettext.
+
2003-10-04 Karl Berry <karl@gnu.org>
* argp*: update from libc.
--- /dev/null
+/* Emergency actions in case of a fatal signal.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+/* Specification. */
+#include "fatal-signal.h"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <string.h>
+#if HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "xalloc.h"
+
+#define SIZEOF(a) (sizeof(a) / sizeof(a[0]))
+
+
+/* ========================================================================= */
+
+
+/* The list of fatal signals.
+ These are those signals whose default action is to terminate the process
+ without a core dump, except
+ SIGKILL - because it cannot be caught,
+ SIGALRM SIGUSR1 SIGUSR2 SIGPOLL SIGIO SIGLOST - because applications
+ often use them for their own purpose,
+ SIGPROF SIGVTALRM - because they are used for profiling,
+ 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,
+ plus
+ SIGXCPU, SIGXFSZ - because they are quite similar to SIGTERM. */
+
+static const int fatal_signals[] =
+ {
+ /* ISO C 99 signals. */
+#ifdef SIGINT
+ SIGINT,
+#endif
+#ifdef SIGTERM
+ SIGTERM,
+#endif
+ /* POSIX:2001 signals. */
+#ifdef SIGHUP
+ SIGHUP,
+#endif
+#ifdef SIGPIPE
+ SIGPIPE,
+#endif
+ /* BSD signals. */
+#ifdef SIGXCPU
+ SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+ SIGXFSZ,
+#endif
+ 0
+ };
+
+#define num_fatal_signals (SIZEOF (fatal_signals) - 1)
+
+
+/* ========================================================================= */
+
+
+/* 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;
+static size_t actions_allocated = SIZEOF (static_actions);
+
+
+/* Uninstall the handlers. */
+static inline void
+uninstall_handlers ()
+{
+ size_t i;
+
+ for (i = 0; i < num_fatal_signals; i++)
+ signal (fatal_signals[i], SIG_DFL);
+}
+
+
+/* The signal handler. It gets called asynchronously. */
+static void
+fatal_signal_handler (int sig)
+{
+ for (;;)
+ {
+ /* Get the last registered cleanup action, in a reentrant way. */
+ action_t action;
+ size_t n = actions_count;
+ if (n == 0)
+ break;
+ n--;
+ actions_count = n;
+ action = actions[n];
+ /* Execute the action. */
+ action ();
+ }
+
+ /* Now execute the signal's default action. */
+ uninstall_handlers ();
+#if HAVE_RAISE
+ raise (sig);
+#else
+ kill (getpid (), sig);
+#endif
+}
+
+
+/* Install the handlers. */
+static inline void
+install_handlers ()
+{
+ size_t i;
+
+ for (i = 0; i < num_fatal_signals; i++)
+ signal (fatal_signals[i], &fatal_signal_handler);
+}
+
+
+/* Register a cleanup function to be executed when a catchable fatal signal
+ occurs. */
+void
+at_fatal_signal (action_t action)
+{
+ static bool cleanup_initialized = false;
+ if (!cleanup_initialized)
+ {
+ install_handlers ();
+ cleanup_initialized = true;
+ }
+
+ if (actions_count == actions_allocated)
+ {
+ /* 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;
+ size_t new_actions_allocated = 2 * actions_allocated;
+ action_t *new_actions =
+ xmalloc (new_actions_allocated * sizeof (action_t));
+
+ memcpy (new_actions, actions, actions_allocated * sizeof (action_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;
+ actions_count++;
+}
+
+
+/* ========================================================================= */
+
+
+#if HAVE_POSIX_SIGNALBLOCKING
+
+static sigset_t fatal_signal_set;
+
+static void
+init_fatal_signal_set ()
+{
+ static bool fatal_signal_set_initialized = false;
+ if (!fatal_signal_set_initialized)
+ {
+ size_t i;
+
+ sigemptyset (&fatal_signal_set);
+ for (i = 0; i < num_fatal_signals; i++)
+ sigaddset (&fatal_signal_set, fatal_signals[i]);
+
+ fatal_signal_set_initialized = true;
+ }
+}
+
+void
+block_fatal_signals ()
+{
+ init_fatal_signal_set ();
+ sigprocmask (SIG_BLOCK, &fatal_signal_set, NULL);
+}
+
+void
+unblock_fatal_signals ()
+{
+ init_fatal_signal_set ();
+ sigprocmask (SIG_UNBLOCK, &fatal_signal_set, NULL);
+}
+
+#else
+
+/* Don't bother caring about the old systems which don't have POSIX signal
+ blocking. */
+
+void
+block_fatal_signals ()
+{
+}
+
+void
+unblock_fatal_signals ()
+{
+}
+
+#endif
--- /dev/null
+/* Emergency actions in case of a fatal signal.
+ Copyright (C) 2003 Free Software Foundation, Inc.
+ Written by Bruno Haible <bruno@clisp.org>, 2003.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software Foundation,
+ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/* It is often useful to do some cleanup action when a usually fatal signal
+ terminates the process, like removing a temporary file or killing a
+ subprocess that may be stuck waiting for a device, pipe or network input.
+ Such signals are SIGHUP, SIGINT, SIGPIPE, SIGTERM, and possibly others.
+ The limitation of this facility is that it cannot work for SIGKILL. */
+
+/* Register a cleanup function to be executed when a catchable fatal signal
+ occurs. */
+extern void at_fatal_signal (void (*function) (void));
+
+
+/* Sometimes it is necessary to block the usually fatal signals while the
+ data structures being accessed by the cleanup action are being built or
+ reorganized. This is the case, for example, when a temporary file or
+ directory is created through mkstemp() or mkdtemp(), because these
+ functions create the temporary file or directory _before_ returning its
+ name to the application. */
+
+/* Temporarily delay the catchable fatal signals. */
+extern void block_fatal_signals (void);
+
+/* Stop delaying the catchable fatal signals. */
+extern void unblock_fatal_signals (void);
+
+
+#ifdef __cplusplus
+}
+#endif
+2003-10-06 Bruno Haible <bruno@clisp.org>
+
+ * fatal-signal.m4: New file.
+ * signalblocking.m4: New file, from GNU gettext.
+
2003-09-27 Paul Eggert <eggert@twinsun.com>
* free.m4: New file.
--- /dev/null
+# fatal-signal.m4 serial 1
+dnl Copyright (C) 2003 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+AC_DEFUN([gl_FATAL_SIGNAL],
+[
+ AC_REQUIRE([gt_SIGNALBLOCKING])
+ AC_CHECK_HEADERS_ONCE(unistd.h)
+ AC_CHECK_FUNCS(raise)
+])
--- /dev/null
+# signalblocking.m4 serial 1 (gettext-0.11)
+dnl Copyright (C) 2001-2002 Free Software Foundation, Inc.
+dnl This file is free software, distributed under the terms of the GNU
+dnl General Public License. As a special exception to the GNU General
+dnl Public License, this file may be distributed as part of a program
+dnl that contains a configuration script generated by Autoconf, under
+dnl the same distribution terms as the rest of that program.
+
+# Determine available signal blocking primitives. Three different APIs exist:
+# 1) POSIX: sigemptyset, sigaddset, sigprocmask
+# 2) SYSV: sighold, sigrelse
+# 3) BSD: sigblock, sigsetmask
+# For simplicity, here we check only for the POSIX signal blocking.
+AC_DEFUN([gt_SIGNALBLOCKING],
+[
+ signals_not_posix=
+ AC_EGREP_HEADER(sigset_t, signal.h, , signals_not_posix=1)
+ if test -z "$signals_not_posix"; then
+ AC_CHECK_FUNC(sigprocmask,
+ AC_DEFINE(HAVE_POSIX_SIGNALBLOCKING, 1,
+ [Define to 1 if you have the sigset_t type and the sigprocmask function.]))
+ fi
+])
--- /dev/null
+Description:
+Emergency actions in case of a fatal signal.
+
+Files:
+lib/fatal-signal.h
+lib/fatal-signal.c
+m4/fatal-signal.m4
+m4/signalblocking.m4
+
+Depends-on:
+xalloc
+stdbool
+
+configure.ac:
+gl_FATAL_SIGNAL
+
+Makefile.am:
+lib_SOURCES += fatal-signal.h fatal-signal.c
+
+Include:
+"fatal-signal.h"
+
+Maintainer:
+Bruno Haible
+