FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/tests/checkasm/ext/src/signal.c
Date: 2026-09-15 03:49:06
Exec Total Coverage
Lines: 12 34 35.3%
Functions: 2 5 40.0%
Branches: 3 15 20.0%

Line Branch Exec Source
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
46 checkasm_jmp_buf checkasm_context;
47
48 static volatile sig_atomic_t sig; // SIG_ATOMIC_MAX = signal handling enabled
49
50 volatile sig_atomic_t checkasm_interrupted;
51
52 376286 void checkasm_set_signal_handler_state(const int enabled)
53 {
54
2/2
✓ Branch 0 taken 188143 times.
✓ Branch 1 taken 188143 times.
376286 sig = enabled ? SIG_ATOMIC_MAX : 0;
55 376286 }
56
57 static void interrupt_handler(const int s)
58 {
59 checkasm_interrupted = s;
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;
65 checkasm_load_context(checkasm_context);
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)
75 static 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;
92 checkasm_load_context(checkasm_context);
93 }
94 return EXCEPTION_CONTINUE_SEARCH;
95 }
96 #endif
97
98 #elif HAVE_SIGACTION && defined(SA_RESETHAND)
99
100 static void signal_handler(int s);
101
102 static const struct sigaction interrupt_handler_act = {
103 .sa_handler = interrupt_handler,
104 .sa_flags = SA_RESETHAND,
105 };
106
107 static const struct sigaction signal_handler_act = {
108 .sa_handler = signal_handler,
109 .sa_flags = SA_RESETHAND,
110 };
111
112 static void signal_handler(const int s)
113 {
114 if (sig == SIG_ATOMIC_MAX) {
115 sig = s;
116 sigaction(s, &signal_handler_act, NULL);
117 checkasm_load_context(checkasm_context);
118 }
119 }
120 #else
121
122 static void signal_handler(const int s)
123 {
124 if (sig == SIG_ATOMIC_MAX) {
125 sig = s;
126 signal(s, signal_handler);
127 checkasm_load_context(checkasm_context);
128 }
129 }
130 #endif
131
132 98 COLD void checkasm_set_signal_handlers(void)
133 {
134 static int handlers_set;
135
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 98 times.
98 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 98 sigaction(SIGBUS, &signal_handler_act, NULL);
147 #endif
148 98 sigaction(SIGFPE, &signal_handler_act, NULL);
149 98 sigaction(SIGILL, &signal_handler_act, NULL);
150 98 sigaction(SIGSEGV, &signal_handler_act, NULL);
151 98 sigaction(SIGINT, &interrupt_handler_act, NULL);
152 98 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 98 handlers_set = 1;
165 }
166
167 const char *checkasm_get_last_signal_desc(void)
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 }
181