105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* POSIX compatible signal blocking. 205436638acc7c010349a69c3395f1a57c642dc62Ying Wang Copyright (C) 2006-2012 Free Software Foundation, Inc. 305436638acc7c010349a69c3395f1a57c642dc62Ying Wang Written by Bruno Haible <bruno@clisp.org>, 2006. 405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 505436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is free software: you can redistribute it and/or modify 605436638acc7c010349a69c3395f1a57c642dc62Ying Wang it under the terms of the GNU General Public License as published by 705436638acc7c010349a69c3395f1a57c642dc62Ying Wang the Free Software Foundation; either version 3 of the License, or 805436638acc7c010349a69c3395f1a57c642dc62Ying Wang (at your option) any later version. 905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang This program is distributed in the hope that it will be useful, 1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang but WITHOUT ANY WARRANTY; without even the implied warranty of 1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang GNU General Public License for more details. 1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang You should have received a copy of the GNU General Public License 1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang along with this program. If not, see <http://www.gnu.org/licenses/>. */ 1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang 1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <config.h> 1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Specification. */ 2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <signal.h> 2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <errno.h> 2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdint.h> 2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stdlib.h> 2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_MSVC_INVALID_PARAMETER_HANDLER 2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include "msvc-inval.h" 2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* We assume that a platform without POSIX signal blocking functions 3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang also does not have the POSIX sigaction() function, only the 3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang signal() function. We also assume signal() has SysV semantics, 3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang where any handler is uninstalled prior to being invoked. This is 3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang true for native Windows platforms. */ 3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* We use raw signal(), but also provide a wrapper rpl_signal() so 3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang that applications can query or change a blocked signal. */ 3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#undef signal 4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Provide invalid signal numbers as fallbacks if the uncatchable 4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang signals are not defined. */ 4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef SIGKILL 4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SIGKILL (-1) 4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef SIGSTOP 4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SIGSTOP (-1) 4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* On native Windows, as of 2008, the signal SIGABRT_COMPAT is an alias 5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang for the signal SIGABRT. Only one signal handler is stored for both 5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang SIGABRT and SIGABRT_COMPAT. SIGABRT_COMPAT is not a signal of its own. */ 5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__ 5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef SIGABRT_COMPAT 5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SIGABRT_COMPAT 6 5605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifdef SIGABRT_COMPAT 5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SIGABRT_COMPAT_MASK (1U << SIGABRT_COMPAT) 5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#else 6005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define SIGABRT_COMPAT_MASK 0 6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6305436638acc7c010349a69c3395f1a57c642dc62Ying Wangtypedef void (*handler_t) (int); 6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_MSVC_INVALID_PARAMETER_HANDLER 6605436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic handler_t 6705436638acc7c010349a69c3395f1a57c642dc62Ying Wangsignal_nothrow (int sig, handler_t handler) 6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang handler_t result; 7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 7105436638acc7c010349a69c3395f1a57c642dc62Ying Wang TRY_MSVC_INVAL 7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = signal (sig, handler); 7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang CATCH_MSVC_INVAL 7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 7705436638acc7c010349a69c3395f1a57c642dc62Ying Wang result = SIG_ERR; 7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang DONE_MSVC_INVAL; 8105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define signal signal_nothrow 8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Handling of gnulib defined signals. */ 8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if GNULIB_defined_SIGPIPE 9005436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic handler_t SIGPIPE_handler = SIG_DFL; 9105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if GNULIB_defined_SIGPIPE 9405436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic handler_t 9505436638acc7c010349a69c3395f1a57c642dc62Ying Wangext_signal (int sig, handler_t handler) 9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang switch (sig) 9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang case SIGPIPE: 10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang handler_t old_handler = SIGPIPE_handler; 10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang SIGPIPE_handler = handler; 10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return old_handler; 10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang default: /* System defined signal */ 10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return signal (sig, handler); 10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang# undef signal 11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define signal ext_signal 11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 11305436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 11405436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigismember (const sigset_t *set, int sig) 11505436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 11605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig >= 0 && sig < NSIG) 11705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 11805436638acc7c010349a69c3395f1a57c642dc62Ying Wang #ifdef SIGABRT_COMPAT 11905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig == SIGABRT_COMPAT) 12005436638acc7c010349a69c3395f1a57c642dc62Ying Wang sig = SIGABRT; 12105436638acc7c010349a69c3395f1a57c642dc62Ying Wang #endif 12205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return (*set >> sig) & 1; 12405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 12505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 12605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 12705436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 12805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 12905436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 13005436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigemptyset (sigset_t *set) 13105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 13205436638acc7c010349a69c3395f1a57c642dc62Ying Wang *set = 0; 13305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 13405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 13505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 13605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 13705436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigaddset (sigset_t *set, int sig) 13805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 13905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig >= 0 && sig < NSIG) 14005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 14105436638acc7c010349a69c3395f1a57c642dc62Ying Wang #ifdef SIGABRT_COMPAT 14205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig == SIGABRT_COMPAT) 14305436638acc7c010349a69c3395f1a57c642dc62Ying Wang sig = SIGABRT; 14405436638acc7c010349a69c3395f1a57c642dc62Ying Wang #endif 14505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 14605436638acc7c010349a69c3395f1a57c642dc62Ying Wang *set |= 1U << sig; 14705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 14805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 14905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 15005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 15105436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 15205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 15305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 15405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 15505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 15605436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 15705436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigdelset (sigset_t *set, int sig) 15805436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 15905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig >= 0 && sig < NSIG) 16005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 16105436638acc7c010349a69c3395f1a57c642dc62Ying Wang #ifdef SIGABRT_COMPAT 16205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig == SIGABRT_COMPAT) 16305436638acc7c010349a69c3395f1a57c642dc62Ying Wang sig = SIGABRT; 16405436638acc7c010349a69c3395f1a57c642dc62Ying Wang #endif 16505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 16605436638acc7c010349a69c3395f1a57c642dc62Ying Wang *set &= ~(1U << sig); 16705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 16805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 16905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 17005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 17105436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 17205436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 17305436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 17405436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 17505436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 17705436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 17805436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigfillset (sigset_t *set) 17905436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 18005436638acc7c010349a69c3395f1a57c642dc62Ying Wang *set = ((2U << (NSIG - 1)) - 1) & ~ SIGABRT_COMPAT_MASK; 18105436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 18205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 18305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Set of currently blocked signals. */ 18505436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic volatile sigset_t blocked_set /* = 0 */; 18605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 18705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Set of currently blocked and pending signals. */ 18805436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic volatile sig_atomic_t pending_array[NSIG] /* = { 0 } */; 18905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 19005436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Signal handler that is installed for blocked signals. */ 19105436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic void 19205436638acc7c010349a69c3395f1a57c642dc62Ying Wangblocked_handler (int sig) 19305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 19405436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* Reinstall the handler, in case the signal occurs multiple times 19505436638acc7c010349a69c3395f1a57c642dc62Ying Wang while blocked. There is an inherent race where an asynchronous 19605436638acc7c010349a69c3395f1a57c642dc62Ying Wang signal in between when the kernel uninstalled the handler and 19705436638acc7c010349a69c3395f1a57c642dc62Ying Wang when we reinstall it will trigger the default handler; oh 19805436638acc7c010349a69c3395f1a57c642dc62Ying Wang well. */ 19905436638acc7c010349a69c3395f1a57c642dc62Ying Wang signal (sig, blocked_handler); 20005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig >= 0 && sig < NSIG) 20105436638acc7c010349a69c3395f1a57c642dc62Ying Wang pending_array[sig] = 1; 20205436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 20305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 20405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 20505436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigpending (sigset_t *set) 20605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 20705436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigset_t pending = 0; 20805436638acc7c010349a69c3395f1a57c642dc62Ying Wang int sig; 20905436638acc7c010349a69c3395f1a57c642dc62Ying Wang 21005436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (sig = 0; sig < NSIG; sig++) 21105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (pending_array[sig]) 21205436638acc7c010349a69c3395f1a57c642dc62Ying Wang pending |= 1U << sig; 21305436638acc7c010349a69c3395f1a57c642dc62Ying Wang *set = pending; 21405436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 21505436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 21605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 21705436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The previous signal handlers. 21805436638acc7c010349a69c3395f1a57c642dc62Ying Wang Only the array elements corresponding to blocked signals are relevant. */ 21905436638acc7c010349a69c3395f1a57c642dc62Ying Wangstatic volatile handler_t old_handlers[NSIG]; 22005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 22105436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 22205436638acc7c010349a69c3395f1a57c642dc62Ying Wangsigprocmask (int operation, const sigset_t *set, sigset_t *old_set) 22305436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 22405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (old_set != NULL) 22505436638acc7c010349a69c3395f1a57c642dc62Ying Wang *old_set = blocked_set; 22605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 22705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (set != NULL) 22805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 22905436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigset_t new_blocked_set; 23005436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigset_t to_unblock; 23105436638acc7c010349a69c3395f1a57c642dc62Ying Wang sigset_t to_block; 23205436638acc7c010349a69c3395f1a57c642dc62Ying Wang 23305436638acc7c010349a69c3395f1a57c642dc62Ying Wang switch (operation) 23405436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 23505436638acc7c010349a69c3395f1a57c642dc62Ying Wang case SIG_BLOCK: 23605436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_blocked_set = blocked_set | *set; 23705436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 23805436638acc7c010349a69c3395f1a57c642dc62Ying Wang case SIG_SETMASK: 23905436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_blocked_set = *set; 24005436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 24105436638acc7c010349a69c3395f1a57c642dc62Ying Wang case SIG_UNBLOCK: 24205436638acc7c010349a69c3395f1a57c642dc62Ying Wang new_blocked_set = blocked_set & ~*set; 24305436638acc7c010349a69c3395f1a57c642dc62Ying Wang break; 24405436638acc7c010349a69c3395f1a57c642dc62Ying Wang default: 24505436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 24605436638acc7c010349a69c3395f1a57c642dc62Ying Wang return -1; 24705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 24805436638acc7c010349a69c3395f1a57c642dc62Ying Wang to_unblock = blocked_set & ~new_blocked_set; 24905436638acc7c010349a69c3395f1a57c642dc62Ying Wang to_block = new_blocked_set & ~blocked_set; 25005436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25105436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (to_block != 0) 25205436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 25305436638acc7c010349a69c3395f1a57c642dc62Ying Wang int sig; 25405436638acc7c010349a69c3395f1a57c642dc62Ying Wang 25505436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (sig = 0; sig < NSIG; sig++) 25605436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((to_block >> sig) & 1) 25705436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 25805436638acc7c010349a69c3395f1a57c642dc62Ying Wang pending_array[sig] = 0; 25905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((old_handlers[sig] = signal (sig, blocked_handler)) != SIG_ERR) 26005436638acc7c010349a69c3395f1a57c642dc62Ying Wang blocked_set |= 1U << sig; 26105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 26205436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 26305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 26405436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (to_unblock != 0) 26505436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 26605436638acc7c010349a69c3395f1a57c642dc62Ying Wang sig_atomic_t received[NSIG]; 26705436638acc7c010349a69c3395f1a57c642dc62Ying Wang int sig; 26805436638acc7c010349a69c3395f1a57c642dc62Ying Wang 26905436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (sig = 0; sig < NSIG; sig++) 27005436638acc7c010349a69c3395f1a57c642dc62Ying Wang if ((to_unblock >> sig) & 1) 27105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 27205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (signal (sig, old_handlers[sig]) != blocked_handler) 27305436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* The application changed a signal handler while the signal 27405436638acc7c010349a69c3395f1a57c642dc62Ying Wang was blocked, bypassing our rpl_signal replacement. 27505436638acc7c010349a69c3395f1a57c642dc62Ying Wang We don't support this. */ 27605436638acc7c010349a69c3395f1a57c642dc62Ying Wang abort (); 27705436638acc7c010349a69c3395f1a57c642dc62Ying Wang received[sig] = pending_array[sig]; 27805436638acc7c010349a69c3395f1a57c642dc62Ying Wang blocked_set &= ~(1U << sig); 27905436638acc7c010349a69c3395f1a57c642dc62Ying Wang pending_array[sig] = 0; 28005436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 28105436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 28205436638acc7c010349a69c3395f1a57c642dc62Ying Wang received[sig] = 0; 28305436638acc7c010349a69c3395f1a57c642dc62Ying Wang 28405436638acc7c010349a69c3395f1a57c642dc62Ying Wang for (sig = 0; sig < NSIG; sig++) 28505436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (received[sig]) 28605436638acc7c010349a69c3395f1a57c642dc62Ying Wang raise (sig); 28705436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 28805436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 28905436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 29005436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 29105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 29205436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Install the handler FUNC for signal SIG, and return the previous 29305436638acc7c010349a69c3395f1a57c642dc62Ying Wang handler. */ 29405436638acc7c010349a69c3395f1a57c642dc62Ying Wanghandler_t 29505436638acc7c010349a69c3395f1a57c642dc62Ying Wangrpl_signal (int sig, handler_t handler) 29605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 29705436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* We must provide a wrapper, so that a user can query what handler 29805436638acc7c010349a69c3395f1a57c642dc62Ying Wang they installed even if that signal is currently blocked. */ 29905436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig >= 0 && sig < NSIG && sig != SIGKILL && sig != SIGSTOP 30005436638acc7c010349a69c3395f1a57c642dc62Ying Wang && handler != SIG_ERR) 30105436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 30205436638acc7c010349a69c3395f1a57c642dc62Ying Wang #ifdef SIGABRT_COMPAT 30305436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (sig == SIGABRT_COMPAT) 30405436638acc7c010349a69c3395f1a57c642dc62Ying Wang sig = SIGABRT; 30505436638acc7c010349a69c3395f1a57c642dc62Ying Wang #endif 30605436638acc7c010349a69c3395f1a57c642dc62Ying Wang 30705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (blocked_set & (1U << sig)) 30805436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 30905436638acc7c010349a69c3395f1a57c642dc62Ying Wang /* POSIX states that sigprocmask and signal are both 31005436638acc7c010349a69c3395f1a57c642dc62Ying Wang async-signal-safe. This is not true of our 31105436638acc7c010349a69c3395f1a57c642dc62Ying Wang implementation - there is a slight data race where an 31205436638acc7c010349a69c3395f1a57c642dc62Ying Wang asynchronous interrupt on signal A can occur after we 31305436638acc7c010349a69c3395f1a57c642dc62Ying Wang install blocked_handler but before we have updated 31405436638acc7c010349a69c3395f1a57c642dc62Ying Wang old_handlers for signal B, such that handler A can see 31505436638acc7c010349a69c3395f1a57c642dc62Ying Wang stale information if it calls signal(B). Oh well - 31605436638acc7c010349a69c3395f1a57c642dc62Ying Wang signal handlers really shouldn't try to manipulate the 31705436638acc7c010349a69c3395f1a57c642dc62Ying Wang installed handlers of unrelated signals. */ 31805436638acc7c010349a69c3395f1a57c642dc62Ying Wang handler_t result = old_handlers[sig]; 31905436638acc7c010349a69c3395f1a57c642dc62Ying Wang old_handlers[sig] = handler; 32005436638acc7c010349a69c3395f1a57c642dc62Ying Wang return result; 32105436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 32205436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 32305436638acc7c010349a69c3395f1a57c642dc62Ying Wang return signal (sig, handler); 32405436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 32505436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 32605436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 32705436638acc7c010349a69c3395f1a57c642dc62Ying Wang errno = EINVAL; 32805436638acc7c010349a69c3395f1a57c642dc62Ying Wang return SIG_ERR; 32905436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 33005436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 33105436638acc7c010349a69c3395f1a57c642dc62Ying Wang 33205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if GNULIB_defined_SIGPIPE 33305436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Raise the signal SIGPIPE. */ 33405436638acc7c010349a69c3395f1a57c642dc62Ying Wangint 33505436638acc7c010349a69c3395f1a57c642dc62Ying Wang_gl_raise_SIGPIPE (void) 33605436638acc7c010349a69c3395f1a57c642dc62Ying Wang{ 33705436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (blocked_set & (1U << SIGPIPE)) 33805436638acc7c010349a69c3395f1a57c642dc62Ying Wang pending_array[SIGPIPE] = 1; 33905436638acc7c010349a69c3395f1a57c642dc62Ying Wang else 34005436638acc7c010349a69c3395f1a57c642dc62Ying Wang { 34105436638acc7c010349a69c3395f1a57c642dc62Ying Wang handler_t handler = SIGPIPE_handler; 34205436638acc7c010349a69c3395f1a57c642dc62Ying Wang if (handler == SIG_DFL) 34305436638acc7c010349a69c3395f1a57c642dc62Ying Wang exit (128 + SIGPIPE); 34405436638acc7c010349a69c3395f1a57c642dc62Ying Wang else if (handler != SIG_IGN) 34505436638acc7c010349a69c3395f1a57c642dc62Ying Wang (*handler) (SIGPIPE); 34605436638acc7c010349a69c3395f1a57c642dc62Ying Wang } 34705436638acc7c010349a69c3395f1a57c642dc62Ying Wang return 0; 34805436638acc7c010349a69c3395f1a57c642dc62Ying Wang} 34905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif 350