NeoMutt  2024-04-25-97-g7d2481
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
signal.c File Reference

Signal handling. More...

#include "config.h"
#include <signal.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "signal2.h"
+ Include dependency graph for signal.c:

Go to the source code of this file.

Functions

int endwin (void)
 
static void exit_print_uint (unsigned int n)
 AS-safe version of printf("%u", n)
 
static void exit_print_int (int n)
 AS-safe version of printf("%d", n)
 
static void exit_print_string (const char *str)
 AS-safe version of printf("%s", str)
 
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_block (void)
 Block signals during critical operations.
 
void mutt_sig_unblock (void)
 Restore previously blocked signals.
 
void mutt_sig_block_system (void)
 Block signals before calling exec()
 
void mutt_sig_unblock_system (bool restore)
 Restore previously blocked signals.
 
void mutt_sig_allow_interrupt (bool allow)
 Allow/disallow Ctrl-C (SIGINT)
 
void mutt_sig_reset_child_signals (void)
 Reset ignored signals back to the default.
 
void assertion_dump (const char *file, int line, const char *func, const char *cond)
 Dump some debugging info before we stop the program.
 

Variables

static sigset_t Sigset
 A set of signals used by mutt_sig_block(), mutt_sig_unblock()
 
static sigset_t SigsetSys
 A set of signals used by mutt_sig_block_system(), mutt_sig_unblock_system()
 
static struct sigaction SysOldInt
 Backup of SIGINT handler, when mutt_sig_block_system() is called.
 
static struct sigaction SysOldQuit
 Backup of SIGQUIT handler, when mutt_sig_block_system() is called.
 
static bool SignalsBlocked
 true when signals are blocked, e.g.
 
static bool SysSignalsBlocked
 true when system signals are blocked, e.g.
 
static sig_handler_t SigHandler = mutt_sig_empty_handler
 Function to handle other signals, e.g. SIGINT (2)
 
static sig_handler_t ExitHandler = mutt_sig_exit_handler
 Function to handle SIGTERM (15), SIGHUP (1), SIGQUIT (3) signals.
 
static sig_handler_t SegvHandler = mutt_sig_exit_handler
 Function to handle SIGSEGV (11) signals.
 
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 signal.c.

Function Documentation

◆ endwin()

int endwin ( void  )
+ Here is the caller graph for this function:

◆ exit_print_uint()

static void exit_print_uint ( unsigned int  n)
static

AS-safe version of printf("%u", n)

Parameters
nNumber to be printed

Definition at line 73 of file signal.c.

74{
75 char digit;
76
77 if (n > 9)
78 exit_print_uint(n / 10);
79
80 digit = '0' + (n % 10);
81 write(STDOUT_FILENO, &digit, 1);
82}
int digit(const char *s)
static void exit_print_uint(unsigned int n)
AS-safe version of printf("%u", n)
Definition: signal.c:73
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exit_print_int()

static void exit_print_int ( int  n)
static

AS-safe version of printf("%d", n)

Parameters
nNumber to be printed

Definition at line 88 of file signal.c.

89{
90 if (n < 0)
91 {
92 write(STDOUT_FILENO, "-", 1);
93 n = -n;
94 }
96}
+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ exit_print_string()

static void exit_print_string ( const char *  str)
static

AS-safe version of printf("%s", str)

Parameters
strString to be printed

Definition at line 102 of file signal.c.

103{
104 if (!str)
105 return;
106
107 write(STDOUT_FILENO, str, strlen(str));
108}
+ 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
static sig_handler_t SigHandler
Function to handle other signals, e.g. SIGINT (2)
Definition: signal.c:60
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_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_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_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_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:

◆ 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}
+ 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:

◆ 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:

Variable Documentation

◆ Sigset

sigset_t Sigset
static

A set of signals used by mutt_sig_block(), mutt_sig_unblock()

Definition at line 42 of file signal.c.

◆ SigsetSys

sigset_t SigsetSys
static

A set of signals used by mutt_sig_block_system(), mutt_sig_unblock_system()

Definition at line 44 of file signal.c.

◆ SysOldInt

struct sigaction SysOldInt
static

Backup of SIGINT handler, when mutt_sig_block_system() is called.

Definition at line 47 of file signal.c.

◆ SysOldQuit

struct sigaction SysOldQuit
static

Backup of SIGQUIT handler, when mutt_sig_block_system() is called.

Definition at line 49 of file signal.c.

◆ SignalsBlocked

bool SignalsBlocked
static

true when signals are blocked, e.g.

SIGTERM, SIGHUP

See also
mutt_sig_block(), mutt_sig_unblock()

Definition at line 53 of file signal.c.

◆ SysSignalsBlocked

bool SysSignalsBlocked
static

true when system signals are blocked, e.g.

SIGINT, SIGQUIT

See also
mutt_sig_block_system(), mutt_sig_unblock_system()

Definition at line 57 of file signal.c.

◆ SigHandler

Function to handle other signals, e.g. SIGINT (2)

Definition at line 60 of file signal.c.

◆ ExitHandler

sig_handler_t ExitHandler = mutt_sig_exit_handler
static

Function to handle SIGTERM (15), SIGHUP (1), SIGQUIT (3) signals.

Definition at line 62 of file signal.c.

◆ SegvHandler

sig_handler_t SegvHandler = mutt_sig_exit_handler
static

Function to handle SIGSEGV (11) signals.

Definition at line 64 of file signal.c.

◆ SigInt

volatile sig_atomic_t SigInt

true after SIGINT is received

Definition at line 66 of file signal.c.

◆ SigWinch

volatile sig_atomic_t SigWinch

true after SIGWINCH is received

Definition at line 67 of file signal.c.