NeoMutt  2019-12-07-60-g0cfa53
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 
39 static sigset_t Sigset;
40 static sigset_t SigsetSys;
41 static struct sigaction SysOldInt;
42 static struct sigaction SysOldQuit;
43 static bool SignalsBlocked;
44 static bool SysSignalsBlocked;
45 
49 
58 {
59 }
60 
65 void mutt_sig_exit_handler(int sig)
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 
150 void mutt_sig_block(void)
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 {
185  if (SysSignalsBlocked)
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 
207 void mutt_sig_unblock_system(bool restore)
208 {
209  if (!SysSignalsBlocked)
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 
238 void mutt_sig_allow_interrupt(bool allow)
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 bool SysSignalsBlocked
Definition: signal.c:44
void mutt_sig_unblock(void)
Restore previously blocked signals.
Definition: signal.c:168
void mutt_sig_block_system(void)
Block signals before calling exec()
Definition: signal.c:183
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:57
static sigset_t Sigset
Definition: signal.c:39
#define _(a)
Definition: message.h:28
void mutt_sig_allow_interrupt(bool allow)
Allow/disallow Ctrl-C (SIGINT)
Definition: signal.c:238
static bool SignalsBlocked
Definition: signal.c:43
static sig_handler_t segv_handler
Definition: signal.c:48
void mutt_sig_unblock_system(bool restore)
Restore previously blocked signals.
Definition: signal.c:207
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
void mutt_sig_exit_handler(int sig)
Notify the user and shutdown gracefully.
Definition: signal.c:65
Message logging.
static sig_handler_t sig_handler
Definition: signal.c:46
static sig_handler_t exit_handler
Definition: signal.c:47
static sigset_t SigsetSys
Definition: signal.c:40
void(* sig_handler_t)(int sig)
typedef sig_handler_t - Handler for signals
Definition: signal2.h:32
static struct sigaction SysOldQuit
Definition: signal.c:42
void mutt_sig_block(void)
Block signals during critical operations.
Definition: signal.c:150
static struct sigaction SysOldInt
Definition: signal.c:41
Signal handling.