-
Notifications
You must be signed in to change notification settings - Fork 0
/
exception.h
154 lines (138 loc) · 5.05 KB
/
exception.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
// Adds try/throw/except for catching signals
// Original code (c)Patricio Bonsembiante ([email protected])
// Released under the GPLv3+
// Updates (c)m1lkweed 2022 GPLv3+
#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_
#include <setjmp.h>
#include <signal.h>
struct exception_frame {
sigjmp_buf *frame;
volatile sig_atomic_t exception;
};
extern _Thread_local char _$exception_stack$[SIGSTKSZ];
extern _Thread_local struct exception_frame except_handler;
void _$except_init$(void);
void throw(int id);
#define try do{ \
sigjmp_buf *_$old_exception_frame$, _$new_exception_frame$; \
volatile int _$except_dummy$ = -1; \
typedef int _$except_no_gotos$[_$except_dummy$]; \
_$old_exception_frame$ = except_handler.frame; \
except_handler.frame = &_$new_exception_frame$; \
except_handler.exception = 0; \
_$except_init$(); \
if((except_handler.exception = sigsetjmp(_$new_exception_frame$, 0)) == 0){ \
for(_$except_dummy$ = 1; _$except_dummy$; --_$except_dummy$)
#define _$EXCEPT_EMPTY$_HELPER(...) = except_handler.exception __VA_OPT__(,) __VA_ARGS__
#define _$EXCEPT_EMPTY$(default, ...) default _$EXCEPT_EMPTY$_HELPER(__VA_ARGS__)
#define except(e) \
except_handler.exception = 0; \
}else{ \
_$EXCEPT_EMPTY$(_$except_dummy$, e) = except_handler.exception; \
} \
except_handler.frame = _$old_exception_frame$; \
}while(0);if(except_handler.exception == 0){}else for(struct{_Bool a;int \
_$except_no_gotos$[((void)1,0)];}_$inc$={};_$inc$.a;_$inc$.a=1)
#ifdef EXCEPTION_IMPLEMENTATION
#include <stddef.h>
_Thread_local char _$exception_stack$[SIGSTKSZ];
_Thread_local struct exception_frame except_handler = {0};
_Noreturn void _$exception_handler$(int signum){
if(except_handler.frame){
siglongjmp(*except_handler.frame, signum);
}else{
//Set handler to SIG_DFL and reraise signal, in case
//the system wants to print a message or core dump
struct sigaction old_action, new_action = {
.sa_handler = SIG_DFL,
.sa_flags = SA_NODEFER
};
sigaction(signum, NULL, &old_action);
sigaction(signum, &new_action, NULL);
raise(signum);
sigaction(signum, &old_action, NULL);
_Exit(128 + signum);
}
__builtin_unreachable();
}
[[gnu::constructor]] void _$except_init$(void){
stack_t _$exception_stack_wrapper$ = {
.ss_size = SIGSTKSZ,
.ss_sp = _$exception_stack$,
.ss_flags = 0
};
struct sigaction old_action, new_action = {
.sa_handler = _$exception_handler$,
.sa_flags = SA_NODEFER | SA_ONSTACK
};
sigaltstack(&_$exception_stack_wrapper$, NULL);
sigaction(SIGILL, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGILL, &new_action, NULL);
#ifdef SIGTRAP
sigaction(SIGTRAP, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGTRAP, &new_action, NULL);
#endif
sigaction(SIGABRT, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGABRT, &new_action, NULL);
#ifdef SIGBUS
sigaction(SIGBUS, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGBUS, &new_action, NULL);
#endif
sigaction(SIGFPE, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGFPE, &new_action, NULL);
sigaction(SIGSEGV, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGSEGV, &new_action, NULL);
#ifdef SIGPIPE
sigaction(SIGPIPE, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGPIPE, &new_action, NULL);
#endif
#ifdef SIGSTKFLT
sigaction(SIGSTKFLT, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGSTKFLT, &new_action, NULL);
#endif
#ifdef SIGURG
sigaction(SIGURG, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGURG, &new_action, NULL);
#endif
#ifdef SIGXFSZ
sigaction(SIGXFSZ, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGXFSZ, &new_action, NULL);
#endif
#ifdef SIGSYS
sigaction(SIGSYS, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGSYS, &new_action, NULL);
#endif
#ifdef SIGEMT
sigaction(SIGEMT, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGEMT, &new_action, NULL);
#endif
#ifdef SIGLOST
sigaction(SIGLOST, NULL, &old_action);
if(old_action.sa_handler == SIG_DFL)
sigaction(SIGLOST, &new_action, NULL);
#endif
}
[[maybe_unused]] void throw(int id){
if(id != 0){
except_handler.exception = id;
if(except_handler.frame)
siglongjmp(*except_handler.frame, id);
_$exception_handler$(id);
}
}
#endif //EXCEPTION_IMPLEMENTATION
#endif //_EXCEPTION_H_
/*--------------------------END OF TRY / EXCEPT CODE-------------------------*/