diff options
Diffstat (limited to 'tests/sigprocmask.c')
| -rw-r--r-- | tests/sigprocmask.c | 58 |
1 files changed, 33 insertions, 25 deletions
diff --git a/tests/sigprocmask.c b/tests/sigprocmask.c index 3df69b51..2399f58e 100644 --- a/tests/sigprocmask.c +++ b/tests/sigprocmask.c @@ -1,5 +1,5 @@ /* POSIX compatible signal blocking. - Copyright (C) 2006-2024 Free Software Foundation, Inc. + Copyright (C) 2006-2026 Free Software Foundation, Inc. Written by Bruno Haible <bruno@clisp.org>, 2006. This file is free software: you can redistribute it and/or modify @@ -24,6 +24,8 @@ #include <stdint.h> #include <stdlib.h> +#include "glthread/lock.h" + #if HAVE_MSVC_INVALID_PARAMETER_HANDLER # include "msvc-inval.h" #endif @@ -84,6 +86,10 @@ signal_nothrow (int sig, handler_t handler) # define signal signal_nothrow #endif +/* This lock protects the variables defined in this file from concurrent + modification in multiple threads. */ +gl_lock_define_initialized(static, sig_lock) + /* Handling of gnulib defined signals. */ #if GNULIB_defined_SIGPIPE @@ -182,7 +188,7 @@ sigfillset (sigset_t *set) } /* Set of currently blocked signals. */ -static volatile sigset_t blocked_set /* = 0 */; +static sigset_t blocked_set /* = 0 */; /* Set of currently blocked and pending signals. */ static volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; @@ -205,11 +211,10 @@ int sigpending (sigset_t *set) { sigset_t pending = 0; - int sig; - - for (sig = 0; sig < NSIG; sig++) + for (int sig = 0; sig < NSIG; sig++) if (pending_array[sig]) pending |= 1U << sig; + *set = pending; return 0; } @@ -221,15 +226,14 @@ static volatile handler_t old_handlers[NSIG]; int sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) { + gl_lock_lock (sig_lock); + if (old_set != NULL) *old_set = blocked_set; if (set != NULL) { sigset_t new_blocked_set; - sigset_t to_unblock; - sigset_t to_block; - switch (operation) { case SIG_BLOCK: @@ -242,31 +246,28 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) new_blocked_set = blocked_set & ~*set; break; default: + gl_lock_unlock (sig_lock); errno = EINVAL; return -1; } - to_unblock = blocked_set & ~new_blocked_set; - to_block = new_blocked_set & ~blocked_set; - if (to_block != 0) - { - int sig; + sigset_t to_unblock = blocked_set & ~new_blocked_set; + sigset_t to_block = new_blocked_set & ~blocked_set; - for (sig = 0; sig < NSIG; sig++) - if ((to_block >> sig) & 1) - { - pending_array[sig] = 0; - if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) - blocked_set |= 1U << sig; - } - } + if (to_block != 0) + for (int sig = 0; sig < NSIG; sig++) + if ((to_block >> sig) & 1) + { + pending_array[sig] = 0; + if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) + blocked_set |= 1U << sig; + } if (to_unblock != 0) { sig_atomic_t received[NSIG]; - int sig; - for (sig = 0; sig < NSIG; sig++) + for (int sig = 0; sig < NSIG; sig++) if ((to_unblock >> sig) & 1) { if (signal (sig, old_handlers[sig]) != blocked_handler) @@ -281,11 +282,13 @@ sigprocmask (int operation, const sigset_t *set, sigset_t *old_set) else received[sig] = 0; - for (sig = 0; sig < NSIG; sig++) + for (int sig = 0; sig < NSIG; sig++) if (received[sig]) raise (sig); } } + + gl_lock_unlock (sig_lock); return 0; } @@ -334,11 +337,16 @@ rpl_signal (int sig, handler_t handler) int _gl_raise_SIGPIPE (void) { + gl_lock_lock (sig_lock); if (blocked_set & (1U << SIGPIPE)) - pending_array[SIGPIPE] = 1; + { + pending_array[SIGPIPE] = 1; + gl_lock_unlock (sig_lock); + } else { handler_t handler = SIGPIPE_handler; + gl_lock_unlock (sig_lock); if (handler == SIG_DFL) exit (128 + SIGPIPE); else if (handler != SIG_IGN) |
