pthread_sigmask: Work around IRIX bug.
authorBruno Haible <bruno@clisp.org>
Fri, 8 Jul 2011 23:37:58 +0000 (01:37 +0200)
committerBruno Haible <bruno@clisp.org>
Fri, 8 Jul 2011 23:37:58 +0000 (01:37 +0200)
* m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Test for the IRIX
bug.
* lib/pthread_sigmask.c (pthread_sigmask): usleep for some time when
there may be unblocked pending signals.
* doc/posix-functions/pthread_sigmask.texi: Mention the IRIX bug.

ChangeLog
doc/posix-functions/pthread_sigmask.texi
lib/pthread_sigmask.c
m4/pthread_sigmask.m4

index cebc6f627af8276032bef990a4e379604e992abe..cb12185916e96bd3668d9383ff15c51a26938a01 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2011-07-08  Bruno Haible  <bruno@clisp.org>
+
+       pthread_sigmask: Work around IRIX bug.
+       * m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Test for the IRIX
+       bug.
+       * lib/pthread_sigmask.c (pthread_sigmask): usleep for some time when
+       there may be unblocked pending signals.
+       * doc/posix-functions/pthread_sigmask.texi: Mention the IRIX bug.
+
 2011-07-08  Bruno Haible  <bruno@clisp.org>
 
        pthread_sigmask: Work around Cygwin bug.
index 58b6295827150167bfac8802f8326e92239ea858..10d7a945ed795d3bea9c7f72b403d9896f87b17f 100644 (file)
@@ -23,6 +23,10 @@ FreeBSD 6.4, HP-UX 11.31, Solaris 9.
 When it fails, this functions returns -1 instead of the error number on
 some platforms:
 Cygwin 1.7.5.
+@item
+This function does not immediately raise signals that were pending before
+the call and unblocked by the call on some platforms:
+IRIX 6.5.
 @end itemize
 
 Portability problems not fixed by Gnulib:
index 06ee7fc42042bf09d061db6c2caa76e593ad6225..349f7ad5c26bb8aa39f37f749278cee020a92670 100644 (file)
@@ -46,6 +46,16 @@ pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask)
 # if PTHREAD_SIGMASK_FAILS_WITH_ERRNO
   if (ret == -1)
     return errno;
+# endif
+# if PTHREAD_SIGMASK_UNBLOCK_BUG
+  if (ret == 0
+      && new_mask != NULL
+      && (how == SIG_UNBLOCK || how == SIG_SETMASK))
+    {
+      /* Give the OS the opportunity to raise signals that were pending before
+         the pthread_sigmask call and have now been unblocked.  */
+      usleep (1);
+    }
 # endif
   return ret;
 #else
index c65a4ce3507cd71553a15f226137dece2c686d21..c73e7e6ec68781e78c08b9ef0aed541e55afa5d3 100644 (file)
@@ -1,4 +1,4 @@
-# pthread_sigmask.m4 serial 8
+# pthread_sigmask.m4 serial 9
 dnl Copyright (C) 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,
@@ -115,7 +115,7 @@ changequote([,])dnl
         *no)
           REPLACE_PTHREAD_SIGMASK=1
           AC_DEFINE([PTHREAD_SIGMASK_INEFFECTIVE], [1],
-            [Define to 1 if pthread_mask() may returns 0 and have no effect.])
+            [Define to 1 if pthread_sigmask() may returns 0 and have no effect.])
           ;;
       esac
     fi
@@ -155,10 +155,74 @@ int main ()
       *no)
         REPLACE_PTHREAD_SIGMASK=1
         AC_DEFINE([PTHREAD_SIGMASK_FAILS_WITH_ERRNO], [1],
-          [Define to 1 if pthread_mask(), when it fails, returns -1 and sets errno.])
+          [Define to 1 if pthread_sigmask(), when it fails, returns -1 and sets errno.])
         ;;
     esac
 
+    dnl On IRIX 6.5, in a single-threaded program, pending signals are not
+    dnl immediately delivered when they are unblocked through pthread_sigmask,
+    dnl only a little while later.
+    AC_CACHE_CHECK([whether pthread_sigmask unblocks signals correctly],
+      [gl_cv_func_pthread_sigmask_unblock_works],
+      [
+        case "$host_os" in
+          irix*)
+            gl_cv_func_pthread_sigmask_unblock_works="guessing no";;
+          *)
+            gl_cv_func_pthread_sigmask_unblock_works="guessing yes";;
+        esac
+        dnl Here we link against $LIBMULTITHREAD, not only $LIB_PTHREAD_SIGMASK,
+        dnl otherwise we get a false positive on those platforms where
+        dnl $gl_cv_func_pthread_sigmask_in_libc_works is "no".
+        gl_save_LIBS="$LIBS"
+        LIBS="$LIBS $LIBMULTITHREAD"
+        AC_RUN_IFELSE(
+          [AC_LANG_SOURCE([[
+#include <pthread.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+static volatile int sigint_occurred;
+static void
+sigint_handler (int sig)
+{
+  sigint_occurred++;
+}
+int main ()
+{
+  sigset_t set;
+  int pid = getpid ();
+  char command[80];
+  signal (SIGINT, sigint_handler);
+  sigemptyset (&set);
+  sigaddset (&set, SIGINT);
+  if (!(pthread_sigmask (SIG_BLOCK, &set, NULL) == 0))
+    return 1;
+  sprintf (command, "sh -c 'sleep 1; kill -%d %d' &", SIGINT, pid);
+  if (!(system (command) == 0))
+    return 2;
+  sleep (2);
+  if (!(sigint_occurred == 0))
+    return 3;
+  if (!(pthread_sigmask (SIG_UNBLOCK, &set, NULL) == 0))
+    return 4;
+  if (!(sigint_occurred == 1)) /* This fails on IRIX.  */
+    return 5;
+  return 0;
+}]])],
+          [:],
+          [gl_cv_func_pthread_sigmask_unblock_works=no],
+          [:])
+        LIBS="$gl_save_LIBS"
+      ])
+    case "$gl_cv_func_pthread_sigmask_unblock_works" in
+      *no)
+        REPLACE_PTHREAD_SIGMASK=1
+        AC_DEFINE([PTHREAD_SIGMASK_UNBLOCK_BUG], [1],
+          [Define to 1 if pthread_sigmask() unblocks signals incorrectly.])
+        ;;
+    esac
   fi
 ])