NeoMutt  2020-11-20
Teaching an old dog new tricks
DOXYGEN
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 <string.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. More...
 
void mutt_sig_exit_handler (int sig)
 Notify the user and shutdown gracefully. More...
 
void mutt_sig_init (sig_handler_t sig_fn, sig_handler_t exit_fn, sig_handler_t segv_fn)
 Initialise the signal handling. More...
 
void mutt_sig_block (void)
 Block signals during critical operations. More...
 
void mutt_sig_unblock (void)
 Restore previously blocked signals. More...
 
void mutt_sig_block_system (void)
 Block signals before calling exec() More...
 
void mutt_sig_unblock_system (bool restore)
 Restore previously blocked signals. More...
 
void mutt_sig_allow_interrupt (bool allow)
 Allow/disallow Ctrl-C (SIGINT) More...
 

Variables

static sigset_t Sigset
 
static sigset_t SigsetSys
 
static struct sigaction SysOldInt
 
static struct sigaction SysOldQuit
 
static bool SignalsBlocked
 
static bool SysSignalsBlocked
 
static sig_handler_t sig_handler = mutt_sig_empty_handler
 
static sig_handler_t exit_handler = mutt_sig_exit_handler
 
static sig_handler_t segv_handler = mutt_sig_exit_handler
 

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

58 {
59 }
+ 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 65 of file signal.c.

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 }
#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 88 of file signal.c.

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 }
void mutt_sig_empty_handler(int sig)
Dummy signal handler.
Definition: signal.c:57
static sig_handler_t segv_handler
Definition: signal.c:48
static sig_handler_t sig_handler
Definition: signal.c:46
static sig_handler_t exit_handler
Definition: signal.c:47
+ 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 150 of file signal.c.

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 }
static sigset_t Sigset
Definition: signal.c:39
static bool SignalsBlocked
Definition: signal.c:43
+ Here is the caller graph for this function:

◆ mutt_sig_unblock()

void mutt_sig_unblock ( void  )

Restore previously blocked signals.

Definition at line 168 of file signal.c.

169 {
170  if (!SignalsBlocked)
171  return;
172 
173  sigprocmask(SIG_UNBLOCK, &Sigset, 0);
174  SignalsBlocked = false;
175 }
static sigset_t Sigset
Definition: signal.c:39
static bool SignalsBlocked
Definition: signal.c:43
+ 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 183 of file signal.c.

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 }
static bool SysSignalsBlocked
Definition: signal.c:44
static sigset_t SigsetSys
Definition: signal.c:40
static struct sigaction SysOldQuit
Definition: signal.c:42
static struct sigaction SysOldInt
Definition: signal.c:41
+ 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 207 of file signal.c.

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 }
static bool SysSignalsBlocked
Definition: signal.c:44
static sigset_t SigsetSys
Definition: signal.c:40
static struct sigaction SysOldQuit
Definition: signal.c:42
static struct sigaction SysOldInt
Definition: signal.c:41
static struct Email * restore(const unsigned char *d)
Restore an Email from data retrieved from the cache.
Definition: hcache.c:145
+ 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 238 of file signal.c.

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 sig_handler_t sig_handler
Definition: signal.c:46
+ Here is the caller graph for this function:

Variable Documentation

◆ Sigset

sigset_t Sigset
static

Definition at line 39 of file signal.c.

◆ SigsetSys

sigset_t SigsetSys
static

Definition at line 40 of file signal.c.

◆ SysOldInt

struct sigaction SysOldInt
static

Definition at line 41 of file signal.c.

◆ SysOldQuit

struct sigaction SysOldQuit
static

Definition at line 42 of file signal.c.

◆ SignalsBlocked

bool SignalsBlocked
static

Definition at line 43 of file signal.c.

◆ SysSignalsBlocked

bool SysSignalsBlocked
static

Definition at line 44 of file signal.c.

◆ sig_handler

sig_handler_t sig_handler = mutt_sig_empty_handler
static

Definition at line 46 of file signal.c.

◆ exit_handler

sig_handler_t exit_handler = mutt_sig_exit_handler
static

Definition at line 47 of file signal.c.

◆ segv_handler

sig_handler_t segv_handler = mutt_sig_exit_handler
static

Definition at line 48 of file signal.c.