summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2011-07-09 00:27:00 +0200
committerBruno Haible <bruno@clisp.org>2011-07-09 00:35:45 +0200
commit2616a6587c4240184112fdd18d164227824a32f0 (patch)
treecce6d3c3eac69f86a31e9aab9c268ba4ae20b7fb
parentb80db060001e52a487a0502a6258156cbeea2a8a (diff)
downloadgnulib-2616a6587c4240184112fdd18d164227824a32f0.tar.gz
pthread_sigmask: Work around bug in single-threaded implementation.
* m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Test for the FreeBSD, HP-UX, Solaris bug. (gl_PREREQ_PTHREAD_SIGMASK): New macro. * lib/pthread_sigmask.c: Include <stddef.h>. (pthread_sigmask): If HAVE_PTHREAD_SIGMASK, define as a wrapper around the system's pthread_sigmask function. * modules/pthread_sigmask (configure.ac): Invoke gl_PREREQ_PTHREAD_SIGMASK. * doc/posix-functions/pthread_sigmask.texi: Mention bug on FreeBSD, HP-UX, Solaris.
-rw-r--r--ChangeLog14
-rw-r--r--doc/posix-functions/pthread_sigmask.texi4
-rw-r--r--lib/pthread_sigmask.c22
-rw-r--r--m4/pthread_sigmask.m457
-rw-r--r--modules/pthread_sigmask1
5 files changed, 97 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index ade65398de..80ae091b79 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2011-07-08 Bruno Haible <bruno@clisp.org>
+
+ pthread_sigmask: Work around bug in single-threaded implementation.
+ * m4/pthread_sigmask.m4 (gl_FUNC_PTHREAD_SIGMASK): Test for the
+ FreeBSD, HP-UX, Solaris bug.
+ (gl_PREREQ_PTHREAD_SIGMASK): New macro.
+ * lib/pthread_sigmask.c: Include <stddef.h>.
+ (pthread_sigmask): If HAVE_PTHREAD_SIGMASK, define as a wrapper around
+ the system's pthread_sigmask function.
+ * modules/pthread_sigmask (configure.ac): Invoke
+ gl_PREREQ_PTHREAD_SIGMASK.
+ * doc/posix-functions/pthread_sigmask.texi: Mention bug on FreeBSD,
+ HP-UX, Solaris.
+
2011-07-08 Eric Blake <eblake@redhat.com>
test-sigprocmask: avoid compiler warning
diff --git a/doc/posix-functions/pthread_sigmask.texi b/doc/posix-functions/pthread_sigmask.texi
index 1bd24e599d..62f0a761cd 100644
--- a/doc/posix-functions/pthread_sigmask.texi
+++ b/doc/posix-functions/pthread_sigmask.texi
@@ -15,6 +15,10 @@ Solaris 2.4, mingw, BeOS.
This function is declared in @code{<pthread.h>} instead of @code{<signal.h>}
on some platforms:
MacOS X 10.3, FreeBSD 6.4, OpenBSD 3.8, OSF/1 4.0, Solaris 2.6.
+@item
+This function does nothing and always returns 0 in programs that are not
+linked with @code{-lpthread} on some platforms:
+FreeBSD 6.4, HP-UX 11.31, Solaris 9.
@end itemize
Portability problems not fixed by Gnulib:
diff --git a/lib/pthread_sigmask.c b/lib/pthread_sigmask.c
index 1f460f13c4..b53b15dd71 100644
--- a/lib/pthread_sigmask.c
+++ b/lib/pthread_sigmask.c
@@ -20,10 +20,32 @@
#include <signal.h>
#include <errno.h>
+#include <stddef.h>
int
pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask)
+#undef pthread_sigmask
{
+#if HAVE_PTHREAD_SIGMASK
+ int ret = pthread_sigmask (how, new_mask, old_mask);
+# if PTHREAD_SIGMASK_INEFFECTIVE
+ if (ret == 0)
+ {
+ /* Detect whether pthread_sigmask is currently ineffective.
+ Don't cache the information: libpthread.so could be dynamically
+ loaded after the program started and after pthread_sigmask was
+ called for the first time. */
+ if (pthread_sigmask (1729, NULL, NULL) == 0)
+ {
+ /* pthread_sigmask is currently ineffective. The program is not
+ linked to -lpthread. So use sigprocmask instead. */
+ return (sigprocmask (how, new_mask, old_mask) < 0 ? errno : 0);
+ }
+ }
+# endif
+ return ret;
+#else
int ret = sigprocmask (how, new_mask, old_mask);
return (ret < 0 ? errno : 0);
+#endif
}
diff --git a/m4/pthread_sigmask.m4 b/m4/pthread_sigmask.m4
index dfa0f660a7..f8b3e8a416 100644
--- a/m4/pthread_sigmask.m4
+++ b/m4/pthread_sigmask.m4
@@ -1,4 +1,4 @@
-# pthread_sigmask.m4 serial 7
+# pthread_sigmask.m4 serial 8
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,
@@ -74,4 +74,59 @@ AC_DEFUN([gl_FUNC_PTHREAD_SIGMASK],
dnl We don't need a variable LTLIB_PTHREAD_SIGMASK, because when
dnl "$gl_threads_api" = posix, $LTLIBMULTITHREAD and $LIBMULTITHREAD are the
dnl same: either both empty or both "-lpthread".
+
+ dnl Now test for some bugs in the system function.
+ if test $HAVE_PTHREAD_SIGMASK = 1; then
+ AC_REQUIRE([AC_PROG_CC])
+ AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+
+ dnl On FreeBSD 6.4, HP-UX 11.31, Solaris 9, in programs that are not linked
+ dnl with -lpthread, the pthread_sigmask() function always returns 0 and has
+ dnl no effect.
+ if test -z "$LIB_PTHREAD_SIGMASK"; then
+ AC_CACHE_CHECK([whether pthread_sigmask works without -lpthread],
+ [gl_cv_func_pthread_sigmask_in_libc_works],
+ [
+ AC_RUN_IFELSE(
+ [AC_LANG_SOURCE([[
+#include <pthread.h>
+#include <signal.h>
+#include <stddef.h>
+int main ()
+{
+ sigset_t set;
+ sigemptyset (&set);
+ return pthread_sigmask (1729, &set, NULL) != 0;
+}]])],
+ [gl_cv_func_pthread_sigmask_in_libc_works=no],
+ [gl_cv_func_pthread_sigmask_in_libc_works=yes],
+ [
+changequote(,)dnl
+ case "$host_os" in
+ freebsd* | hpux* | solaris | solaris2.[2-9]*)
+ gl_cv_func_pthread_sigmask_in_libc_works="guessing no";;
+ *)
+ gl_cv_func_pthread_sigmask_in_libc_works="guessing yes";;
+ esac
+changequote([,])dnl
+ ])
+ ])
+ case "$gl_cv_func_pthread_sigmask_in_libc_works" in
+ *no)
+ REPLACE_PTHREAD_SIGMASK=1
+ AC_DEFINE([PTHREAD_SIGMASK_INEFFECTIVE], [1],
+ [Define to 1 if pthread_mask() may returns 0 and have no effect.])
+ ;;
+ esac
+ fi
+ fi
+])
+
+# Prerequisite of lib/pthread_sigmask.c.
+AC_DEFUN([gl_PREREQ_PTHREAD_SIGMASK],
+[
+ if test $HAVE_PTHREAD_SIGMASK = 1; then
+ AC_DEFINE([HAVE_PTHREAD_SIGMASK], [1],
+ [Define to 1 if the pthread_sigmask function can be used (despite bugs).])
+ fi
])
diff --git a/modules/pthread_sigmask b/modules/pthread_sigmask
index 087c1589bc..9e26e1309d 100644
--- a/modules/pthread_sigmask
+++ b/modules/pthread_sigmask
@@ -13,6 +13,7 @@ configure.ac:
gl_FUNC_PTHREAD_SIGMASK
if test $HAVE_PTHREAD_SIGMASK = 0 || test $REPLACE_PTHREAD_SIGMASK = 1; then
AC_LIBOBJ([pthread_sigmask])
+ gl_PREREQ_PTHREAD_SIGMASK
fi
gl_SIGNAL_MODULE_INDICATOR([pthread_sigmask])