summaryrefslogtreecommitdiff
path: root/examples/dte/signals.c
diff options
context:
space:
mode:
Diffstat (limited to 'examples/dte/signals.c')
-rw-r--r--examples/dte/signals.c169
1 files changed, 0 insertions, 169 deletions
diff --git a/examples/dte/signals.c b/examples/dte/signals.c
deleted file mode 100644
index e1a7155..0000000
--- a/examples/dte/signals.c
+++ /dev/null
@@ -1,169 +0,0 @@
-#include "compat.h"
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-#include "signals.h"
-#include "util/debug.h"
-#include "util/exitcode.h"
-#include "util/log.h"
-#include "util/macros.h"
-
-volatile sig_atomic_t resized = 0;
-
-static const int ignored_signals[] = {
- SIGINT, // Terminal interrupt (see: VINTR in termios(3))
- SIGQUIT, // Terminal quit (see: VQUIT in termios(3))
- SIGTSTP, // Terminal stop (see: VSUSP in termios(3))
- SIGXFSZ, // File size limit exceeded (see: RLIMIT_FSIZE in getrlimit(3))
- SIGPIPE, // Broken pipe (see: EPIPE error in write(3))
- SIGUSR1, // User signal 1 (terminates by default, for no good reason)
- SIGUSR2, // User signal 2 (as above)
-};
-
-static const int default_signals[] = {
- SIGABRT, // Terminate (cleanup already done)
- SIGCHLD, // Ignore (see: wait(3))
- SIGURG, // Ignore
- SIGTTIN, // Stop
- SIGTTOU, // Stop
- SIGCONT, // Continue
-};
-
-static const int fatal_signals[] = {
- SIGBUS,
- SIGFPE,
- SIGILL,
- SIGSEGV,
- SIGSYS,
- SIGTRAP,
- SIGXCPU,
- SIGALRM,
- SIGVTALRM,
- SIGHUP,
- SIGTERM,
-#ifdef SIGPROF
- SIGPROF,
-#endif
-#ifdef SIGEMT
- SIGEMT,
-#endif
-};
-
-void handle_sigwinch(int UNUSED_ARG(signum))
-{
- resized = 1;
-}
-
-static noreturn COLD void handle_fatal_signal(int signum)
-{
- LOG_CRITICAL("received signal %d (%s)", signum, strsignal(signum));
-
- // If `signum` is SIGHUP, there's no point in trying to clean up the
- // state of the (disconnected) terminal
- if (signum != SIGHUP) {
- fatal_error_cleanup();
- }
-
- // Restore and unblock `signum` and then re-raise it, to ensure the
- // termination status (as seen by e.g. waitpid(3) in the parent) is
- // set appropriately
- struct sigaction sa = {.sa_handler = SIG_DFL};
- if (
- sigemptyset(&sa.sa_mask) == 0
- && sigaction(signum, &sa, NULL) == 0
- && sigaddset(&sa.sa_mask, signum) == 0
- && sigprocmask(SIG_UNBLOCK, &sa.sa_mask, NULL) == 0
- ) {
- raise(signum);
- }
-
- // This is here just to make extra certain the handler never returns.
- // If everything is working correctly, this code should be unreachable.
- raise(SIGKILL);
- _exit(EX_OSERR);
-}
-
-// strsignal(3) is fine in situations where a signal is being reported
-// as terminating a process, but it tends to be confusing in most other
-// circumstances, where the signal name (not description) is usually
-// clearer
-static const char *signum_to_str(int signum)
-{
-#if HAVE_SIG2STR
- static char buf[SIG2STR_MAX + 3];
- if (sig2str(signum, buf + 3) == 0) {
- return memcpy(buf, "SIG", 3);
- }
-#elif HAVE_SIGABBREV_NP
- static char buf[16];
- const char *abbr = sigabbrev_np(signum);
- if (abbr && memccpy(buf + 3, abbr, '\0', sizeof(buf) - 3)) {
- return memcpy(buf, "SIG", 3);
- }
-#endif
-
- const char *str = strsignal(signum);
- return likely(str) ? str : "??";
-}
-
-static void do_sigaction(int sig, const struct sigaction *action)
-{
- struct sigaction old_action;
- if (unlikely(sigaction(sig, action, &old_action) != 0)) {
- const char *err = strerror(errno);
- LOG_ERROR("failed to set disposition for signal %d: %s", sig, err);
- return;
- }
- if (unlikely(old_action.sa_handler == SIG_IGN)) {
- const char *str = signum_to_str(sig);
- LOG_WARNING("ignored signal was inherited: %d (%s)", sig, str);
- }
-}
-
-/*
- * "A program that uses these functions should be written to catch all
- * signals and take other appropriate actions to ensure that when the
- * program terminates, whether planned or not, the terminal device's
- * state is restored to its original state."
- *
- * (https://pubs.opengroup.org/onlinepubs/9699919799/functions/tcgetattr.html)
- */
-void set_signal_handlers(void)
-{
- struct sigaction action = {.sa_handler = handle_fatal_signal};
- sigfillset(&action.sa_mask);
- for (size_t i = 0; i < ARRAYLEN(fatal_signals); i++) {
- do_sigaction(fatal_signals[i], &action);
- }
-
- // "The default actions for the realtime signals in the range SIGRTMIN
- // to SIGRTMAX shall be to terminate the process abnormally."
- // (POSIX.1-2017 ยง2.4.3)
-#if defined(SIGRTMIN) && defined(SIGRTMAX)
- for (int s = SIGRTMIN, max = SIGRTMAX; s <= max; s++) {
- do_sigaction(s, &action);
- }
-#endif
-
- action.sa_handler = SIG_IGN;
- for (size_t i = 0; i < ARRAYLEN(ignored_signals); i++) {
- do_sigaction(ignored_signals[i], &action);
- }
-
- action.sa_handler = SIG_DFL;
- for (size_t i = 0; i < ARRAYLEN(default_signals); i++) {
- do_sigaction(default_signals[i], &action);
- }
-
-#if defined(SIGWINCH)
- LOG_INFO("setting SIGWINCH handler");
- action.sa_handler = handle_sigwinch;
- do_sigaction(SIGWINCH, &action);
-#endif
-
- // Set signal mask explicitly, to avoid any possibility of
- // inheriting blocked signals
- sigset_t mask;
- sigemptyset(&mask);
- sigprocmask(SIG_SETMASK, &mask, NULL);
-}