1 ///////////////////////////////////////////////////////////////////////////////
4 /// \brief Handling signals to abort operation
6 // Author: Lasse Collin
8 // This file has been put into the public domain.
9 // You can do whatever you want with this file.
11 ///////////////////////////////////////////////////////////////////////////////
16 volatile sig_atomic_t user_abort = false;
21 /// If we were interrupted by a signal, we store the signal number so that
22 /// we can raise that signal to kill the program when all cleanups have
24 static volatile sig_atomic_t exit_signal = 0;
26 /// Mask of signals for which have have established a signal handler to set
27 /// user_abort to true.
28 static sigset_t hooked_signals;
30 /// signals_block() and signals_unblock() can be called recursively.
31 static size_t signals_block_count = 0;
35 signal_handler(int sig)
46 // List of signals for which we establish the signal handler.
47 static const int sigs[] = {
64 // Mask of the signals for which we have established a signal handler.
65 sigemptyset(&hooked_signals);
66 for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i)
67 sigaddset(&hooked_signals, sigs[i]);
71 // All the signals that we handle we also blocked while the signal
73 sa.sa_mask = hooked_signals;
75 // Don't set SA_RESTART, because we want EINTR so that we can check
76 // for user_abort and cleanup before exiting. We block the signals
77 // for which we have established a handler when we don't want EINTR.
79 sa.sa_handler = &signal_handler;
81 for (size_t i = 0; i < ARRAY_SIZE(sigs); ++i) {
82 // If the parent process has left some signals ignored,
83 // we don't unignore them.
85 if (sigaction(sigs[i], NULL, &old) == 0
86 && old.sa_handler == SIG_IGN)
89 // Establish the signal handler.
90 if (sigaction(sigs[i], &sa, NULL))
91 message_signal_handler();
102 if (signals_block_count++ == 0) {
103 const int saved_errno = errno;
104 mythread_sigmask(SIG_BLOCK, &hooked_signals, NULL);
113 signals_unblock(void)
115 assert(signals_block_count > 0);
117 if (--signals_block_count == 0) {
118 const int saved_errno = errno;
119 mythread_sigmask(SIG_UNBLOCK, &hooked_signals, NULL);
131 const int sig = exit_signal;
135 sa.sa_handler = SIG_DFL;
136 sigfillset(&sa.sa_mask);
138 sigaction(sig, &sa, NULL);
147 // While Windows has some very basic signal handling functions as required
148 // by C89, they are not really used, or so I understood. Instead, we use
149 // SetConsoleCtrlHandler() to catch user pressing C-c.
155 signal_handler(DWORD type lzma_attribute((unused)))
157 // Since we don't get a signal number which we could raise() at
158 // signals_exit() like on POSIX, just set the exit status to
159 // indicate an error, so that we cannot return with zero exit status.
160 set_exit_status(E_ERROR);
169 if (!SetConsoleCtrlHandler(&signal_handler, TRUE))
170 message_signal_handler();