diff options
| author | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-12-03 20:50:11 +0100 | 
|---|---|---|
| committer | Jörg Frings-Fürst <debian@jff-webhosting.net> | 2017-12-03 20:50:11 +0100 | 
| commit | 4cf52fc0bc3b80c0ef6c58c5db4413ebdafe661c (patch) | |
| tree | 676b26b024117cf656080a011e3d17b8fb6889af /tests/pthread_sigmask.c | |
| parent | 1ecbfbb92248e67b564f5b144c4671ccaa86ee2f (diff) | |
| parent | 44ff3127b1e57b703c2a73a24f7ab38e4aad8ae4 (diff) | |
Merge branch 'release/0.9.8-1'0.9.8-1
Diffstat (limited to 'tests/pthread_sigmask.c')
| -rw-r--r-- | tests/pthread_sigmask.c | 92 | 
1 files changed, 92 insertions, 0 deletions
| diff --git a/tests/pthread_sigmask.c b/tests/pthread_sigmask.c new file mode 100644 index 00000000..9ccf89b5 --- /dev/null +++ b/tests/pthread_sigmask.c @@ -0,0 +1,92 @@ +/* POSIX compatible signal blocking for threads. +   Copyright (C) 2011-2017 Free Software Foundation, Inc. + +   This program is free software: you can redistribute it and/or modify +   it under the terms of the GNU General Public License as published by +   the Free Software Foundation; either version 3 of the License, or +   (at your option) any later version. + +   This program is distributed in the hope that it will be useful, +   but WITHOUT ANY WARRANTY; without even the implied warranty of +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the +   GNU General Public License for more details. + +   You should have received a copy of the GNU General Public License +   along with this program.  If not, see <https://www.gnu.org/licenses/>.  */ + +#include <config.h> + +/* Specification.  */ +#include <signal.h> + +#include <errno.h> +#include <stddef.h> + +#if PTHREAD_SIGMASK_INEFFECTIVE +# include <string.h> +#endif + +#if PTHREAD_SIGMASK_UNBLOCK_BUG +# include <unistd.h> +#endif + +int +pthread_sigmask (int how, const sigset_t *new_mask, sigset_t *old_mask) +#undef pthread_sigmask +{ +#if HAVE_PTHREAD_SIGMASK +  int ret; + +# if PTHREAD_SIGMASK_INEFFECTIVE +  sigset_t omask, omask_copy; +  sigset_t *old_mask_ptr = &omask; +  sigemptyset (&omask); +  /* Add a signal unlikely to be blocked, so that OMASK_COPY +     is unlikely to match the actual mask.  */ +  sigaddset (&omask, SIGILL); +  memcpy (&omask_copy, &omask, sizeof omask); +# else +  sigset_t *old_mask_ptr = old_mask; +# endif + +  ret = pthread_sigmask (how, new_mask, old_mask_ptr); + +# 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 (memcmp (&omask_copy, &omask, sizeof omask) == 0 +          && pthread_sigmask (1729, &omask_copy, 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); +        } + +      if (old_mask) +        memcpy (old_mask, &omask, sizeof omask); +    } +# endif +# 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 +  int ret = sigprocmask (how, new_mask, old_mask); +  return (ret < 0 ? errno : 0); +#endif +} | 
