Define SA_RESTART also for mingw.
[gnulib.git] / lib / sigaction.c
1 /* POSIX compatible signal blocking.
2    Copyright (C) 2008 Free Software Foundation, Inc.
3    Written by Eric Blake <ebb9@byu.net>, 2008.
4
5    This program is free software: you can redistribute it and/or modify
6    it under the terms of the GNU General Public License as published by
7    the Free Software Foundation; either version 3 of the License, or
8    (at your option) any later version.
9
10    This program is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13    GNU General Public License for more details.
14
15    You should have received a copy of the GNU General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
17
18 #include <config.h>
19
20 /* Specification.  */
21 #include <signal.h>
22
23 #include <errno.h>
24 #include <stdint.h>
25 #include <stdlib.h>
26
27 /* This implementation of sigaction is tailored to Woe32 behavior:
28    signal() has SysV semantics (ie. the handler is uninstalled before
29    it is invoked).  This is an inherent data race if an asynchronous
30    signal is sent twice in a row before we can reinstall our handler,
31    but there's nothing we can do about it.  Meanwhile, sigprocmask()
32    is not present, and while we can use the gnulib replacement to
33    provide critical sections, it too suffers from potential data races
34    in the face of an ill-timed asynchronous signal.  And we compound
35    the situation by reading static storage in a signal handler, which
36    POSIX warns is not generically async-signal-safe.  Oh well.
37
38    Additionally:
39      - We don't implement SA_NOCLDSTOP or SA_NOCLDWAIT, because SIGCHLD
40        is not defined.
41      - We don't implement SA_ONSTACK, because sigaltstack() is not present.
42      - We ignore SA_RESTART, because blocking Win32 calls are not interrupted
43        anyway when an asynchronous signal occurs, and the MSVCRT runtime
44        never sets errno to EINTR.
45      - We don't implement SA_SIGINFO because it is impossible to do so
46        portably.
47
48    POSIX states that an application should not mix signal() and
49    sigaction().  We support the use of signal() within the gnulib
50    sigprocmask() substitute, but all other application code linked
51    with this module should stick with only sigaction().  */
52
53 /* Check some of our assumptions.  */
54 #if defined SIGCHLD || defined HAVE_SIGALTSTACK || defined HAVE_SIGINTERRUPT
55 # error "Revisit the assumptions made in the sigaction module"
56 #endif
57
58 /* Out-of-range substitutes make a good fallback for uncatchable
59    signals.  */
60 #ifndef SIGKILL
61 # define SIGKILL (-1)
62 #endif
63 #ifndef SIGSTOP
64 # define SIGSTOP (-1)
65 #endif
66
67 /* A signal handler.  */
68 typedef void (*handler_t) (int signal);
69
70 /* Set of current actions.  If sa_handler for an entry is NULL, then
71    that signal is not currently handled by the sigaction handler.  */
72 static struct sigaction volatile action_array[NSIG] /* = 0 */;
73
74 /* Signal handler that is installed for signals.  */
75 static void
76 sigaction_handler (int sig)
77 {
78   handler_t handler;
79   sigset_t mask;
80   sigset_t oldmask;
81   int saved_errno = errno;
82   if (sig < 0 || NSIG <= sig || !action_array[sig].sa_handler)
83     {
84       /* Unexpected situation; be careful to avoid recursive abort.  */
85       if (sig == SIGABRT)
86         signal (SIGABRT, SIG_DFL);
87       abort ();
88     }
89
90   /* Reinstall the signal handler when required; otherwise update the
91      bookkeeping so that the user's handler may call sigaction and get
92      accurate results.  We know the signal isn't currently blocked, or
93      we wouldn't be in its handler, therefore we know that we are not
94      interrupting a sigaction() call.  There is a race where any
95      asynchronous instance of the same signal occurring before we
96      reinstall the handler will trigger the default handler; oh
97      well.  */
98   handler = action_array[sig].sa_handler;
99   if ((action_array[sig].sa_flags & SA_RESETHAND) == 0)
100     signal (sig, sigaction_handler);
101   else
102     action_array[sig].sa_handler = NULL;
103
104   /* Block appropriate signals.  */
105   mask = action_array[sig].sa_mask;
106   if ((action_array[sig].sa_flags & SA_NODEFER) == 0)
107     sigaddset (&mask, sig);
108   sigprocmask (SIG_BLOCK, &mask, &oldmask);
109
110   /* Invoke the user's handler, then restore prior mask.  */
111   errno = saved_errno;
112   handler (sig);
113   saved_errno = errno;
114   sigprocmask (SIG_SETMASK, &oldmask, NULL);
115   errno = saved_errno;
116 }
117
118 /* Change and/or query the action that will be taken on delivery of
119    signal SIG.  If not NULL, ACT describes the new behavior.  If not
120    NULL, OACT is set to the prior behavior.  Return 0 on success, or
121    set errno and return -1 on failure.  */
122 int
123 sigaction (int sig, const struct sigaction *restrict act,
124            struct sigaction *restrict oact)
125 {
126   sigset_t mask;
127   sigset_t oldmask;
128   int saved_errno;
129
130   if (sig < 0 || NSIG <= sig || sig == SIGKILL || sig == SIGSTOP
131       || (act && act->sa_handler == SIG_ERR))
132     {
133       errno = EINVAL;
134       return -1;
135     }
136
137   /* POSIX requires sigaction() to be async-signal-safe.  In other
138      words, if an asynchronous signal can occur while we are anywhere
139      inside this function, the user's handler could then call
140      sigaction() recursively and expect consistent results.  We meet
141      this rule by using sigprocmask to block all signals before
142      modifying any data structure that could be read from a signal
143      handler; this works since we know that the gnulib sigprocmask
144      replacement does not try to use sigaction() from its handler.  */
145   if (!act && !oact)
146     return 0;
147   sigfillset (&mask);
148   sigprocmask (SIG_BLOCK, &mask, &oldmask);
149   if (oact)
150     {
151       if (action_array[sig].sa_handler)
152         *oact = action_array[sig];
153       else
154         {
155           /* Safe to change the handler at will here, since all
156              signals are currently blocked.  */
157           oact->sa_handler = signal (sig, SIG_DFL);
158           if (oact->sa_handler == SIG_ERR)
159             goto failure;
160           signal (sig, oact->sa_handler);
161           oact->sa_flags = SA_RESETHAND | SA_NODEFER;
162           sigemptyset (&oact->sa_mask);
163         }
164     }
165
166   if (act)
167     {
168       /* Safe to install the handler before updating action_array,
169          since all signals are currently blocked.  */
170       if (act->sa_handler == SIG_DFL || act->sa_handler == SIG_IGN)
171         {
172           if (signal (sig, act->sa_handler) == SIG_ERR)
173             goto failure;
174           action_array[sig].sa_handler = NULL;
175         }
176       else
177         {
178           if (signal (sig, sigaction_handler) == SIG_ERR)
179             goto failure;
180           action_array[sig] = *act;
181         }
182     }
183   sigprocmask (SIG_SETMASK, &oldmask, NULL);
184   return 0;
185
186  failure:
187   saved_errno = errno;
188   sigprocmask (SIG_SETMASK, &oldmask, NULL);
189   errno = saved_errno;
190   return -1;
191 }