changeset 15757:a27be0e3ac06

sigprocmask: Avoid crashes through signal() on MSVC 9. * lib/sigprocmask.c: Include msvc-inval.h. (signal_nothrow): New function. (signal): Redefine it. * m4/signalblocking.m4 (gl_PREREQ_SIGPROCMASK): Require AC_C_INLINE. * modules/sigprocmask (Depends-on): Add msvc-inval. * doc/posix-functions/signal.texi: Mention the problem on MSVC.
author Bruno Haible <bruno@clisp.org>
date Sat, 24 Sep 2011 01:07:22 +0200
parents 6efe9315fa03
children 51a803e5cfdc
files ChangeLog doc/posix-functions/signal.texi lib/sigprocmask.c m4/signalblocking.m4 modules/sigprocmask
diffstat 5 files changed, 43 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2011-09-23  Bruno Haible  <bruno@clisp.org>
+
+	sigprocmask: Avoid crashes through signal() on MSVC 9.
+	* lib/sigprocmask.c: Include msvc-inval.h.
+	(signal_nothrow): New function.
+	(signal): Redefine it.
+	* m4/signalblocking.m4 (gl_PREREQ_SIGPROCMASK): Require AC_C_INLINE.
+	* modules/sigprocmask (Depends-on): Add msvc-inval.
+	* doc/posix-functions/signal.texi: Mention the problem on MSVC.
+
 2011-09-23  Bruno Haible  <bruno@clisp.org>
 
 	Tests for module 'raise'.
--- a/doc/posix-functions/signal.texi
+++ b/doc/posix-functions/signal.texi
@@ -13,6 +13,9 @@
 Portability problems not fixed by Gnulib:
 @itemize
 @item
+This function crashes when invoked with invalid arguments on some platforms:
+MSVC 9.
+@item
 On System V platforms, when the signal is triggered, the kernel uninstalls the
 handler (i.e.@: resets the signal's action to SIG_DFL) before invoking the
 handler.  This opens the door to race conditions: undesired things happen
--- a/lib/sigprocmask.c
+++ b/lib/sigprocmask.c
@@ -24,6 +24,8 @@
 #include <stdint.h>
 #include <stdlib.h>
 
+#include "msvc-inval.h"
+
 /* We assume that a platform without POSIX signal blocking functions
    also does not have the POSIX sigaction() function, only the
    signal() function.  We also assume signal() has SysV semantics,
@@ -58,6 +60,28 @@
 
 typedef void (*handler_t) (int);
 
+#if HAVE_MSVC_INVALID_PARAMETER_HANDLER
+static inline handler_t
+signal_nothrow (int sig, handler_t handler)
+{
+  handler_t result;
+
+  TRY_MSVC_INVAL
+    {
+      result = signal (sig, handler);
+    }
+  CATCH_MSVC_INVAL
+    {
+      result = SIG_ERR;
+      errno = EINVAL;
+    }
+  DONE_MSVC_INVAL;
+
+  return result;
+}
+# define signal signal_nothrow
+#endif
+
 /* Handling of gnulib defined signals.  */
 
 #if GNULIB_defined_SIGPIPE
@@ -80,6 +104,7 @@
       return signal (sig, handler);
     }
 }
+# undef signal
 # define signal ext_signal
 #endif
 
--- a/m4/signalblocking.m4
+++ b/m4/signalblocking.m4
@@ -1,4 +1,4 @@
-# signalblocking.m4 serial 12
+# signalblocking.m4 serial 13
 dnl Copyright (C) 2001-2002, 2006-2011 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -22,4 +22,6 @@
 ])
 
 # Prerequisites of lib/sigprocmask.c.
-AC_DEFUN([gl_PREREQ_SIGPROCMASK], [:])
+AC_DEFUN([gl_PREREQ_SIGPROCMASK], [
+  AC_REQUIRE([AC_C_INLINE])
+])
--- a/modules/sigprocmask
+++ b/modules/sigprocmask
@@ -9,6 +9,7 @@
 signal
 stdint          [test $HAVE_POSIX_SIGNALBLOCKING = 0]
 raise           [test $HAVE_POSIX_SIGNALBLOCKING = 0]
+msvc-inval      [test $HAVE_POSIX_SIGNALBLOCKING = 0]
 
 configure.ac:
 gl_SIGNALBLOCKING