diff options
author | Bruno Haible <bruno@clisp.org> | 2008-09-26 13:25:57 +0200 |
---|---|---|
committer | Bruno Haible <bruno@clisp.org> | 2008-09-26 13:44:51 +0200 |
commit | b5298eb7a71c5ae0a2320a99dd3965ef8df33648 (patch) | |
tree | 1701a50a98d9e437b514d1da5ddf17298091477c | |
parent | 1d569ca4e7e6147793e6e6510e5a36a4139b2f31 (diff) | |
download | gnulib-b5298eb7a71c5ae0a2320a99dd3965ef8df33648.tar.gz |
Support signal handling with SIGPIPE on native Windows platforms.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | doc/posix-headers/signal.texi | 8 | ||||
-rw-r--r-- | lib/signal.in.h | 21 | ||||
-rw-r--r-- | lib/sigprocmask.c | 51 | ||||
-rw-r--r-- | m4/signal_h.m4 | 3 | ||||
-rw-r--r-- | modules/signal | 1 |
6 files changed, 91 insertions, 3 deletions
@@ -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' \ |