NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
signal.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <stddef.h>
31#include <signal.h>
32#include <stdbool.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include "message.h"
36#include "signal2.h"
37
39static sigset_t Sigset;
41static sigset_t SigsetSys;
42
44static struct sigaction SysOldInt;
46static struct sigaction SysOldQuit;
47
50static bool SignalsBlocked;
51
55
62
63volatile sig_atomic_t SigInt;
64volatile sig_atomic_t SigWinch;
65
74{
75}
76
82{
83#ifdef HAVE_DECL_SYS_SIGLIST
84 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, sys_siglist[sig]);
85#elif (defined(__sun__) && defined(__svr4__))
86 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, _sys_siglist[sig]);
87#elif (defined(__alpha) && defined(__osf__))
88 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, __sys_siglist[sig]);
89#else
90 printf(_("Caught signal %d ... Exiting\n"), sig);
91#endif
92 exit(0);
93}
94
105{
106 if (sig_fn)
107 SigHandler = sig_fn;
108
109 if (exit_fn)
110 ExitHandler = exit_fn;
111
112 if (segv_fn)
113 SegvHandler = segv_fn;
114
115 struct sigaction act = { 0 };
116
117 sigemptyset(&act.sa_mask);
118 act.sa_flags = 0;
119 act.sa_handler = SIG_IGN;
120 sigaction(SIGPIPE, &act, NULL);
121
122 act.sa_handler = SegvHandler;
123 sigaction(SIGSEGV, &act, NULL);
124
125 act.sa_handler = ExitHandler;
126 sigaction(SIGTERM, &act, NULL);
127 sigaction(SIGHUP, &act, NULL);
128 sigaction(SIGQUIT, &act, NULL);
129
130 /* we want to avoid race conditions */
131 sigaddset(&act.sa_mask, SIGTSTP);
132
133 act.sa_handler = SigHandler;
134
135 /* we want SIGALRM to abort the current syscall, so we do this before
136 * setting the SA_RESTART flag below. currently this is only used to
137 * timeout on a connect() call in a reasonable amount of time. */
138 sigaction(SIGALRM, &act, NULL);
139
140/* we also don't want to mess with interrupted system calls */
141#ifdef SA_RESTART
142 act.sa_flags = SA_RESTART;
143#endif
144
145 sigaction(SIGCONT, &act, NULL);
146 sigaction(SIGTSTP, &act, NULL);
147 sigaction(SIGINT, &act, NULL);
148 sigaction(SIGWINCH, &act, NULL);
149
150 /* POSIX doesn't allow us to ignore SIGCHLD,
151 * so we just install a dummy handler for it */
152 act.sa_handler = mutt_sig_empty_handler;
153 /* don't need to block any other signals here */
154 sigemptyset(&act.sa_mask);
155 /* we don't want to mess with stopped children */
156 act.sa_flags |= SA_NOCLDSTOP;
157 sigaction(SIGCHLD, &act, NULL);
158}
159
167{
168 if (SignalsBlocked)
169 return;
170
171 sigemptyset(&Sigset);
172 sigaddset(&Sigset, SIGTERM);
173 sigaddset(&Sigset, SIGHUP);
174 sigaddset(&Sigset, SIGTSTP);
175 sigaddset(&Sigset, SIGINT);
176 sigaddset(&Sigset, SIGWINCH);
177 sigprocmask(SIG_BLOCK, &Sigset, 0);
178 SignalsBlocked = true;
179}
180
185{
186 if (!SignalsBlocked)
187 return;
188
189 sigprocmask(SIG_UNBLOCK, &Sigset, 0);
190 SignalsBlocked = false;
191}
192
200{
202 return;
203
204 struct sigaction sa = { 0 };
205
206 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
207 sa.sa_handler = SIG_IGN;
208 sa.sa_flags = 0;
209 sigemptyset(&sa.sa_mask);
210 sigaction(SIGINT, &sa, &SysOldInt);
211 sigaction(SIGQUIT, &sa, &SysOldQuit);
212
213 sigemptyset(&SigsetSys);
214 sigaddset(&SigsetSys, SIGCHLD);
215 sigprocmask(SIG_BLOCK, &SigsetSys, 0);
216 SysSignalsBlocked = true;
217}
218
223void mutt_sig_unblock_system(bool restore)
224{
226 return;
227
228 sigprocmask(SIG_UNBLOCK, &SigsetSys, NULL);
229 if (restore)
230 {
231 sigaction(SIGQUIT, &SysOldQuit, NULL);
232 sigaction(SIGINT, &SysOldInt, NULL);
233 }
234 else
235 {
236 struct sigaction sa = { 0 };
237
238 sa.sa_handler = SIG_DFL;
239 sigemptyset(&sa.sa_mask);
240 sa.sa_flags = 0;
241 sigaction(SIGQUIT, &sa, NULL);
242 sigaction(SIGINT, &sa, NULL);
243 }
244
245 SysSignalsBlocked = false;
246}
247
255{
256 struct sigaction sa = { 0 };
257
258 sa.sa_handler = SigHandler;
259#ifdef SA_RESTART
260 if (!allow)
261 sa.sa_flags |= SA_RESTART;
262#endif
263 sigaction(SIGINT, &sa, NULL);
264}
265
276{
277 struct sigaction sa = { 0 };
278
279 sa.sa_handler = SIG_DFL;
280 sa.sa_flags = 0;
281 sigemptyset(&sa.sa_mask);
282
283 /* These signals are set to SIG_IGN and must be reset */
284 sigaction(SIGPIPE, &sa, NULL);
285
286 /* These technically don't need to be reset, but the code has been
287 * doing so for a long time. */
288 sigaction(SIGTERM, &sa, NULL);
289 sigaction(SIGTSTP, &sa, NULL);
290 sigaction(SIGCONT, &sa, NULL);
291}
Message logging.
#define _(a)
Definition: message.h:28
Signal handling.
void(* sig_handler_t)(int sig)
Definition: signal2.h:40
void mutt_sig_init(sig_handler_t sig_fn, sig_handler_t exit_fn, sig_handler_t segv_fn)
Initialise the signal handling.
Definition: signal.c:104
static bool SysSignalsBlocked
true when system signals are blocked, e.g.
Definition: signal.c:54
static sig_handler_t ExitHandler
Function to handle SIGTERM (15), SIGHUP (1), SIGQUIT (3) signals.
Definition: signal.c:59
volatile sig_atomic_t SigWinch
true after SIGWINCH is received
Definition: signal.c:64
static sig_handler_t SigHandler
Function to handle other signals, e.g. SIGINT (2)
Definition: signal.c:57
static struct sigaction SysOldQuit
Backup of SIGQUIT handler, when mutt_sig_block_system() is called.
Definition: signal.c:46
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:73
static sigset_t Sigset
A set of signals used by mutt_sig_block(), mutt_sig_unblock()
Definition: signal.c:39
void mutt_sig_reset_child_signals(void)
Reset ignored signals back to the default.
Definition: signal.c:275
volatile sig_atomic_t SigInt
true after SIGINT is received
Definition: signal.c:63
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:199
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:166
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:184
static bool SignalsBlocked
true when signals are blocked, e.g.
Definition: signal.c:50
static sig_handler_t SegvHandler
Function to handle SIGSEGV (11) signals.
Definition: signal.c:61
static sigset_t SigsetSys
A set of signals used by mutt_sig_block_system(), mutt_sig_unblock_system()
Definition: signal.c:41
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:223
static struct sigaction SysOldInt
Backup of SIGINT handler, when mutt_sig_block_system() is called.
Definition: signal.c:44
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:254
void mutt_sig_exit_handler(int sig)
Notify the user and shutdown gracefully.
Definition: signal.c:81