NeoMutt  2024-11-14-34-g5aaf0d
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
signal2.h File Reference

Signal handling. More...

#include "config.h"
#include <signal.h>
#include <stdbool.h>
+ Include dependency graph for signal2.h:
+ This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Macros

#define ASSERT_STOP   (*(volatile int *) 0 = 0)
 
#define ASSERT(COND)
 

Typedefs

typedef void(* sig_handler_t) (int sig)
 

Functions

static void show_backtrace (void)
 
void assertion_dump (const char *file, int line, const char *func, const char *cond)
 Dump some debugging info before we stop the program.
 
void mutt_sig_allow_interrupt (bool allow)
 Allow/disallow Ctrl-C (SIGINT)
 
void mutt_sig_block (void)
 Block signals during critical operations.
 
void mutt_sig_block_system (void)
 Block signals before calling exec()
 
void mutt_sig_empty_handler (int sig)
 Dummy signal handler.
 
void mutt_sig_exit_handler (int sig)
 Notify the user and shutdown gracefully.
 
void mutt_sig_init (sig_handler_t sig_fn, sig_handler_t exit_fn, sig_handler_t segv_fn)
 Initialise the signal handling.
 
void mutt_sig_reset_child_signals (void)
 Reset ignored signals back to the default.
 
void mutt_sig_unblock (void)
 Restore previously blocked signals.
 
void mutt_sig_unblock_system (bool restore)
 Restore previously blocked signals.
 

Variables

volatile sig_atomic_t SigInt
 true after SIGINT is received
 
volatile sig_atomic_t SigWinch
 true after SIGWINCH is received
 

Detailed Description

Signal handling.

Authors
  • Richard Russon

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.

Definition in file signal2.h.

Macro Definition Documentation

◆ ASSERT_STOP

#define ASSERT_STOP   (*(volatile int *) 0 = 0)

Definition at line 56 of file signal2.h.

◆ ASSERT

