From: Bruno Haible Date: Fri, 8 Jul 2011 23:37:58 +0000 (+0200) Subject: pthread_sigmask: Work around IRIX bug. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=29090434bf92407bb16b21e66a2bd5d36e1e7bd4;p=pspp 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. --- diff --git a/ChangeLog b/ChangeLog index cebc6f627a..cb12185916 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-07-08 Bruno Haible + + 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 pthread_sigmask: Work around 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 @@ -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 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 +#include +#include +#include +#include +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 ])