C-Menu 0.2.9
A User Interface Toolkit
Loading...
Searching...
No Matches
sig.c
Go to the documentation of this file.
1/** @file sig.c
2 @brief signal handling for interrupt signals
3 @author Bill Waller
4 Copyright (c) 2025
5 MIT License
6 billxwaller@gmail.com
7 @date 2026-02-09
8 */
9
10/** @defgroup signal_handling Signal Handling
11 @brief Handles signals such as SIGINT, SIGTERM, SIGQUIT, SIGUSR1, and
12 SIGSEGV.
13 @details This module provides functions to set up signal handlers for
14 various signals, handle received signals, and reset signal handlers to their
15 default behavior. It allows the program to respond to interrupt signals by
16 prompting the user for action and ensuring proper cleanup before exiting or
17 continuing execution.
18 */
19
20#include "cm.h"
21#include "ui_backend.h"
22#include <execinfo.h>
23#include <signal.h>
24#include <stdbool.h>
25#include <stdlib.h>
26#include <string.h>
27#include <termios.h>
28#include <unistd.h>
29
30#define MAX_FRAMES 64
31
32volatile sig_atomic_t sig_received = 0;
33
34/** @brief Set signal handlers to default behavior
35 @ingroup signal_handling
36 @details This function sets the signal handlers for SIGINT, SIGTERM,
37 SIGQUIT, SIGUSR1, and SIGSEGV to their default behavior. This is typically
38 used when the program needs to exit or reset its signal handling to the
39 default state.
40 */
42 struct sigaction sa;
43
44 sa.sa_handler = SIG_DFL;
45 sigemptyset(&sa.sa_mask);
46 sa.sa_flags = SA_RESTART;
47 sigaction(SIGINT, &sa, nullptr);
48 sigaction(SIGTERM, &sa, nullptr);
49 sigaction(SIGQUIT, &sa, nullptr);
50 sigaction(SIGUSR1, &sa, nullptr);
51 sa.sa_flags = SA_SIGINFO;
52 sigaction(SIGSEGV, &sa, nullptr);
53}
54/** @brief Set up signal handlers for interrupt signals
55 @ingroup signal_handling
56 @details Upon receiving an interrupt signal (SIGINT, SIGTERM, SIGQUIT), the
57 program will prompt the user to either exit the program or continue
58 execution. If the user chooses to exit, a confirmation prompt will be
59 displayed. If the user opts to continue, the program will resume normal
60 operation. */
62 struct sigaction sa;
63
64 memset(&sa, 0, sizeof(sa));
65 sa.sa_handler = signal_handler;
66 sigemptyset(&sa.sa_mask);
67 sa.sa_flags = SA_RESTART;
68 if (sigaction(SIGINT, &sa, nullptr) == -1) {
69 ui_abend(-1, _("sigaction SIGINT failed"));
70 exit(EXIT_FAILURE);
71 }
72 if (sigaction(SIGTERM, &sa, nullptr) == -1) {
73 ui_abend(-1, _("sigaction SIGTERM failed"));
74 exit(EXIT_FAILURE);
75 };
76 if (sigaction(SIGQUIT, &sa, nullptr) == -1) {
77 ui_abend(-1, _("sigaction SIGQUIT failed"));
78 exit(EXIT_FAILURE);
79 }
80 if (sigaction(SIGUSR1, &sa, nullptr) == -1) {
81 ui_abend(-1, _("sigaction SIGUSR1 failed"));
82 exit(EXIT_FAILURE);
83 }
84 sa.sa_flags = SA_SIGINFO; // Set the flag to receive siginfo_t
85 if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
86 ui_abend(-1, _("sigaction SIGSEGV failed"));
87 exit(EXIT_FAILURE);
88 }
89}
90/** @brief Signal handler for interrupt signals
91 @ingroup signal_handling
92 @param sig_num The signal number received
93 */
94void signal_handler(int sig_num) {
95 switch (sig_num) {
96 case SIGINT:
97 sig_received = SIGINT;
98 break;
99 case SIGTERM:
100 sig_received = SIGTERM;
101 break;
102 case SIGQUIT:
103 sig_received = SIGQUIT;
104 break;
105 case SIGSEGV:
107 char *msg1 = "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n";
108 write(STDERR_FILENO, msg1, strlen(msg1));
109 char *msg2 = "SIGSEGV - Segmentation fault - Stack trace\n\n";
110 write(STDERR_FILENO, msg2, strlen(msg2));
111 void *addrlist[MAX_FRAMES];
112 char **symbols;
113 int frames;
114 frames = backtrace(addrlist, MAX_FRAMES);
115 symbols = backtrace_symbols(addrlist, frames);
116 if (symbols == nullptr) {
117 ui_abend(-1, _("backtrace_symbols failed"));
118 exit(EXIT_FAILURE);
119 }
120 for (int i = 0; i < frames; i++) {
121 char buf[256];
122 ssnprintf(buf, sizeof(buf), "%s\n", symbols[i]);
123 write(STDERR_FILENO, buf, strlen(buf));
124 }
125 free(symbols);
126 msg2 = _("\nSIGSEGV Segmentation fault - Writing core to file\n\n");
127 write(STDERR_FILENO, msg2, strlen(msg2));
128 struct sigaction sa;
129 sa.sa_handler = SIG_DFL;
130 sigemptyset(&sa.sa_mask);
131 sa.sa_flags = 0;
132 sigaction(SIGSEGV, &sa, NULL);
133 kill(getpid(), SIGSEGV); // Re-raise the signal
134 exit(EXIT_FAILURE);
135 case SIGUSR1:
136 sig_received = SIGUSR1;
137 break;
138 default:
139 return;
140 }
141}
142/** @brief Handle received signals and prompt user for action
143 @ingroup signal_handling
144 @param sig_num The signal number received
145 */
146bool handle_signal(int sig_num) {
147 switch (sig_num) {
148 case SIGINT:
149 strnz__cpy(em1, _("SIGINT - Interrupt from keyboard"), MAXLEN - 1);
150 break;
151 case SIGTERM:
152 strnz__cpy(em1, _("SIGTERM - Termination signal"), MAXLEN - 1);
153 break;
154 case SIGQUIT:
155 strnz__cpy(em1, _("SIGQUIT - Quit from keyboard"), MAXLEN - 1);
156 break;
157 case SIGSEGV:
158 strnz__cpy(em1, _("SIGSEGV - Segmentation fault"), MAXLEN - 1);
159 break;
160 case SIGUSR1:
161 strnz__cpy(em1, _("SIGUSR1 - User Signal 1"), MAXLEN - 1);
162 break;
163 default:
164 strnz__cpy(em1, _("unknown signal"), MAXLEN - 1);
165 break;
166 }
169 em0[0] = '\0';
170 ssnprintf(em0, MAXLEN - 1, _("Caught signal %d\n"), sig_num);
171#ifdef DEBUG_LOG
172 sprintf(em0, _("Caught signal %d", sig_num));
173 ui_log(INFO, em0);
174#endif
175 strnz__cpy(em2, _("Press 'q' or F9 to exit, any other key to continue"),
176 MAXLEN - 1);
177 sig_received = 0;
178 return true;
179}
volatile sig_atomic_t sig_received
Definition sig.c:32
bool handle_signal(sig_atomic_t)
bool f_ncurses_open
Definition ui_common.c:50
char em1[MAXLEN]
Definition ui_common.c:47
char em2[MAXLEN]
Definition ui_common.c:48
char em0[MAXLEN]
Definition ui_common.c:46
bool f_notcurses_open
Definition ui_common.c:51
void ui_abend(int ec, char *s)
Convert multibyte string to complex character array.
Definition ui_common.c:362
#define MAXLEN
Definition curskeys.c:15
#define MAX_FRAMES
Definition sig.c:30
#define _(String)
Definition amort.c:23
struct termios shell_tioctl
Definition scriou.c:22
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition whence.c:291
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:390
bool set_sane_tioctl(struct termios *)
set_sane_tioctl() - set terminal to sane settings for C-MENU
Definition scriou.c:99
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
Definition scriou.c:57
void sig_dfl_mode()
Set signal handlers to default behavior.
Definition sig.c:41
void signal_handler(int)
Signal handler for interrupt signals.
Definition sig.c:94
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition sig.c:61