WG14 threadsafe signals
Loading...
Searching...
No Matches
thrd_signal_handle.h
Go to the documentation of this file.
1/* Proposed WG14 improved signals support
2(C) 2025 - 2026 Niall Douglas <http://www.nedproductions.biz/>
3File Created: Feb 2025
4
5
6Licensed under the Apache License, Version 2.0 (the "License");
7you may not use this file except in compliance with the License.
8You may obtain a copy of the License in the accompanying file
9Licence.txt or at
10
11http://www.apache.org/licenses/LICENSE-2.0
12
13Unless required by applicable law or agreed to in writing, software
14distributed under the License is distributed on an "AS IS" BASIS,
15WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16See the License for the specific language governing permissions and
17limitations under the License.
18*/
19
20#ifndef WG14_SIGNALS_THREAD_LOCAL_SIGNAL_HANDLE_H
21#define WG14_SIGNALS_THREAD_LOCAL_SIGNAL_HANDLE_H
22
23#include "config.h"
24
25#include <signal.h>
26#include <stdbool.h>
27#include <stdint.h>
28
29#if __GLIBC__
30// glibc defines a userspace siginfo_t as an unnamed struct. No
31// choice here but to drag in the relevant header.
32#include <bits/types/siginfo_t.h>
33#endif
34
35
36#ifdef __cplusplus
37extern "C"
38{
39#endif
40
41#ifdef _WIN32
42 // MSVC may be missing necessary signal support, so the sigset helpers are
43 // defined here. The N3924 synopses (7.14.2.1/7.14.2.2) declare
44 // sigemptyset/sigfillset/sigaddset/sigdelset as `int` "always returns zero"
45 // and sigismember as "positive one if set, zero if not", so these match the
46 // proposal exactly. On POSIX the four `int` helpers are the host libc's (from
47 // <signal.h>), which follow the POSIX contract -- 0 on success, but -1 with
48 // errno = EINVAL for an out-of-range signo in sigaddset/sigdelset -- a
49 // documented divergence from the proposal's "always returns zero" that only
50 // matters for out-of-range input (plans/analysis.md VSDT).
51 typedef uint32_t sigset_t;
52 static inline int sigemptyset(sigset_t *ss)
53 {
54 *ss = 0;
55 return 0;
56 }
57 static inline int sigfillset(sigset_t *ss)
58 {
59 *ss = UINT32_MAX;
60 return 0;
61 }
62 // The shifts below are bounds-checked against the 32-signal bit set
63 // (analysis.md 4.5): for signo outside [1, 32], 1u << (signo - 1) is
64 // undefined behaviour. sigaddset/sigdelset become no-ops out of range (and
65 // still "always return zero", matching the proposal rather than the POSIX
66 // -1/EINVAL divergence); sigismember is kept total (returns false) so the
67 // Windows sigfillset_* lazy-init checks never read a torn set
68 // (plans/ideas.md 4.3). These helpers run in signal-handler context too, so
69 // no error reporting.
70 static inline int sigaddset(sigset_t *ss, const int signo)
71 {
72 if(signo >= 1 && signo <= 32)
73 {
74 *ss |= (1u << (signo - 1));
75 }
76 return 0;
77 }
78 static inline int sigdelset(sigset_t *ss, const int signo)
79 {
80 if(signo >= 1 && signo <= 32)
81 {
82 *ss &= ~(1u << (signo - 1));
83 }
84 return 0;
85 }
86 static inline bool sigismember(const sigset_t *ss, const int signo)
87 {
88 return (signo >= 1 && signo <= 32) && (*ss & (1u << (signo - 1))) != 0;
89 }
90
91 // The 32-signal bit-set scheme above (sigfillset == UINT32_MAX, shifts
92 // 1..32, plans/ideas.md 4.3) requires the redefinition to be at least 32
93 // bits wide; fail the build if it ever shrinks (plans/ideas.md 4.2).
94 WG14_SIGNALS_STATIC_ASSERT((sizeof(sigset_t) >= sizeof(uint32_t)),
95 "wg14_signals: Windows sigset_t must be at least "
96 "32 bits to hold the 32-signal bit set");
97
98// MSVC appears to follow the Linux signal numbering
99#ifndef SIGBUS
100#define SIGBUS (7)
101#endif
102#ifndef SIGKILL
103#define SIGKILL (9)
104#endif
105#ifndef SIGSTOP
106#define SIGSTOP (19)
107#endif
108#endif
109
110#ifndef WG14_SIGNALS_DISABLE_SIGFENCE_MACRO
111#define WG14_SIGNALS_SIGFENCE_GLUE(x, y) x y
112#define WG14_SIGNALS_SIGFENCE_RETURN_ARG_COUNT(_1_, _2_, _3_, _4_, _5_, _6_, \
113 _7_, _8_, count, ...) \
114 count
115#define WG14_SIGNALS_SIGFENCE_EXPAND_ARGS(args) \
116 WG14_SIGNALS_SIGFENCE_RETURN_ARG_COUNT args
117
118// The argument counting below uses __VA_OPT__ only for the zero-argument
119// sigfence() form (the comma-suppression case it exists for). __VA_OPT__ is
120// C23/C++20, provided as an extension by GCC/Clang in all modes and by MSVC's
121// conforming preprocessor in C++20 and C11/C17 modes only. MSVC in C++14/17
122// mode has no __VA_OPT__ at all, so use a plain comma-list counting there:
123// it dispatches 1..8 arguments correctly (and the compile-time assert below
124// checks exactly those), while the zero-argument sigfence() form is
125// unavailable on such compilers (plans/analysis.md 4.10).
126#if defined(__GNUC__) || defined(__clang__)
127#define WG14_SIGNALS_HAVE_VA_OPT 1
128#elif defined(_MSC_VER) && defined(_MSVC_TRADITIONAL) && \
129(0 == _MSVC_TRADITIONAL)
130#if defined(__cplusplus)
131#if defined(_MSVC_LANG) && (_MSVC_LANG >= 202002L)
132#define WG14_SIGNALS_HAVE_VA_OPT 1
133#endif
134#else
135#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
136#define WG14_SIGNALS_HAVE_VA_OPT 1
137#endif
138#endif
139#endif
140#ifdef WG14_SIGNALS_HAVE_VA_OPT
141#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...) \
142 WG14_SIGNALS_SIGFENCE_EXPAND_ARGS( \
143 (__VA_ARGS__ __VA_OPT__(, ) 8, 7, 6, 5, 4, 3, 2, 1, 0))
144#else
145#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...) \
146 WG14_SIGNALS_SIGFENCE_EXPAND_ARGS((__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0))
147#endif
148#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO2(name, count) name##count
149#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO1(name, count) \
150 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO2(name, count)
151#define WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO(name, count) \
152 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO1(name, count)
153#define WG14_SIGNALS_SIGFENCE_CALL_OVERLOAD(name, ...) \
154 WG14_SIGNALS_SIGFENCE_GLUE( \
155 WG14_SIGNALS_SIGFENCE_OVERLOAD_MACRO( \
156 name, WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(__VA_ARGS__)), \
157 (__VA_ARGS__))
158
159 // The arg counting above depends on __VA_OPT__ (C23/C++20, supported as a
160 // GNU/Clang/MSVC extension in older modes). Verify at compile time that the
161 // counting machinery returns the right counts: on a compiler without
162 // __VA_OPT__ the expansion below is a hard preprocessing error, and on a
163 // compiler whose counting is broken the assertion fails — either way the
164 // defect surfaces instead of silently mis-dispatching. (The zero-argument
165 // path — the comma-suppression case __VA_OPT__ exists for — is exercised by
166 // test/sigfence_fence_test.c, whose TU suppresses the -Wpedantic diagnostic
167 // that an empty variadic-macro call triggers; a public header must not.
168 // The counts asserted here — 3 and 5 — are in the 1..8 range that the
169 // non-__VA_OPT__ fallback counting also handles, so the assert is valid on
170 // every supported compiler, including MSVC C++14/17.)
172 ((WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(a, b, c) == 3) &&
173 (WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(a, b, c, d, e) == 5)),
174 "wg14_signals: sigfence() argument counting is broken (requires __VA_OPT__ "
175 "on this compiler, or a counting-broken preprocessor)");
176
177#if (defined(__GNUC__) || defined(__clang__)) && !defined(DISABLE_INLINE_ASM)
178// On compilers with extended inline asm, we can tell the compiler that a
179// specific list of variables must be specifically written out and reloaded
180// around the fence. You may find https://godbolt.org/z/chh8ee6Mj useful to
181// review. DISABLE_INLINE_ASM (defined by cmake/filc-toolchain.cmake for the
182// Fil-C memory-safe compiler) selects the portable volatile-sink fallback
183// below instead, because Fil-C cannot compile these asm forms (analysis.md
184// AA2).
185#define WG14_SIGNALS_SIGFENCE_IMPL_0() __asm__ volatile(";" : : : "memory")
186#define WG14_SIGNALS_SIGFENCE_IMPL_1(a) \
187 __asm__ volatile(";" : "+m"(a) : : "memory")
188#define WG14_SIGNALS_SIGFENCE_IMPL_2(a, b) \
189 __asm__ volatile(";" : "+m"(a), "+m"(b) : : "memory")
190#define WG14_SIGNALS_SIGFENCE_IMPL_3(a, b, c) \
191 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c) : : "memory")
192#define WG14_SIGNALS_SIGFENCE_IMPL_4(a, b, c, d) \
193 __asm__ volatile(";" : "+m"(a), "+m"(b), "+m"(c), "+m"(d) : : "memory")
194#define WG14_SIGNALS_SIGFENCE_IMPL_5(a, b, c, d, e) \
195 __asm__ volatile(";" \
196 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e) \
197 : \
198 : "memory")
199#define WG14_SIGNALS_SIGFENCE_IMPL_6(a, b, c, d, e, f) \
200 __asm__ volatile(";" \
201 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f) \
202 : \
203 : "memory")
204#define WG14_SIGNALS_SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
205 __asm__ volatile(";" \
206 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
207 "+m"(g) \
208 : \
209 : "memory")
210#define WG14_SIGNALS_SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
211 __asm__ volatile(";" \
212 : "+m"(a), "+m"(b), "+m"(c), "+m"(d), "+m"(e), "+m"(f), \
213 "+m"(g), "+m"(h) \
214 : \
215 : "memory")
216#else
217 // Compilers without extended inline asm (e.g. MSVC), or with it disabled via
218 // -DDISABLE_INLINE_ASM (Fil-C): force the listed local variables to be
219 // memory-resident, and their values reloaded afterwards, as the "+m" operands
220 // and "memory" clobber above do.
221 // WG14_SIGNALS_SIGFENCE_ESCAPE() (1) stores each variable's address into a
222 // volatile sink so the address escapes to observable memory, and (2) performs
223 // a volatile read of one byte of the object -- char may alias any object
224 // (C11 6.5p7), and volatile accesses are observable behaviour (C11 5.1.2.3),
225 // so no optimizer, link-time code generation (/GL /LTCG) included, may
226 // eliminate or reorder them: the value is committed to memory before the
227 // fence and must be reloaded after it. No out-of-line function is needed, so
228 // the fence cannot be defeated by the optimizer inlining a helper away, and
229 // the sink is per-TU static, so header-only consumers need no library
230 // symbols.
231 static void *volatile WG14_SIGNALS_PREFIX(sigfence_sink)[9];
232#define WG14_SIGNALS_SIGFENCE_BARRIER() \
233 ((void) (WG14_SIGNALS_PREFIX(sigfence_sink)[8] = \
234 WG14_SIGNALS_PREFIX(sigfence_sink)[8]))
235#define WG14_SIGNALS_SIGFENCE_ESCAPE(a, i) \
236 do \
237 { \
238 WG14_SIGNALS_PREFIX(sigfence_sink)[(i)] = (void *) &(a); \
239 (void) *(volatile unsigned char *) &(a); \
240 } while(0)
241#define WG14_SIGNALS_SIGFENCE_IMPL_0() WG14_SIGNALS_SIGFENCE_BARRIER()
242#define WG14_SIGNALS_SIGFENCE_IMPL_1(a) \
243 do \
244 { \
245 WG14_SIGNALS_SIGFENCE_BARRIER(); \
246 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
247 WG14_SIGNALS_SIGFENCE_BARRIER(); \
248 } while(0)
249#define WG14_SIGNALS_SIGFENCE_IMPL_2(a, b) \
250 do \
251 { \
252 WG14_SIGNALS_SIGFENCE_BARRIER(); \
253 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
254 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
255 WG14_SIGNALS_SIGFENCE_BARRIER(); \
256 } while(0)
257#define WG14_SIGNALS_SIGFENCE_IMPL_3(a, b, c) \
258 do \
259 { \
260 WG14_SIGNALS_SIGFENCE_BARRIER(); \
261 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
262 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
263 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
264 WG14_SIGNALS_SIGFENCE_BARRIER(); \
265 } while(0)
266#define WG14_SIGNALS_SIGFENCE_IMPL_4(a, b, c, d) \
267 do \
268 { \
269 WG14_SIGNALS_SIGFENCE_BARRIER(); \
270 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
271 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
272 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
273 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
274 WG14_SIGNALS_SIGFENCE_BARRIER(); \
275 } while(0)
276#define WG14_SIGNALS_SIGFENCE_IMPL_5(a, b, c, d, e) \
277 do \
278 { \
279 WG14_SIGNALS_SIGFENCE_BARRIER(); \
280 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
281 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
282 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
283 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
284 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
285 WG14_SIGNALS_SIGFENCE_BARRIER(); \
286 } while(0)
287#define WG14_SIGNALS_SIGFENCE_IMPL_6(a, b, c, d, e, f) \
288 do \
289 { \
290 WG14_SIGNALS_SIGFENCE_BARRIER(); \
291 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
292 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
293 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
294 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
295 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
296 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
297 WG14_SIGNALS_SIGFENCE_BARRIER(); \
298 } while(0)
299#define WG14_SIGNALS_SIGFENCE_IMPL_7(a, b, c, d, e, f, g) \
300 do \
301 { \
302 WG14_SIGNALS_SIGFENCE_BARRIER(); \
303 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
304 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
305 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
306 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
307 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
308 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
309 WG14_SIGNALS_SIGFENCE_ESCAPE(g, 6); \
310 WG14_SIGNALS_SIGFENCE_BARRIER(); \
311 } while(0)
312#define WG14_SIGNALS_SIGFENCE_IMPL_8(a, b, c, d, e, f, g, h) \
313 do \
314 { \
315 WG14_SIGNALS_SIGFENCE_BARRIER(); \
316 WG14_SIGNALS_SIGFENCE_ESCAPE(a, 0); \
317 WG14_SIGNALS_SIGFENCE_ESCAPE(b, 1); \
318 WG14_SIGNALS_SIGFENCE_ESCAPE(c, 2); \
319 WG14_SIGNALS_SIGFENCE_ESCAPE(d, 3); \
320 WG14_SIGNALS_SIGFENCE_ESCAPE(e, 4); \
321 WG14_SIGNALS_SIGFENCE_ESCAPE(f, 5); \
322 WG14_SIGNALS_SIGFENCE_ESCAPE(g, 6); \
323 WG14_SIGNALS_SIGFENCE_ESCAPE(h, 7); \
324 WG14_SIGNALS_SIGFENCE_BARRIER(); \
325 } while(0)
326#endif
329#define sigfence(...) \
330 WG14_SIGNALS_SIGFENCE_CALL_OVERLOAD(WG14_SIGNALS_SIGFENCE_IMPL_, __VA_ARGS__)
331#endif
332
333#ifdef _MSC_VER
334#pragma warning(push)
335#pragma warning(disable : 4190) // C-linkage with UDTs
336#endif
337#if defined(__clang__) && defined(__cplusplus)
338#pragma clang diagnostic push
339#pragma clang diagnostic ignored "-Wreturn-type-c-linkage"
340#endif
341
345 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
346 {
347 intptr_t int_value;
349#if defined(__cplusplus)
350 constexpr WG14_SIGNALS_PREFIX(stdc_siginfo_value)()
351 : int_value(0)
352 {
353 }
354 constexpr WG14_SIGNALS_PREFIX(stdc_siginfo_value)(int v)
355 : int_value(v)
356 {
357 }
358 constexpr WG14_SIGNALS_PREFIX(stdc_siginfo_value)(void *v)
359 : ptr_value(v)
360 {
361 }
362#endif
363 };
364
365#ifdef _WIN32
366 typedef long WG14_SIGNALS_PREFIX(stdc_siginfo_error_code_t);
367#else
368typedef int WG14_SIGNALS_PREFIX(stdc_siginfo_error_code_t);
369#endif
370
373#ifdef _WIN32
374 typedef struct _EXCEPTION_RECORD WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t);
375#elif __GLIBC__
376typedef siginfo_t WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t);
377#elif defined(__FILC__)
378// Fil-C's libc siginfo_t is its own complete type, unrelated to the
379// struct __siginfo that other POSIX libcs expose, so forward-declaring that
380// struct would make every siginfo interaction in the POSIX backend a
381// compile-time error. Alias directly to the type the signal handler receives.
382typedef siginfo_t WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t);
383#elif __ANDROID__
384typedef struct siginfo WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t);
385#else
386typedef struct __siginfo WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t);
387#endif
388
391#ifdef _WIN32
392 typedef struct _CONTEXT WG14_SIGNALS_PREFIX(stdc_siginfo_context_t);
393#else
394typedef ucontext_t WG14_SIGNALS_PREFIX(stdc_siginfo_context_t);
395#endif
396
397 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t);
398 struct WG14_SIGNALS_PREFIX(sighandler_info);
399 struct WG14_SIGNALS_PREFIX(global_signal_decider_t);
400
404 struct WG14_SIGNALS_PREFIX(stdc_siginfo)
405 {
406 int signo;
407
412 void *addr;
414 union WG14_SIGNALS_PREFIX(
416
418 WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t) * raw_info;
420 WG14_SIGNALS_PREFIX(stdc_siginfo_context_t) * raw_context;
425
426 // Used internally only
427 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t) *
429 struct WG14_SIGNALS_PREFIX(sighandler_info) * internal_sighandler;
430 struct WG14_SIGNALS_PREFIX(global_signal_decider_t) *
432#ifdef _WIN32
433 void *internal_win_state;
434#endif
436 };
437
439 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
440 sig_func_t))(union WG14_SIGNALS_PREFIX(stdc_siginfo_value));
441
444 typedef union WG14_SIGNALS_PREFIX(stdc_siginfo_value)(WG14_SIGNALS_PREFIX(
445 sig_recover_t))(const struct WG14_SIGNALS_PREFIX(stdc_siginfo) *);
446
448 enum WG14_SIGNALS_PREFIX(sig_decision_t)
449 {
451 WG14_SIGNALS_PREFIX(sig_decision_next_decider),
453 WG14_SIGNALS_PREFIX(sig_decision_resume_execution),
457 WG14_SIGNALS_PREFIX(sig_decision_call_recovery)
458 };
459
462 typedef enum WG14_SIGNALS_PREFIX(sig_decision_t)(WG14_SIGNALS_PREFIX(
463 sig_decide_t))(struct WG14_SIGNALS_PREFIX(stdc_siginfo) *);
464
481 WG14_SIGNALS_PREFIX(sigfillset_synchronous)(sigset_t *set);
482
510 WG14_SIGNALS_PREFIX(sigfillset_asynchronous_nondebug)(sigset_t *set);
511
526 WG14_SIGNALS_PREFIX(sigfillset_asynchronous_debug)(sigset_t *set);
527
553 WG14_SIGNALS_EXTERN union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
554 WG14_SIGNALS_PREFIX(sigguarded)(const sigset_t *signals,
555 WG14_SIGNALS_PREFIX(sig_func_t) guarded,
556 WG14_SIGNALS_PREFIX(sig_recover_t) recovery,
557 WG14_SIGNALS_PREFIX(sig_decide_t) decider,
558 union WG14_SIGNALS_PREFIX(stdc_siginfo_value)
559 value);
560
561 struct WG14_SIGNALS_PREFIX(sig_global_state_tss_state_per_frame_t);
562
574 WG14_SIGNALS_EXTERN void WG14_SIGNALS_PREFIX(sigdecider_abandon)(
575 struct WG14_SIGNALS_PREFIX(stdc_siginfo) * rsi);
576
584 struct WG14_SIGNALS_PREFIX(stdc_siginfo) * rsi);
585
586#if defined(__clang__) && defined(__cplusplus)
587#pragma clang diagnostic pop
588#endif
589#ifdef _MSC_VER
590#pragma warning(pop)
591#endif
592
624 WG14_SIGNALS_EXTERN bool WG14_SIGNALS_PREFIX(stdc_raise)(
625 int signo, WG14_SIGNALS_PREFIX(stdc_siginfo_siginfo_t) * raw_info,
626 WG14_SIGNALS_PREFIX(stdc_siginfo_context_t) * raw_context);
627
654 WG14_SIGNALS_PREFIX(siginstall)(const sigset_t *guarded);
657 WG14_SIGNALS_EXTERN int WG14_SIGNALS_PREFIX(siguninstall)(void *i);
660 WG14_SIGNALS_EXTERN int WG14_SIGNALS_PREFIX(siguninstall_system)(int version);
661
681 WG14_SIGNALS_EXTERN void *WG14_SIGNALS_PREFIX(signal_decider_create)(
682 const sigset_t *guarded, bool callfirst,
683 WG14_SIGNALS_PREFIX(sig_decide_t) decider,
684 union WG14_SIGNALS_PREFIX(stdc_siginfo_value) value);
694 WG14_SIGNALS_PREFIX(signal_decider_destroy)(void *decider);
695
696
697#ifdef __cplusplus
698}
699#endif
700
701#if WG14_SIGNALS_ENABLE_HEADER_ONLY
702#ifdef _WIN32
703#include "detail/impl/thrd_signal_handle_windows.c.ipp"
704#else
705#include "detail/impl/thrd_signal_handle_posix.c.ipp"
706#endif
707#endif
708
709
710#endif
#define WG14_SIGNALS_STATIC_ASSERT(cond, msg)
Compile-time assertion, spelled _Static_assert in C11 and static_assert in C++11 (plans/ideas....
Definition config.h:39
#define WG14_SIGNALS_EXTERN
Definition config.h:128
A platform independent subset of siginfo_t.
int signo
The signal raised.
stdc_siginfo_context_t * raw_context
The OS specific ucontext_t (POSIX) or PCONTEXT (Windows).
struct sig_global_state_tss_state_per_frame_t * internal_local_decider
struct global_signal_decider_t * internal_global_decider
struct sighandler_info * internal_sighandler
bool internal_decider_is_abandoned
stdc_siginfo_error_code_t error_code
The system specific error code for this signal, the si_errno code (POSIX) or NTSTATUS code (Windows)....
union stdc_siginfo_value value
A user-defined value.
stdc_siginfo_siginfo_t * raw_info
The OS specific signal info.
int sigfillset_asynchronous_nondebug(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fills the set of non-debug asynchronous signals for this platform.
struct __siginfo stdc_siginfo_siginfo_t
A placeholder type for an OS specific siginfo_t * (POSIX) or PEXCEPTION_RECORD (Windows).
void * siginstall(const sigset_t *guarded)
THREADSAFE Installs, and potentially enables, the global signal handlers for the signals specified by...
#define WG14_SIGNALS_SIGFENCE_COUNT_ARGS_MAX8(...)
void sigdecider_abandon_resume(struct stdc_siginfo *rsi)
THREADSAFE ASYNC-SIGNAL-SAFE Undoes a prior call of sigdecider_abandon(). Do not call except from the...
enum sig_decision_t sig_decide_t(struct stdc_siginfo *)
The type of the function called when a signal is raised. Returns a decision of how to handle the sign...
union stdc_siginfo_value sig_func_t(union stdc_siginfo_value)
The type of the guarded function.
int siguninstall(void *i)
THREADSAFE Uninstall a previously installed signal guard.
int stdc_siginfo_error_code_t
Typedef to a system specific error code type.
sig_decision_t
The decision taken by the decider function.
@ sig_decision_call_recovery
Thread local signal deciders only: reset the stack and local state to entry to sigguarded(),...
@ sig_decision_resume_execution
We have fixed the cause of the signal, please resume execution.
@ sig_decision_next_decider
We have decided to do nothing.
void * signal_decider_create(const sigset_t *guarded, bool callfirst, sig_decide_t decider, union stdc_siginfo_value value)
THREADSAFE NOT REENTRANT Create a global signal continuation decider. Threadsafe with respect to othe...
int sigfillset_asynchronous_debug(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fille the set of debug asynchronous signals for this platform.
bool stdc_raise(int signo, stdc_siginfo_siginfo_t *raw_info, stdc_siginfo_context_t *raw_context)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Call OUR currently installed signal decider for a signal (POSIX)...
int signal_decider_destroy(void *decider)
THREADSAFE NOT REENTRANT Destroy a global signal continuation decider. Threadsafe with respect to oth...
int sigfillset_synchronous(sigset_t *set)
THREADSAFE ASYNC-SIGNAL-SAFE Fills the set of synchronous signals for this platform.
ucontext_t stdc_siginfo_context_t
A placeholder type for an OS specific ucontext_t (POSIX) or PCONTEXT (Windows).
union stdc_siginfo_value sigguarded(const sigset_t *signals, sig_func_t guarded, sig_recover_t recovery, sig_decide_t decider, union stdc_siginfo_value value)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Installs a thread-local signal guard for the calling thread,...
void sigdecider_abandon(struct stdc_siginfo *rsi)
THREADSAFE ASYNC-SIGNAL-SAFE Lets the decider machinery know you won't be returning into it....
union stdc_siginfo_value sig_recover_t(const struct stdc_siginfo *)
The type of the function called to recover from a signal being raised in a guarded section.
int siguninstall_system(int version)
THREADSAFE Uninstall a previously system installed signal guard.
User defined value.