summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2008-09-26 13:25:57 +0200
committerBruno Haible <bruno@clisp.org>2008-09-26 13:44:51 +0200
commitb5298eb7a71c5ae0a2320a99dd3965ef8df33648 (patch)
tree1701a50a98d9e437b514d1da5ddf17298091477c
parent1d569ca4e7e6147793e6e6510e5a36a4139b2f31 (diff)
downloadgnulib-b5298eb7a71c5ae0a2320a99dd3965ef8df33648.tar.gz
Support signal handling with SIGPIPE on native Windows platforms.
-rw-r--r--ChangeLog10
-rw-r--r--doc/posix-headers/signal.texi8
-rw-r--r--lib/signal.in.h21
-rw-r--r--lib/sigprocmask.c51
-rw-r--r--m4/signal_h.m43
-rw-r--r--modules/signal1
6 files changed, 91 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index 2ee1db36e7..4c814825d8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,16 @@
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.
diff --git a/doc/posix-headers/signal.texi b/doc/posix-headers/signal.texi
index 924408992f..d9c2e5a1b0 100644
--- a/doc/posix-headers/signal.texi
+++ b/doc/posix-headers/signal.texi
@@ -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
diff --git a/lib/signal.in.h b/lib/signal.in.h
index fce94f31c9..4df1567c92 100644
--- a/lib/signal.in.h
+++ b/lib/signal.in.h
@@ -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@
diff --git a/lib/sigprocmask.c b/lib/sigprocmask.c
index d6daca6ae2..7f73f951c1 100644
--- a/lib/sigprocmask.c
+++ b/lib/sigprocmask.c
@@ -45,6 +45,31 @@
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
diff --git a/m4/signal_h.m4 b/m4/signal_h.m4
index 0a10547089..4ac2e04621 100644
--- a/m4/signal_h.m4
+++ b/m4/signal_h.m4
@@ -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.
diff --git a/modules/signal b/modules/signal
index b472fb4e19..7562a8b7e6 100644
--- a/modules/signal
+++ b/modules/signal
@@ -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' \