NeoMutt  2024-03-23-147-g885fbc
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
signal.c File Reference

Signal handling. More...

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

Go to the source code of this file.

Functions

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.
 

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

◆ 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 73 of file signal.c.

74{
75}
+ 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 81 of file signal.c.

82{
83#ifdef HAVE_DECL_SYS_SIGLIST
84 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, sys_siglist[sig]);
85#elif (defined(__sun__) && defined(__svr4__))
86 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, _sys_siglist[sig]);
87#elif (defined(__alpha) && defined(__osf__))
88 printf(_("Caught signal %d (%s) ... Exiting\n"), sig, __sys_siglist[sig]);
89#else
90 printf(_("Caught signal %d ... Exiting\n"), sig);
91#endif
92 exit(0);
93}
#define _(a)
Definition: message.h:28
+ 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 104 of file signal.c.

105{
106 if (sig_fn)
107 SigHandler = sig_fn;
108
109 if (exit_fn)
110 ExitHandler = exit_fn;
111
112 if (segv_fn)
113 SegvHandler = segv_fn;
114
115 struct sigaction act = { 0 };
116
117 sigemptyset(&act.sa_mask);
118 act.sa_flags = 0;
119 act.sa_handler = SIG_IGN;
120 sigaction(SIGPIPE, &act, NULL);
121
122 act.sa_handler = SegvHandler;
123 sigaction(SIGSEGV, &act, NULL);
124
125 act.sa_handler = ExitHandler;
126 sigaction(SIGTERM, &act, NULL);
127 sigaction(SIGHUP, &act, NULL);
128 sigaction(SIGQUIT, &act, NULL);
129
130 /* we want to avoid race conditions */
131 sigaddset(&act.sa_mask, SIGTSTP);
132
133 act.sa_handler = SigHandler;
134
135 /* we want SIGALRM to abort the current syscall, so we do this before
136 * setting the SA_RESTART flag below. currently this is only used to
137 * timeout on a connect() call in a reasonable amount of time. */
138 sigaction(SIGALRM, &act, NULL);
139
140/* we also don't want to mess with interrupted system calls */
141#ifdef SA_RESTART
142 act.sa_flags = SA_RESTART;
143#endif
144
145 sigaction(SIGCONT, &act, NULL);
146 sigaction(SIGTSTP, &act, NULL);
147 sigaction(SIGINT, &act, NULL);
148 sigaction(SIGWINCH, &act, NULL);
149
150 /* POSIX doesn't allow us to ignore SIGCHLD,
151 * so we just install a dummy handler for it */
152 act.sa_handler = mutt_sig_empty_handler;
153 /* don't need to block any other signals here */
154 sigemptyset(&act.sa_mask);
155 /* we don't want to mess with stopped children */
156 act.sa_flags |= SA_NOCLDSTOP;
157 sigaction(SIGCHLD, &act, NULL);
158}
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
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:73
static sig_handler_t SegvHandler
Function to handle SIGSEGV (11) signals.
Definition: signal.c:61
+ 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 166 of file signal.c.

167{
168 if (SignalsBlocked)
169 return;
170
171 sigemptyset(&Sigset);
172 sigaddset(&Sigset, SIGTERM);
173 sigaddset(&Sigset, SIGHUP);
174 sigaddset(&Sigset, SIGTSTP);
175 sigaddset(&Sigset, SIGINT);
176 sigaddset(&Sigset, SIGWINCH);
177 sigprocmask(SIG_BLOCK, &Sigset, 0);
178 SignalsBlocked = true;
179}
static sigset_t Sigset
A set of signals used by mutt_sig_block(), mutt_sig_unblock()
Definition: signal.c:39
static bool SignalsBlocked
true when signals are blocked, e.g.
Definition: signal.c:50
+ Here is the caller graph for this function:

◆ mutt_sig_unblock()

void mutt_sig_unblock ( void  )

Restore previously blocked signals.

Definition at line 184 of file signal.c.