#define ASSERT (   COND)
Value:
do \
{ \
if (!(COND)) \
{ \
assertion_dump(__FILE__, __LINE__, __func__, #COND); \
} \
} while (false);
#define ASSERT_STOP
Definition: signal2.h:56

Definition at line 58 of file signal2.h.

Typedef Documentation

◆ sig_handler_t

typedef void(* sig_handler_t) (int sig)

Definition at line 46 of file signal2.h.

Function Documentation

◆ show_backtrace()

static void show_backtrace ( void  )
inlinestatic

Definition at line 33 of file signal2.h.

33{} // LCOV_EXCL_LINE

◆ assertion_dump()

void assertion_dump ( const char *  file,
int  line,
const char *  func,
const char *  cond 
)

Dump some debugging info before we stop the program.

Parameters
fileSource file
lineLine of source
funcFunction
condAssertion condition

Definition at line 346 of file signal.c.

347{
348 endwin();
350 printf("%s:%d:%s() -- assertion failed (%s)\n", file, line, func, cond);
351}
void show_backtrace(void)
Log the program's call stack.
Definition: backtrace.c:39
int endwin(void)
+ Here is the call graph for this function:

◆ mutt_sig_allow_interrupt()

void mutt_sig_allow_interrupt ( bool  allow)

Allow/disallow Ctrl-C (SIGINT)

Parameters
allowTrue to allow Ctrl-C to interrupt signals

Allow the user to interrupt some long operations.

Definition at line 300 of file signal.c.

301{
302 struct sigaction sa = { 0 };
303
304 sa.sa_handler = SigHandler;
305#ifdef SA_RESTART
306 if (!allow)
307 sa.sa_flags |= SA_RESTART;
308#endif
309 sigaction(SIGINT, &sa, NULL);
310}
static sig_handler_t SigHandler
Function to handle other signals, e.g. SIGINT (2)
Definition: signal.c:60
+ Here is the caller graph for this function:

◆ mutt_sig_block()

void mutt_sig_block ( void  )

Block signals during critical operations.

It's important that certain signals don't interfere with critical operations. Call mutt_sig_unblock() to restore the signals' behaviour.

Definition at line 212 of file signal.c.

213{
214 if (SignalsBlocked)
215 return;
216
217 sigemptyset(&Sigset);
218 sigaddset(&Sigset, SIGTERM);
219 sigaddset(&Sigset, SIGHUP);
220 sigaddset(&Sigset, SIGTSTP);
221 sigaddset(&Sigset, SIGINT);
222 sigaddset(&Sigset, SIGWINCH);
223 sigprocmask(SIG_BLOCK, &Sigset, 0);
224 SignalsBlocked = true;
225}
static sigset_t Sigset
A set of signals used by mutt_sig_block(), mutt_sig_unblock()
Definition: signal.c:42
static bool SignalsBlocked
true when signals are blocked, e.g.
Definition: signal.c:53
+ Here is the caller graph for this function:

◆ mutt_sig_block_system()

void mutt_sig_block_system ( void  )

Block signals before calling exec()

It's important that certain signals don't interfere with the child process. Call mutt_sig_unblock_system() to restore the signals' behaviour.

Definition at line 245 of file signal.c.

246{
248 return;
249
250 struct sigaction sa = { 0 };
251
252 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
253 sa.sa_handler = SIG_IGN;
254 sa.sa_flags = 0;
255 sigemptyset(&sa.sa_mask);
256 sigaction(SIGINT, &sa, &SysOldInt);
257 sigaction(SIGQUIT, &sa, &SysOldQuit);
258
259 sigemptyset(&SigsetSys);
260 sigaddset(&SigsetSys, SIGCHLD);
261 sigprocmask(SIG_BLOCK, &SigsetSys, 0);
262 SysSignalsBlocked = true;
263}
static bool SysSignalsBlocked
true when system signals are blocked, e.g.
Definition: signal.c:57
static struct sigaction SysOldQuit
Backup of SIGQUIT handler, when mutt_sig_block_system() is called.
Definition: signal.c:49
static sigset_t SigsetSys
A set of signals used by mutt_sig_block_system(), mutt_sig_unblock_system()
Definition: signal.c:44
static struct sigaction SysOldInt
Backup of SIGINT handler, when mutt_sig_block_system() is called.
Definition: signal.c:47
+ Here is the caller graph for this function:

◆ mutt_sig_empty_handler()

void mutt_sig_empty_handler ( int  sig)

Dummy signal handler.

Parameters
sigSignal number, e.g. SIGINT

Useful for signals that we can't ignore, or don't want to do anything with.

Definition at line 117 of file signal.c.

118{
119}
+ Here is the caller graph for this function:

◆ mutt_sig_exit_handler()

void mutt_sig_exit_handler ( int  sig)

Notify the user and shutdown gracefully.

Parameters
sigSignal number, e.g. SIGINT

Definition at line 125 of file signal.c.

126{
127 exit_print_string("Caught signal ");
128 exit_print_int(sig);
130#ifdef HAVE_DECL_SYS_SIGLIST
131 exit_print_string(sys_siglist[sig]);
132#elif (defined(__sun__) && defined(__svr4__))
133 exit_print_string(_sys_siglist[sig]);
134#elif (defined(__alpha) && defined(__osf__))
135 exit_print_string(__sys_siglist[sig]);
136#endif
137 exit_print_string("... Exiting\n");
138 exit(0);
139}
static void exit_print_int(int n)
AS-safe version of printf("%d", n)
Definition: signal.c:88
static void exit_print_string(const char *str)
AS-safe version of printf("%s", str)
Definition: signal.c:102
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sig_init()

void mutt_sig_init ( sig_handler_t  sig_fn,
sig_handler_t  exit_fn,
sig_handler_t  segv_fn 
)

Initialise the signal handling.

Parameters
sig_fnFunction to handle signals
exit_fnFunction to call on uncaught signals
segv_fnFunction to call on a segfault (Segmentation Violation)

Set up handlers to ignore or catch signals of interest. We use three handlers for the signals we want to catch, ignore, or exit.

Definition at line 150 of file signal.c.

151{
152 if (sig_fn)
153 SigHandler = sig_fn;
154
155 if (exit_fn)
156 ExitHandler = exit_fn;
157
158 if (segv_fn)
159 SegvHandler = segv_fn;
160
161 struct sigaction act = { 0 };
162
163 sigemptyset(&act.sa_mask);
164 act.sa_flags = 0;
165 act.sa_handler = SIG_IGN;
166 sigaction(SIGPIPE, &act, NULL);
167
168 act.sa_handler = SegvHandler;
169 sigaction(SIGSEGV, &act, NULL);
170
171 act.sa_handler = ExitHandler;
172 sigaction(SIGTERM, &act, NULL);
173 sigaction(SIGHUP, &act, NULL);
174 sigaction(SIGQUIT, &act, NULL);
175
176 /* we want to avoid race conditions */
177 sigaddset(&act.sa_mask, SIGTSTP);
178
179 act.sa_handler = SigHandler;
180
181 /* we want SIGALRM to abort the current syscall, so we do this before
182 * setting the SA_RESTART flag below. currently this is only used to
183 * timeout on a connect() call in a reasonable amount of time. */
184 sigaction(SIGALRM, &act, NULL);
185
186/* we also don't want to mess with interrupted system calls */
187#ifdef SA_RESTART
188 act.sa_flags = SA_RESTART;
189#endif
190
191 sigaction(SIGCONT, &act, NULL);
192 sigaction(SIGTSTP, &act, NULL);
193 sigaction(SIGINT, &act, NULL);
194 sigaction(SIGWINCH, &act, NULL);
195
196 /* POSIX doesn't allow us to ignore SIGCHLD,
197 * so we just install a dummy handler for it */
198 act.sa_handler = mutt_sig_empty_handler;
199 /* don't need to block any other signals here */
200 sigemptyset(&act.sa_mask);
201 /* we don't want to mess with stopped children */
202 act.sa_flags |= SA_NOCLDSTOP;
203 sigaction(SIGCHLD, &act, NULL);
204}
static sig_handler_t ExitHandler
Function to handle SIGTERM (15), SIGHUP (1), SIGQUIT (3) signals.
Definition: signal.c:62
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:117
static sig_handler_t SegvHandler
Function to handle SIGSEGV (11) signals.
Definition: signal.c:64
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ mutt_sig_reset_child_signals()

void mutt_sig_reset_child_signals ( void  )

Reset ignored signals back to the default.

See sigaction(2): A child created via fork(2) inherits a copy of its parent's signal dispositions. During an execve(2), the dispositions of handled signals are reset to the default; the dispositions of ignored signals are left unchanged.

Definition at line 321 of file signal.c.

322{
323 struct sigaction sa = { 0 };
324
325 sa.sa_handler = SIG_DFL;
326 sa.sa_flags = 0;
327 sigemptyset(&sa.sa_mask);
328
329 /* These signals are set to SIG_IGN and must be reset */
330 sigaction(SIGPIPE, &sa, NULL);
331
332 /* These technically don't need to be reset, but the code has been
333 * doing so for a long time. */
334 sigaction(SIGTERM, &sa, NULL);
335 sigaction(SIGTSTP, &sa, NULL);
336 sigaction(SIGCONT, &sa, NULL);
337}
+ Here is the caller graph for this function:

◆ mutt_sig_unblock()

void mutt_sig_unblock ( void  )

Restore previously blocked signals.

Definition at line 230 of file signal.c.

231{
232 if (!SignalsBlocked)
233 return;
234
235 sigprocmask(SIG_UNBLOCK, &Sigset, 0);
236 SignalsBlocked = false;
237}
+ Here is the caller graph for this function:

◆ mutt_sig_unblock_system()

void mutt_sig_unblock_system ( bool  restore)

Restore previously blocked signals.

Parameters
restoreIf true, restore previous SIGINT, SIGQUIT behaviour

Definition at line 269 of file signal.c.

270{
272 return;
273
274 sigprocmask(SIG_UNBLOCK, &SigsetSys, NULL);
275 if (restore)
276 {
277 sigaction(SIGQUIT, &SysOldQuit, NULL);
278 sigaction(SIGINT, &SysOldInt, NULL);
279 }
280 else
281 {
282 struct sigaction sa = { 0 };
283
284 sa.sa_handler = SIG_DFL;
285 sigemptyset(&sa.sa_mask);
286 sa.sa_flags = 0;
287 sigaction(SIGQUIT, &sa, NULL);
288 sigaction(SIGINT, &sa, NULL);
289 }
290
291 SysSignalsBlocked = false;
292}
+ Here is the caller graph for this function:

Variable Documentation

◆ SigInt

volatile sig_atomic_t SigInt
extern

true after SIGINT is received

Definition at line 66 of file signal.c.

◆ SigWinch

volatile sig_atomic_t SigWinch
extern

true after SIGWINCH is received

Definition at line 67 of file signal.c.