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