FFmpeg
Loading...
Searching...
No Matches
signal.c
Go to the documentation of this file.
1/*
2 * Copyright © 2025, Niklas Haas
3 * Copyright © 2018, VideoLAN and dav1d authors
4 * Copyright © 2018, Two Orioles, LLC
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright notice,
14 * this list of conditions and the following disclaimer in the documentation
15 * and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
21 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
26 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <assert.h>
30#include <signal.h>
31#include <stdarg.h>
32
33#include "checkasm_config.h"
34
35#include "checkasm/test.h"
36#include "internal.h"
37
38#ifdef _WIN32
39 #include <windows.h>
40 #ifndef SIGBUS
41 /* non-standard, use the same value as mingw-w64 */
42 #define SIGBUS 10
43 #endif
44#endif
45
47
48static volatile sig_atomic_t sig; // SIG_ATOMIC_MAX = signal handling enabled
49
50volatile sig_atomic_t checkasm_interrupted;
51
52void checkasm_set_signal_handler_state(const int enabled)
53{
54 sig = enabled ? SIG_ATOMIC_MAX : 0;
55}
56
57static void interrupt_handler(const int s)
58{
60
61 /* If we happen to be currently executing a test function, we should jump
62 * directly out of it; since it may take an arbitrary amount of time */
63 if (sig == SIG_ATOMIC_MAX) {
64 sig = s;
66 }
67
68 /* Don't re-set the signal handler, to let the next signal trigger the
69 * default action */
70}
71
72#ifdef _WIN32
73
74 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
75static LONG NTAPI signal_handler(EXCEPTION_POINTERS *const e)
76{
77 if (sig == SIG_ATOMIC_MAX) {
78 int s;
79 switch (e->ExceptionRecord->ExceptionCode) {
80 case EXCEPTION_FLT_DIVIDE_BY_ZERO:
81 case EXCEPTION_INT_DIVIDE_BY_ZERO: s = SIGFPE; break;
82 case EXCEPTION_ILLEGAL_INSTRUCTION:
83 case EXCEPTION_PRIV_INSTRUCTION: s = SIGILL; break;
84 case EXCEPTION_ACCESS_VIOLATION:
85 case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
86 case EXCEPTION_DATATYPE_MISALIGNMENT:
87 case EXCEPTION_STACK_OVERFLOW: s = SIGSEGV; break;
88 case EXCEPTION_IN_PAGE_ERROR: s = SIGBUS; break;
89 default: return EXCEPTION_CONTINUE_SEARCH;
90 }
91 sig = s;
93 }
94 return EXCEPTION_CONTINUE_SEARCH;
95}
96 #endif
97
98#elif HAVE_SIGACTION && defined(SA_RESETHAND)
99
100static void signal_handler(int s);
101
102static const struct sigaction interrupt_handler_act = {
103 .sa_handler = interrupt_handler,
104 .sa_flags = SA_RESETHAND,
105};
106
107static const struct sigaction signal_handler_act = {
108 .sa_handler = signal_handler,
109 .sa_flags = SA_RESETHAND,
110};
111
112static void signal_handler(const int s)
113{
114 if (sig == SIG_ATOMIC_MAX) {
115 sig = s;
116 sigaction(s, &signal_handler_act, NULL);
118 }
119}
120#else
121
122static void signal_handler(const int s)
123{
124 if (sig == SIG_ATOMIC_MAX) {
125 sig = s;
126 signal(s, signal_handler);
128 }
129}
130#endif
131
133{
134 static int handlers_set;
135 if (handlers_set)
136 return;
137
138#ifdef _WIN32
139 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
140 AddVectoredExceptionHandler(0, signal_handler);
141 #endif
142 signal(SIGINT, interrupt_handler);
143 signal(SIGTERM, interrupt_handler);
144#elif HAVE_SIGACTION && defined(SA_RESETHAND)
145#ifdef SIGBUS
146 sigaction(SIGBUS, &signal_handler_act, NULL);
147#endif
148 sigaction(SIGFPE, &signal_handler_act, NULL);
149 sigaction(SIGILL, &signal_handler_act, NULL);
150 sigaction(SIGSEGV, &signal_handler_act, NULL);
151 sigaction(SIGINT, &interrupt_handler_act, NULL);
152 sigaction(SIGTERM, &interrupt_handler_act, NULL);
153#else
154#ifdef SIGBUS
155 signal(SIGBUS, signal_handler);
156#endif
157 signal(SIGFPE, signal_handler);
158 signal(SIGILL, signal_handler);
159 signal(SIGSEGV, signal_handler);
160 signal(SIGINT, interrupt_handler);
161 signal(SIGTERM, interrupt_handler);
162#endif
163
164 handlers_set = 1;
165}
166
168{
169 switch (sig) {
170 case SIGFPE: return "fatal arithmetic error";
171 case SIGILL: return "illegal instruction";
172#ifdef SIGBUS
173 case SIGBUS: return "bus error";
174#endif
175 case SIGSEGV: return "segmentation fault";
176 case SIGINT: return "interrupted";
177 case SIGTERM: return "terminated";
178 default: return NULL;
179 }
180}
#define s(width, name)
Definition cbs_vp9.c:198
#define NULL
Definition coverity.c:32
void checkasm_set_signal_handler_state(const int enabled)
Enable or disable signal handling.
Definition signal.c:52
jmp_buf checkasm_jmp_buf
Definition longjmp.h:66
#define checkasm_load_context(ctx)
Definition longjmp.h:68
static void signal_handler(const int s)
Definition signal.c:122
static void interrupt_handler(const int s)
Definition signal.c:57
static volatile sig_atomic_t sig
Definition signal.c:48
const char * checkasm_get_last_signal_desc(void)
Definition signal.c:167
COLD void checkasm_set_signal_handlers(void)
Definition signal.c:132
Test writing API for checkasm.
checkasm_jmp_buf checkasm_context
Definition signal.c:46
#define COLD
Definition internal.h:45
volatile sig_atomic_t checkasm_interrupted
Definition signal.c:50