summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-07-09 01:37:58 +0200
committerBruno Haible <bruno@clisp.org>2011-07-09 01:37:58 +0200
commit29090434bf92407bb16b21e66a2bd5d36e1e7bd4 (patch)
tree0b26a02c6b0c937a3b8cb404b0d13cf08727db99
parent43243b5fdcf1e0c0e016cabe190f1ab29b984871 (diff)
downloadgnulib-29090434bf92407bb16b21e66a2bd5d36e1e7bd4.tar.gz
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.
-rw-r--r--ChangeLog9
-rw-r--r--doc/posix-functions/pthread_sigmask.texi4
-rw-r--r--lib/pthread_sigmask.c10
-rw-r--r--m4/pthread_sigmask.m470
4 files changed, 90 insertions, 3 deletions
diff --git a/ChangeLog b/ChangeLog
index cebc6f627a..cb12185916 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
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.
* m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Test for the Cygwin
bug.
diff --git a/doc/posix-functions/pthread_sigmask.texi b/doc/posix-functions/pthread_sigmask.texi
index 58b6295827..10d7a945ed 100644
--- a/doc/posix-functions/pthread_sigmask.texi
+++ b/doc/posix-functions/pthread_sigmask.texi
@@ -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:
diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c
index 06ee7fc420..349f7ad5c2 100644
--- a/lib/pthread_sigmask.c
+++ b/lib/pthread_sigmask.c
@@ -47,6 +47,16 @@ pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask)
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
int ret = sigprocmask (how, new_mask, old_mask);
diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4
index c65a4ce350..c73e7e6ec6 100644
--- a/m4/pthread_sigmask.m4
+++ b/m4/pthread_sigmask.m4
@@ -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
])