Support signal handling with SIGPIPE on native Windows platforms.
authorBruno Haible <bruno@clisp.org>
Fri, 26 Sep 2008 11:25:57 +0000 (13:25 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 26 Sep 2008 11:44:51 +0000 (13:44 +0200)
ChangeLog
doc/posix-headers/signal.texi
lib/signal.in.h
lib/sigprocmask.c
m4/signal_h.m4
modules/signal

index 2ee1db36e75ac7266084ca5defe8afe13725bfae..4c814825d8d1b201c1e19fad061f05a872f72dfd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
 
 2008-09-26  Bruno Haible  <bruno@clisp.org>
 
+       * lib/signal.in.h (SIGPIPE): Define to a replacement value.
+       (raise): New declaration.
+       * lib/sigprocmask.c (SIGPIPE_handler): New variable.
+       (ext_signal): New function.
+       (rpl_raise): New function.
+       * m4/signal_h.m4 (gl_SIGNAL_H_DEFAULTS): Initialize
+       GNULIB_SIGNAL_H_SIGPIPE.
+       * modules/signal (Makefile.am): Substitute GNULIB_SIGNAL_H_SIGPIPE.
+       * doc/posix-headers/signal.texi: Mention the SIGPIPE issue.
+
        * modules/sigpipe: New file.
        * m4/sigpipe.m4: New file.
 
index 924408992f0fbe657f9b1f9f83745f0b4b068c41..d9c2e5a1b0e7577ba706579db51238d5f86f2197 100644 (file)
@@ -10,18 +10,22 @@ Portability problems fixed by Gnulib:
 @item
 @code{sigset_t} is only declared in <sys/types.h> on some platforms:
 mingw.
-
 @item
 @code{struct sigaction} and @code{siginfo_t} are missing on some
 platforms:
 mingw.
-
 @item
 @code{struct sigaction} lacks the @code{sa_sigaction} member on some
 platforms:
 Irix 5.3, Interix 3.5.
+@item
+The signal @code{SIGPIPE} is not defined on some platforms:
+mingw.
 @end itemize
 
 Portability problems not fixed by Gnulib:
 @itemize
+@item
+Many signals are not defined on some platforms:
+mingw.
 @end itemize
index fce94f31c90821456eb226cbd811b912ece34be5..4df1567c92bdd5730ef5e69150fa8136c798a1bb 100644 (file)
@@ -44,6 +44,17 @@ extern "C" {
 #endif
 
 
+#if @GNULIB_SIGNAL_H_SIGPIPE@
+# ifndef SIGPIPE
+/* Define SIGPIPE to a value that does not overlap with other signals.  */
+#  define SIGPIPE 13
+#  define GNULIB_defined_SIGPIPE 1
+/* To actually use SIGPIPE, you also need the gnulib modules 'sigprocmask',
+   'write', 'stdio'.  */
+# endif
+#endif
+
+
 #if !@HAVE_POSIX_SIGNALBLOCKING@
 
 /* Maximum signal number + 1.  */
@@ -92,8 +103,18 @@ extern int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set);
    handler.  */
 extern void (*signal (int sig, void (*func) (int))) (int);
 
+# if GNULIB_defined_SIGPIPE
+
+/* Raise signal SIG.  */
+#  undef raise
+#  define raise rpl_raise
+extern int raise (int sig);
+
+# endif
+
 #endif /* !@HAVE_POSIX_SIGNALBLOCKING@ */
 
+
 #if !@HAVE_SIGACTION@
 
 # if !@HAVE_SIGINFO_T@
index d6daca6ae2157b713efed0e0ea4f5b75d8a8a498..7f73f951c1e4bc345974a0075371d3c72a5635d9 100644 (file)
 
 typedef void (*handler_t) (int);
 
+/* Handling of gnulib defined signals.  */
+
+#if GNULIB_defined_SIGPIPE
+static handler_t SIGPIPE_handler = SIG_DFL;
+#endif
+
+#if GNULIB_defined_SIGPIPE
+static handler_t
+ext_signal (int sig, handler_t handler)
+{
+  switch (sig)
+    {
+    case SIGPIPE:
+      {
+       handler_t old_handler = SIGPIPE_handler;
+       SIGPIPE_handler = handler;
+       return old_handler;
+      }
+    default: /* System defined signal */
+      return signal (sig, handler);
+    }
+}
+# define signal ext_signal
+#endif
+
 int
 sigismember (const sigset_t *set, int sig)
 {
@@ -240,3 +265,29 @@ rpl_signal (int sig, handler_t handler)
       return SIG_ERR;
     }
 }
+
+#if GNULIB_defined_SIGPIPE
+/* Raise the signal SIG.  */
+int
+rpl_raise (int sig)
+# undef raise
+{
+  switch (sig)
+    {
+    case SIGPIPE:
+      if (blocked_set & (1U << sig))
+       pending_array[sig] = 1;
+      else
+       {
+         handler_t handler = SIGPIPE_handler;
+         if (handler == SIG_DFL)
+           exit (128 + SIGPIPE);
+         else if (handler != SIG_IGN)
+           (*handler) (sig);
+       }
+      return 0;
+    default: /* System defined signal */
+      return raise (sig);
+    }
+}
+#endif
index 0a105470890825df9d08b82a56e4541369823181..4ac2e046219c3b85dd92fc2cffeedae3bee0d649 100644 (file)
@@ -1,4 +1,4 @@
-# signal_h.m4 serial 5
+# signal_h.m4 serial 6
 dnl Copyright (C) 2007, 2008 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -19,6 +19,7 @@ AC_DEFUN([gl_SIGNAL_MODULE_INDICATOR],
 
 AC_DEFUN([gl_SIGNAL_H_DEFAULTS],
 [
+  GNULIB_SIGNAL_H_SIGPIPE=0;   AC_SUBST([GNULIB_SIGNAL_H_SIGPIPE])
   GNULIB_SIGPROCMASK=0;        AC_SUBST([GNULIB_SIGPROCMASK])
   GNULIB_SIGACTION=0;          AC_SUBST([GNULIB_SIGACTION])
   dnl Assume proper GNU behavior unless another module says otherwise.
index b472fb4e199d070b543b861162cbf3aaf18be47e..7562a8b7e66645a62f3d5708712ccc57951cb5dd 100644 (file)
@@ -23,6 +23,7 @@ signal.h: signal.in.h
          sed -e 's|@''INCLUDE_NEXT''@|$(INCLUDE_NEXT)|g' \
              -e 's|@''PRAGMA_SYSTEM_HEADER''@|@PRAGMA_SYSTEM_HEADER@|g' \
              -e 's|@''NEXT_SIGNAL_H''@|$(NEXT_SIGNAL_H)|g' \
+             -e 's|@''GNULIB_SIGNAL_H_SIGPIPE''@|$(GNULIB_SIGNAL_H_SIGPIPE)|g' \
              -e 's|@''GNULIB_SIGPROCMASK''@|$(GNULIB_SIGPROCMASK)|g' \
              -e 's|@''GNULIB_SIGACTION''@|$(GNULIB_SIGACTION)|g' \
              -e 's|@''HAVE_POSIX_SIGNALBLOCKING''@|$(HAVE_POSIX_SIGNALBLOCKING)|g' \