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 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
43 typedef uint32_t sigset_t;
44 static inline void sigemptyset(sigset_t *ss)
45 {
46 *ss = 0;
47 }
48 static inline void sigfillset(sigset_t *ss)
49 {
50 *ss = UINT32_MAX;
51 }
52 static inline void sigaddset(sigset_t *ss, const int signo)
53 {
54 *ss |= (1u << (signo - 1));
55 }
56 static inline void sigdelset(sigset_t *ss, const int signo)
57 {
58 *ss &= ~(1u << (signo - 1));
59 }
60 static inline bool sigismember(const sigset_t *ss, const int signo)
61 {
62 return (*ss & (1u << (signo - 1))) != 0;
63 }
64
65// MSVC appears to follow the Linux signal numbering
66#ifndef SIGBUS
67#define SIGBUS (7)
68#endif
69#ifndef SIGKILL
70#define SIGKILL (9)
71#endif
72#ifndef SIGSTOP
73#define SIGSTOP (19)
74#endif
75#endif
76
80 union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)
81 {
82 intptr_t int_value;
83 void *ptr_value;
84#if defined(__cplusplus)
85 constexpr WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)()
86 : int_value(0)
87 {
88 }
89 constexpr WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)(int v)
90 : int_value(v)
91 {
92 }
93 constexpr WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)(void *v)
94 : ptr_value(v)
95 {
96 }
97#endif
98 };
100#ifdef _WIN32
101 typedef long WG14_SIGNALS_PREFIX(thrd_raised_signal_error_code_t);
102#else
103typedef int WG14_SIGNALS_PREFIX(thrd_raised_signal_error_code_t);
104#endif
105
108#ifdef _WIN32
109 typedef struct _EXCEPTION_RECORD
110 WG14_SIGNALS_PREFIX(thrd_raised_signal_info_siginfo_t);
111#elif __GLIBC__
112typedef siginfo_t WG14_SIGNALS_PREFIX(thrd_raised_signal_info_siginfo_t);
113#else
114typedef struct __siginfo WG14_SIGNALS_PREFIX(thrd_raised_signal_info_siginfo_t);
115#endif
116
119#ifdef _WIN32
120 typedef struct _CONTEXT
121 WG14_SIGNALS_PREFIX(thrd_raised_signal_info_context_t);
122#else
123typedef struct ucontext_t
125#endif
126
130 struct WG14_SIGNALS_PREFIX(thrd_raised_signal_info)
131 {
132 int signo;
133
137 void *addr;
138 union WG14_SIGNALS_PREFIX(
140
145 };
146
148 typedef union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)(
149 WG14_SIGNALS_PREFIX(thrd_signal_func_t))(
150 union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value));
151
154 typedef union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)(
155 WG14_SIGNALS_PREFIX(thrd_signal_recover_t))(
156 const struct WG14_SIGNALS_PREFIX(thrd_raised_signal_info) *);
157
159 enum WG14_SIGNALS_PREFIX(thrd_signal_decision_t)
160 {
168 WG14_SIGNALS_PREFIX(thrd_signal_decision_invoke_recovery)
169 };
170
173 typedef enum WG14_SIGNALS_PREFIX(thrd_signal_decision_t)(WG14_SIGNALS_PREFIX(
174 thrd_signal_decide_t))(struct WG14_SIGNALS_PREFIX(thrd_raised_signal_info) *);
175
176#ifdef _MSC_VER
177#pragma warning(push)
178#pragma warning(disable : 4190) // C-linkage with UDTs
179#endif
195 WG14_SIGNALS_EXTERN const sigset_t *
196 WG14_SIGNALS_PREFIX(synchronous_sigset)(void);
197
224 WG14_SIGNALS_EXTERN const sigset_t *
225 WG14_SIGNALS_PREFIX(asynchronous_nondebug_sigset)(void);
226
240 WG14_SIGNALS_EXTERN const sigset_t *
241 WG14_SIGNALS_PREFIX(asynchronous_debug_sigset)(void);
242
263 WG14_SIGNALS_EXTERN union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value)
264 WG14_SIGNALS_PREFIX(thrd_signal_invoke)(
265 const sigset_t *signals, WG14_SIGNALS_PREFIX(thrd_signal_func_t) guarded,
266 WG14_SIGNALS_PREFIX(thrd_signal_recover_t) recovery,
267 WG14_SIGNALS_PREFIX(thrd_signal_decide_t) decider,
268 union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value) value);
269#ifdef _MSC_VER
270#pragma warning(pop)
271#endif
272
300 WG14_SIGNALS_EXTERN bool WG14_SIGNALS_PREFIX(thrd_signal_raise)(
301 int signo, WG14_SIGNALS_PREFIX(thrd_raised_signal_info_siginfo_t) * raw_info,
302 WG14_SIGNALS_PREFIX(thrd_raised_signal_info_context_t) * raw_context);
303
331 WG14_SIGNALS_PREFIX(threadsafe_signals_install)(const sigset_t *guarded,
332 int version);
336 WG14_SIGNALS_PREFIX(threadsafe_signals_uninstall)(void *i);
340 WG14_SIGNALS_PREFIX(threadsafe_signals_uninstall_system)(int version);
341
361 WG14_SIGNALS_EXTERN void *WG14_SIGNALS_PREFIX(signal_decider_create)(
362 const sigset_t *guarded, bool callfirst,
363 WG14_SIGNALS_PREFIX(thrd_signal_decide_t) decider,
364 union WG14_SIGNALS_PREFIX(thrd_raised_signal_info_value) value);
371 WG14_SIGNALS_PREFIX(signal_decider_destroy)(void *decider);
372
373
374#ifdef __cplusplus
375}
376#endif
377
378#endif
#define WG14_SIGNALS_EXTERN
Definition config.h:85
A platform independent subset of siginfo_t.
thrd_raised_signal_info_context_t * raw_context
The OS specific ucontext_t (POSIX) or PCONTEXT (Windows)
thrd_raised_signal_info_siginfo_t * raw_info
The OS specific signal info.
void * addr
Memory location which caused fault, if appropriate.
int signo
The signal raised.
thrd_raised_signal_error_code_t error_code
The system specific error code for this signal, the si_errno code (POSIX) or NTSTATUS code (Windows)
struct ucontext_t thrd_raised_signal_info_context_t
A placeholder type for an OS specific ucontext_t (POSIX) or PCONTEXT (Windows)
void * signal_decider_create(const sigset_t *guarded, bool callfirst, thrd_signal_decide_t decider, union thrd_raised_signal_info_value value)
THREADSAFE NOT REENTRANT Create a global signal continuation decider. Threadsafe with respect to othe...
const sigset_t * asynchronous_debug_sigset(void)
THREADSAFE ASYNC-SIGNAL-SAFE The set of debug asynchronous signals for this platform.
enum thrd_signal_decision_t() thrd_signal_decide_t(struct thrd_raised_signal_info *)
The type of the function called when a signal is raised. Returns a decision of how to handle the sign...
int threadsafe_signals_uninstall(void *i)
THREADSAFE Uninstall a previously installed signal guard.
thrd_signal_decision_t
The decision taken by the decider function.
@ thrd_signal_decision_invoke_recovery
Thread local signal deciders only: reset the stack and local state to entry to thrd_signal_invoke(),...
@ thrd_signal_decision_resume_execution
We have fixed the cause of the signal, please resume execution.
@ thrd_signal_decision_next_decider
We have decided to do nothing.
union thrd_raised_signal_info_value() thrd_signal_func_t(union thrd_raised_signal_info_value)
The type of the guarded function.
bool thrd_signal_raise(int signo, thrd_raised_signal_info_siginfo_t *raw_info, thrd_raised_signal_info_context_t *raw_context)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Call OUR currently installed signal decider for a signal (POSIX)...
struct __siginfo thrd_raised_signal_info_siginfo_t
A placeholder type for an OS specific siginfo_t * (POSIX) or PEXCEPTION_RECORD (Windows)
const sigset_t * synchronous_sigset(void)
THREADSAFE ASYNC-SIGNAL-SAFE The set of synchronous signals for this platform.
union thrd_raised_signal_info_value thrd_signal_invoke(const sigset_t *signals, thrd_signal_func_t guarded, thrd_signal_recover_t recovery, thrd_signal_decide_t decider, union thrd_raised_signal_info_value value)
THREADSAFE USUALLY ASYNC-SIGNAL-SAFE Installs a thread-local signal guard for the calling thread,...
int signal_decider_destroy(void *decider)
THREADSAFE NOT REENTRANT Destroy a global signal continuation decider. Threadsafe with respect to oth...
int thrd_raised_signal_error_code_t
Typedef to a system specific error code type.
union thrd_raised_signal_info_value() thrd_signal_recover_t(const struct thrd_raised_signal_info *)
The type of the function called to recover from a signal being raised in a guarded section.
int threadsafe_signals_uninstall_system(int version)
THREADSAFE Uninstall a previously system installed signal guard.
const sigset_t * asynchronous_nondebug_sigset(void)
THREADSAFE ASYNC-SIGNAL-SAFE The set of non-debug asynchronous signals for this platform.
void * threadsafe_signals_install(const sigset_t *guarded, int version)
THREADSAFE Installs, and potentially enables, the global signal handlers for the signals specified by...