NeoMutt
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
71{
72}
73
79{
80#ifdef HAVE_DECL_SYS_SIGLIST
81 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, sys_siglist[sig]);
82#elif (defined(__sun__) && defined(__svr4__))
83 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, _sys_siglist[sig]);
84#elif (defined(__alpha) && defined(__osf__))
85 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, __sys_siglist[sig]);
86#else
87 printf(_("Caught signal %d ... Exiting\n"), sig);
88#endif
89 exit(0);
90}
91
102{
103 if (sig_fn)
104 SigHandler = sig_fn;
105
106 if (exit_fn)
107 ExitHandler = exit_fn;
108
109 if (segv_fn)
110 SegvHandler = segv_fn;
111
112 struct sigaction act = { 0 };
113
114 sigemptyset(&act.sa_mask);
115 act.sa_flags = 0;
116 act.sa_handler = SIG_IGN;
117 sigaction(SIGPIPE, &act, NULL);
118
119 act.sa_handler = SegvHandler;
120 sigaction(SIGSEGV, &act, NULL);
121
122 act.sa_handler = ExitHandler;
123 sigaction(SIGTERM, &act, NULL);
124 sigaction(SIGHUP, &act, NULL);
125 sigaction(SIGQUIT, &act, NULL);
126
127 /* we want to avoid race conditions */
128 sigaddset(&act.sa_mask, SIGTSTP);
129
130 act.sa_handler = SigHandler;
131
132 /* we want SIGALRM to abort the current syscall, so we do this before
133 * setting the SA_RESTART flag below. currently this is only used to
134 * timeout on a connect() call in a reasonable amount of time. */
135 sigaction(SIGALRM, &act, NULL);
136
137/* we also don't want to mess with interrupted system calls */
138#ifdef SA_RESTART
139 act.sa_flags = SA_RESTART;
140#endif
141
142 sigaction(SIGCONT, &act, NULL);
143 sigaction(SIGTSTP, &act, NULL);
144 sigaction(SIGINT, &act, NULL);
145 sigaction(SIGWINCH, &act, NULL);
146
147 /* POSIX doesn't allow us to ignore SIGCHLD,
148 * so we just install a dummy handler for it */
149 act.sa_handler = mutt_sig_empty_handler;
150 /* don't need to block any other signals here */
151 sigemptyset(&act.sa_mask);
152 /* we don't want to mess with stopped children */
153 act.sa_flags |= SA_NOCLDSTOP;
154 sigaction(SIGCHLD, &act, NULL);
155}
156
164{
165 if (SignalsBlocked)
166 return;
167
168 sigemptyset(&Sigset);
169 sigaddset(&Sigset, SIGTERM);
170 sigaddset(&Sigset, SIGHUP);
171 sigaddset(&Sigset, SIGTSTP);
172 sigaddset(&Sigset, SIGINT);
173 sigaddset(&Sigset, SIGWINCH);
174 sigprocmask(SIG_BLOCK, &Sigset, 0);
175 SignalsBlocked = true;
176}
177
182{
183 if (!SignalsBlocked)
184 return;
185
186 sigprocmask(SIG_UNBLOCK, &Sigset, 0);
187 SignalsBlocked = false;
188}
189
197{
199 return;
200
201 struct sigaction sa = { 0 };
202
203 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
204 sa.sa_handler = SIG_IGN;
205 sa.sa_flags = 0;
206 sigemptyset(&sa.sa_mask);
207 sigaction(SIGINT, &sa, &SysOldInt);
208 sigaction(SIGQUIT, &sa, &SysOldQuit);
209
210 sigemptyset(&SigsetSys);
211 sigaddset(&SigsetSys, SIGCHLD);
212 sigprocmask(SIG_BLOCK, &SigsetSys, 0);
213 SysSignalsBlocked = true;
214}
215
220void mutt_sig_unblock_system(bool restore)
221{
223 return;
224
225 sigprocmask(SIG_UNBLOCK, &SigsetSys, NULL);
226 if (restore)
227 {
228 sigaction(SIGQUIT, &SysOldQuit, NULL);
229 sigaction(SIGINT, &SysOldInt, NULL);
230 }
231 else
232 {
233 struct sigaction sa = { 0 };
234
235 sa.sa_handler = SIG_DFL;
236 sigemptyset(&sa.sa_mask);
237 sa.sa_flags = 0;
238 sigaction(SIGQUIT, &sa, NULL);
239 sigaction(SIGINT, &sa, NULL);
240 }
241
242 SysSignalsBlocked = false;
243}
244
252{
253 struct sigaction sa = { 0 };
254
255 sa.sa_handler = SigHandler;
256#ifdef SA_RESTART
257 if (!allow)
258 sa.sa_flags |= SA_RESTART;
259#endif
260 sigaction(SIGINT, &sa, NULL);
261}
Message logging.
#define _(a)
Definition: message.h:28
Signal handling.
void(* sig_handler_t)(int sig)
Definition: signal2.h:35
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:101
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
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:70
static sigset_t Sigset
A set of signals used by mutt_sig_block(), mutt_sig_unblock()
Definition: signal.c:39
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:196
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:163
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:181
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:220
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:251
void mutt_sig_exit_handler(int sig)
Notify the user and shutdown gracefully.
Definition: signal.c:78