NeoMutt  2023-03-22
Teaching an old dog new tricks
DOXYGEN
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 <string.h>
36#include "message.h"
37#include "signal2.h"
38
39static sigset_t Sigset;
40static sigset_t SigsetSys;
41static struct sigaction SysOldInt;
42static struct sigaction SysOldQuit;
43static bool SignalsBlocked;
45
49
58{
59}
60
66{
67#ifdef HAVE_DECL_SYS_SIGLIST
68 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, sys_siglist[sig]);
69#elif (defined(__sun__) && defined(__svr4__))
70 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, _sys_siglist[sig]);
71#elif (defined(__alpha) && defined(__osf__))
72 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, __sys_siglist[sig]);
73#else
74 printf(_("Caught signal %d ... Exiting\n"), sig);
75#endif
76 exit(0);
77}
78
89{
90 if (sig_fn)
91 sig_handler = sig_fn;
92
93 if (exit_fn)
94 exit_handler = exit_fn;
95
96 if (segv_fn)
97 segv_handler = segv_fn;
98
99 struct sigaction act;
100
101 sigemptyset(&act.sa_mask);
102 act.sa_flags = 0;
103 act.sa_handler = SIG_IGN;
104 sigaction(SIGPIPE, &act, NULL);
105
106 act.sa_handler = segv_handler;
107 sigaction(SIGSEGV, &act, NULL);
108
109 act.sa_handler = exit_handler;
110 sigaction(SIGTERM, &act, NULL);
111 sigaction(SIGHUP, &act, NULL);
112 sigaction(SIGQUIT, &act, NULL);
113
114 /* we want to avoid race conditions */
115 sigaddset(&act.sa_mask, SIGTSTP);
116
117 act.sa_handler = sig_handler;
118
119 /* we want SIGALRM to abort the current syscall, so we do this before
120 * setting the SA_RESTART flag below. currently this is only used to
121 * timeout on a connect() call in a reasonable amount of time. */
122 sigaction(SIGALRM, &act, NULL);
123
124/* we also don't want to mess with interrupted system calls */
125#ifdef SA_RESTART
126 act.sa_flags = SA_RESTART;
127#endif
128
129 sigaction(SIGCONT, &act, NULL);
130 sigaction(SIGTSTP, &act, NULL);
131 sigaction(SIGINT, &act, NULL);
132 sigaction(SIGWINCH, &act, NULL);
133
134 /* POSIX doesn't allow us to ignore SIGCHLD,
135 * so we just install a dummy handler for it */
136 act.sa_handler = mutt_sig_empty_handler;
137 /* don't need to block any other signals here */
138 sigemptyset(&act.sa_mask);
139 /* we don't want to mess with stopped children */
140 act.sa_flags |= SA_NOCLDSTOP;
141 sigaction(SIGCHLD, &act, NULL);
142}
143
151{
152 if (SignalsBlocked)
153 return;
154
155 sigemptyset(&Sigset);
156 sigaddset(&Sigset, SIGTERM);
157 sigaddset(&Sigset, SIGHUP);
158 sigaddset(&Sigset, SIGTSTP);
159 sigaddset(&Sigset, SIGINT);
160 sigaddset(&Sigset, SIGWINCH);
161 sigprocmask(SIG_BLOCK, &Sigset, 0);
162 SignalsBlocked = true;
163}
164
169{
170 if (!SignalsBlocked)
171 return;
172
173 sigprocmask(SIG_UNBLOCK, &Sigset, 0);
174 SignalsBlocked = false;
175}
176
184{
186 return;
187
188 struct sigaction sa;
189
190 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
191 sa.sa_handler = SIG_IGN;
192 sa.sa_flags = 0;
193 sigemptyset(&sa.sa_mask);
194 sigaction(SIGINT, &sa, &SysOldInt);
195 sigaction(SIGQUIT, &sa, &SysOldQuit);
196
197 sigemptyset(&SigsetSys);
198 sigaddset(&SigsetSys, SIGCHLD);
199 sigprocmask(SIG_BLOCK, &SigsetSys, 0);
200 SysSignalsBlocked = true;
201}
202
208{
210 return;
211
212 sigprocmask(SIG_UNBLOCK, &SigsetSys, NULL);
213 if (restore)
214 {
215 sigaction(SIGQUIT, &SysOldQuit, NULL);
216 sigaction(SIGINT, &SysOldInt, NULL);
217 }
218 else
219 {
220 struct sigaction sa;
221
222 sa.sa_handler = SIG_DFL;
223 sigemptyset(&sa.sa_mask);
224 sa.sa_flags = 0;
225 sigaction(SIGQUIT, &sa, NULL);
226 sigaction(SIGINT, &sa, NULL);
227 }
228
229 SysSignalsBlocked = false;
230}
231
239{
240 struct sigaction sa;
241
242 memset(&sa, 0, sizeof(sa));
243 sa.sa_handler = sig_handler;
244#ifdef SA_RESTART
245 if (!allow)
246 sa.sa_flags |= SA_RESTART;
247#endif
248 sigaction(SIGINT, &sa, NULL);
249}
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:143
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:88
static bool SysSignalsBlocked
Definition: signal.c:44
static struct sigaction SysOldQuit
Definition: signal.c:42
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:57
static sigset_t Sigset
Definition: signal.c:39
static sig_handler_t exit_handler
Definition: signal.c:47
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:183
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
static bool SignalsBlocked
Definition: signal.c:43
static sig_handler_t sig_handler
Definition: signal.c:46
static sigset_t SigsetSys
Definition: signal.c:40
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
static sig_handler_t segv_handler
Definition: signal.c:48
static struct sigaction SysOldInt
Definition: signal.c:41
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
void mutt_sig_exit_handler(int sig)
Notify the user and shutdown gracefully.
Definition: signal.c:65