Skip to content

Commit c044a9d

Browse files
committed
Added _Thread_local, fixed NO_THROW
1 parent a731928 commit c044a9d

File tree

3 files changed

+42
-40
lines changed

3 files changed

+42
-40
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Try-Catch blocks for C
22

3-
Small experiment that simulates try-catch blocks in C using `setjmp`/`longjmp`. Please note that it doesn't support nested try blocks and it is not thread safe.
3+
Small experiment that simulates try-catch blocks in C using `setjmp`/`longjmp`. Please note that it doesn't support nested try blocks and it is not thread safe. Throwing outside of try blocks has undefined behaviour unless `NO_THROW` is defined. **Signals that are not caught will not stop the program and will lead to the execution being continued normally after the try block.**
44

55
It can handle exceptions and signals. It can simulate the functionality of `try`, `catch(exception)`, `catch(signal)`, `catch_all` and `finally`. It has rudimentary support for tracing the signals and exceptions, showing where and when they happened. Throws and retries can be turned off.
66

trycatch.c

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
#include <signal.h>
22
#include "trycatch.h"
33

4-
jmp_buf _catch_jmp_buf = { 0 };
5-
jmp_buf _retry_jmp_buf = { 0 };
6-
int _catch_value = 0;
7-
volatile bool _retry_attempt = false;
8-
volatile bool _init_signals = false;
9-
volatile bool _throw_enabled = true;
4+
_Thread_local jmp_buf _catch_jmp_buf = { 0 };
5+
_Thread_local int _catch_value = 0;
6+
_Thread_local volatile bool _retry_attempt = false;
7+
_Thread_local volatile bool _init_signals = false;
108

11-
volatile bool _trextrigger = false;
12-
volatile const char *_trexfile = "";
13-
volatile const char *_trexfunc = "";
14-
volatile unsigned long _trexline = 0;
15-
volatile int _trex = 0;
9+
_Thread_local volatile bool _trextrigger = false;
10+
_Thread_local volatile const char *_trexfile = "";
11+
_Thread_local volatile const char *_trexfunc = "";
12+
_Thread_local volatile unsigned long _trexline = 0;
13+
_Thread_local volatile int _trex = 0;
1614

1715
const char *_exception_string[] = {
1816
"EX_OVERFLOW",
@@ -31,11 +29,6 @@ const char *_exception_string[] = {
3129
};
3230

3331
void _catch_sig_handle(int sig) {
34-
if (!_throw_enabled) {
35-
signal(sig, SIG_DFL);
36-
return;
37-
}
38-
3932
switch (sig) {
4033
case SIGFPE:
4134
throw(EX_SIGFPE);
@@ -49,10 +42,10 @@ void _catch_sig_handle(int sig) {
4942
throw(EX_SIGINT);
5043
case SIGTERM:
5144
throw(EX_SIGTERM);
52-
#ifdef SIGCONT
45+
#ifdef SIGCONT
5346
case SIGCONT:
5447
return;
55-
#endif
48+
#endif
5649
default:
5750
signal(sig, SIG_DFL);
5851
return;

trycatch.h

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,20 @@ extern const char *_exception_string[];
3131

3232
#define SIG_MAX 0x20
3333

34-
extern jmp_buf _catch_jmp_buf;
35-
extern int _catch_value;
36-
extern volatile bool _retry_attempt;
37-
extern volatile bool _init_signals;
34+
extern _Thread_local jmp_buf _catch_jmp_buf;
35+
extern _Thread_local int _catch_value;
36+
extern _Thread_local volatile bool _retry_attempt;
37+
extern _Thread_local volatile bool _init_signals;
3838

39-
extern volatile bool _trextrigger;
40-
extern volatile const char *_trexfile;
41-
extern volatile const char *_trexfunc;
42-
extern volatile unsigned long _trexline;
43-
extern volatile int _trex;
39+
extern _Thread_local volatile bool _trextrigger;
40+
extern _Thread_local volatile const char *_trexfile;
41+
extern _Thread_local volatile const char *_trexfunc;
42+
extern _Thread_local volatile unsigned long _trexline;
43+
extern _Thread_local volatile int _trex;
4444

4545
void _catch_sig_handle(int);
4646

47-
#define _do_nothing() \
47+
#define _do_nothing() \
4848
do { /* nothing */ } while (false)
4949

5050
#define _trace_prepare(X) \
@@ -79,12 +79,20 @@ void _catch_sig_handle(int);
7979
#define _trace_if_triggered() _do_nothing()
8080
#endif
8181

82+
#ifndef NO_THROW
83+
#define _bind_signals() \
84+
do { \
85+
for (uint8_t i = 1; i < SIG_MAX; i++) \
86+
signal(i, _catch_sig_handle); \
87+
_init_signals = true; \
88+
} while (false)
89+
#else
90+
#define _bind_signals() _do_nothing()
91+
#endif
92+
8293
#define try \
83-
if (!_init_signals) { \
84-
for (uint8_t i = 1; i < SIG_MAX; i++) \
85-
signal(i, _catch_sig_handle); \
86-
_init_signals = true; \
87-
} \
94+
if (!_init_signals) \
95+
_bind_signals(); \
8896
_catch_value = setjmp(_catch_jmp_buf); \
8997
_trace_if_triggered(); \
9098
if (_retry_attempt) { \
@@ -93,21 +101,22 @@ void _catch_sig_handle(int);
93101
} \
94102
if (!_catch_value)
95103

96-
#define catch_all \
97-
else
98-
99104
#define finally \
100105
if (_catch_value == 0)
101106

102107
#ifndef NO_THROW
103-
#define catch(X) \
108+
#define catch(X) \
104109
else if (_catch_value == X)
105110

106-
#define throw(X) \
107-
do { _trace_prepare(X); \
111+
#define throw(X) \
112+
do { _trace_prepare(X); \
108113
longjmp(_catch_jmp_buf, X); } while (false)
114+
115+
#define catch_all \
116+
else
109117
#else
110118
#define catch(X) else if (false)
119+
#define catch_all else if (false)
111120
#define throw(X) _do_nothing()
112121
#endif
113122

0 commit comments

Comments
 (0)