185{
186 if (!SignalsBlocked)
187 return;
188
189 sigprocmask(SIG_UNBLOCK, &Sigset, 0);
190 SignalsBlocked = false;
191}
+ 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 199 of file signal.c.

200{
202 return;
203
204 struct sigaction sa = { 0 };
205
206 /* POSIX: ignore SIGINT and SIGQUIT & block SIGCHLD before exec */
207 sa.sa_handler = SIG_IGN;
208 sa.sa_flags = 0;
209 sigemptyset(&sa.sa_mask);
210 sigaction(SIGINT, &sa, &SysOldInt);
211 sigaction(SIGQUIT, &sa, &SysOldQuit);
212
213 sigemptyset(&SigsetSys);
214 sigaddset(&SigsetSys, SIGCHLD);
215 sigprocmask(SIG_BLOCK, &SigsetSys, 0);
216 SysSignalsBlocked = true;
217}
static bool SysSignalsBlocked
true when system signals are blocked, e.g.
Definition: signal.c:54
static struct sigaction SysOldQuit
Backup of SIGQUIT handler, when mutt_sig_block_system() is called.
Definition: signal.c:46
static sigset_t SigsetSys
A set of signals used by mutt_sig_block_system(), mutt_sig_unblock_system()
Definition: signal.c:41
static struct sigaction SysOldInt
Backup of SIGINT handler, when mutt_sig_block_system() is called.
Definition: signal.c:44
+ 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 223 of file signal.c.

224{
226 return;
227
228 sigprocmask(SIG_UNBLOCK, &SigsetSys, NULL);
229 if (restore)
230 {
231 sigaction(SIGQUIT, &SysOldQuit, NULL);
232 sigaction(SIGINT, &SysOldInt, NULL);
233 }
234 else
235 {
236 struct sigaction sa = { 0 };
237
238 sa.sa_handler = SIG_DFL;
239 sigemptyset(&sa.sa_mask);
240 sa.sa_flags = 0;
241 sigaction(SIGQUIT, &sa, NULL);
242 sigaction(SIGINT, &sa, NULL);
243 }
244
245 SysSignalsBlocked = false;
246}
+ 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 254 of file signal.c.

255{
256 struct sigaction sa = { 0 };
257
258 sa.sa_handler = SigHandler;
259#ifdef SA_RESTART
260 if (!allow)
261 sa.sa_flags |= SA_RESTART;
262#endif
263 sigaction(SIGINT, &sa, NULL);
264}
+ 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 275 of file signal.c.

276{
277 struct sigaction sa = { 0 };
278
279 sa.sa_handler = SIG_DFL;
280 sa.sa_flags = 0;
281 sigemptyset(&sa.sa_mask);
282
283 /* These signals are set to SIG_IGN and must be reset */
284 sigaction(SIGPIPE, &sa, NULL);
285
286 /* These technically don't need to be reset, but the code has been
287 * doing so for a long time. */
288 sigaction(SIGTERM, &sa, NULL);
289 sigaction(SIGTSTP, &sa, NULL);
290 sigaction(SIGCONT, &sa, NULL);
291}
+ Here is the caller 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 39 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 41 of file signal.c.

◆ SysOldInt

struct sigaction SysOldInt
static

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

Definition at line 44 of file signal.c.

◆ SysOldQuit

struct sigaction SysOldQuit
static

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

Definition at line 46 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 50 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 54 of file signal.c.

◆ SigHandler

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

Definition at line 57 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 59 of file signal.c.

◆ SegvHandler

sig_handler_t SegvHandler = mutt_sig_exit_handler
static

Function to handle SIGSEGV (11) signals.

Definition at line 61 of file signal.c.

◆ SigInt

volatile sig_atomic_t SigInt

true after SIGINT is received

Definition at line 63 of file signal.c.

◆ SigWinch

volatile sig_atomic_t SigWinch

true after SIGWINCH is received

Definition at line 64 of file signal.c.