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 <execinfo.h>
22#include <signal.h>
23#include <stdbool.h>
24#include <stdlib.h>
25#include <string.h>
26#include <termios.h>
27#include <unistd.h>
28
29#define MAX_FRAMES 64
30
31volatile sig_atomic_t sig_received = 0;
32
33bool f_curses_open = false;
34
35/** @brief Set signal handlers to default behavior
36 @ingroup signal_handling
37 @details This function sets the signal handlers for SIGINT, SIGTERM,
38 SIGQUIT, SIGUSR1, and SIGSEGV to their default behavior. This is typically
39 used when the program needs to exit or reset its signal handling to the
40 default state.
41 */
43 struct sigaction sa;
44
45 sa.sa_handler = SIG_DFL;
46 sigemptyset(&sa.sa_mask);
47 sa.sa_flags = SA_RESTART;
48 sigaction(SIGINT, &sa, nullptr);
49 sigaction(SIGTERM, &sa, nullptr);
50 sigaction(SIGQUIT, &sa, nullptr);
51 sigaction(SIGUSR1, &sa, nullptr);
52 sa.sa_flags = SA_SIGINFO;
53 sigaction(SIGSEGV, &sa, nullptr);
54}
55/** @brief Set up signal handlers for interrupt signals
56 @ingroup signal_handling
57 @details Upon receiving an interrupt signal (SIGINT, SIGTERM, SIGQUIT), the
58 program will prompt the user to either exit the program or continue
59 execution. If the user chooses to exit, a confirmation prompt will be
60 displayed. If the user opts to continue, the program will resume normal
61 operation. */
63 struct sigaction sa;
64
65 memset(&sa, 0, sizeof(sa));
66 sa.sa_handler = signal_handler;
67 sigemptyset(&sa.sa_mask);
68 sa.sa_flags = SA_RESTART;
69 if (sigaction(SIGINT, &sa, nullptr) == -1) {
70 abend(-1, "sigaction SIGINT failed");
71 exit(EXIT_FAILURE);
72 }
73 if (sigaction(SIGTERM, &sa, nullptr) == -1) {
74 abend(-1, "sigaction SIGTERM failed");
75 exit(EXIT_FAILURE);
76 };
77 if (sigaction(SIGQUIT, &sa, nullptr) == -1) {
78 abend(-1, "sigaction SIGQUIT failed");
79 exit(EXIT_FAILURE);
80 }
81 if (sigaction(SIGUSR1, &sa, nullptr) == -1) {
82 abend(-1, "sigaction SIGUSR1 failed");
83 exit(EXIT_FAILURE);
84 }
85 sa.sa_flags = SA_SIGINFO; // Set the flag to receive siginfo_t
86 if (sigaction(SIGSEGV, &sa, nullptr) == -1) {
87 abend(-1, "sigaction SIGSEGV failed");
88 exit(EXIT_FAILURE);
89 }
90}
91/** @brief Signal handler for interrupt signals
92 @ingroup signal_handling
93 @param sig_num The signal number received
94 */
95void signal_handler(int sig_num) {
96 switch (sig_num) {
97 case SIGINT:
98 sig_received = SIGINT;
99 break;
100 case SIGTERM:
101 sig_received = SIGTERM;
102 break;
103 case SIGQUIT:
104 sig_received = SIGQUIT;
105 break;
106 case SIGSEGV:
108 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";
109 write(STDERR_FILENO, msg1, strlen(msg1));
110 char *msg2 = "SIGSEGV - Segmentation fault - Stack trace\n\n";
111 write(STDERR_FILENO, msg2, strlen(msg2));
112 void *addrlist[MAX_FRAMES];
113 char **symbols;
114 int frames;
115 frames = backtrace(addrlist, MAX_FRAMES);
116 symbols = backtrace_symbols(addrlist, frames);
117 if (symbols == nullptr) {
118 abend(-1, "backtrace_symbols failed");
119 exit(EXIT_FAILURE);
120 }
121 for (int i = 0; i < frames; i++) {
122 char buf[256];
123 ssnprintf(buf, sizeof(buf), "%s\n", symbols[i]);
124 write(STDERR_FILENO, buf, strlen(buf));
125 }
126 free(symbols);
127 msg2 = "\nSIGSEGV Segmentation fault - Writing core to file\n\n";
128 write(STDERR_FILENO, msg2, strlen(msg2));
129 struct sigaction sa;
130 sa.sa_handler = SIG_DFL;
131 sigemptyset(&sa.sa_mask);
132 sa.sa_flags = 0;
133 sigaction(SIGSEGV, &sa, NULL);
134 kill(getpid(), SIGSEGV); // Re-raise the signal
135 exit(EXIT_FAILURE);
136 case SIGUSR1:
137 sig_received = SIGUSR1;
138 break;
139 default:
140 return;
141 }
142}
143/** @brief Handle received signals and prompt user for action
144 @ingroup signal_handling
145 @param sig_num The signal number received
146 */
147bool handle_signal(int sig_num) {
148 switch (sig_num) {
149 case SIGINT:
150 strnz__cpy(em1, "SIGINT - Interrupt from keyboard", MAXLEN - 1);
151 break;
152 case SIGTERM:
153 strnz__cpy(em1, "SIGTERM - Termination signal", MAXLEN - 1);
154 break;
155 case SIGQUIT:
156 strnz__cpy(em1, "SIGQUIT - Quit from keyboard", MAXLEN - 1);
157 break;
158 case SIGSEGV:
159 strnz__cpy(em1, "SIGSEGV - Segmentation fault", MAXLEN - 1);
160 break;
161 case SIGUSR1:
162 strnz__cpy(em1, "SIGUSR1 - User Signal 1", MAXLEN - 1);
163 break;
164 default:
165 strnz__cpy(em1, "unknown signal", MAXLEN - 1);
166 break;
167 }
168 if (!f_curses_open)
170 em0[0] = '\0';
171 ssnprintf(em0, MAXLEN - 1, "Caught signal %d\n", sig_num);
172 strnz__cpy(em2, "Press 'q' or F9 to exit, any other key to continue",
173 MAXLEN - 1);
174 sig_received = 0;
175 return true;
176}
volatile sig_atomic_t sig_received
Definition sig.c:31
bool handle_signal(sig_atomic_t)
bool f_curses_open
Definition sig.c:33
#define nullptr
Definition cm.h:23
#define MAXLEN
Definition curskeys.c:15
#define MAX_FRAMES
Definition sig.c:29
char em1[MAXLEN]
Definition dwin.c:133
char em0[MAXLEN]
Definition dwin.c:132
char em2[MAXLEN]
Definition dwin.c:134
struct termios shell_tioctl
Definition scriou.c:22
void abend(int, char *)
Abnormal program termination.
Definition dwin.c:1331
size_t strnz__cpy(char *, const char *, size_t)
safer alternative to strncpy
Definition futil.c:269
size_t ssnprintf(char *, size_t, const char *,...)
ssnprintf was designed to be a safer alternative to snprintf.
Definition futil.c:147
bool set_sane_tioctl(struct termios *)
set_sane_tioctl() - set terminal to sane settings for C-MENU
Definition scriou.c:95
bool restore_shell_tioctl()
restore_shell_tioctl() - restore shell terminal settings
Definition scriou.c:56
void sig_dfl_mode()
Set signal handlers to default behavior.
Definition sig.c:42
void signal_handler(int)
Signal handler for interrupt signals.
Definition sig.c:95
void sig_prog_mode()
Set up signal handlers for interrupt signals.
Definition sig.c:62