Skip to content

Commit 6389eef

Browse files
committed
Windows bug fixes - record signal, add reset func
- Tests show Windows was not rethrowing if exception was cause using `raise()` - always use `RaiseException` to throw
1 parent 91faf4c commit 6389eef

File tree

2 files changed

+104
-12
lines changed

2 files changed

+104
-12
lines changed

include/exception.h

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,9 @@ C_API void ex_signal(int sig, const char *ex);
162162
/* Convert signals into exceptions */
163163
C_API void ex_signal_setup(void);
164164

165+
/* Reset signal handler to default */
166+
C_API void ex_signal_default(void);
167+
165168
#ifdef _WIN32
166169
#define EXCEPTION_PANIC 0xE0000001
167170
C_API void ex_signal_seh(DWORD sig, const char *ex);
@@ -215,10 +218,6 @@ enum {
215218
#define ex_longjmp(buf,st) longjmp(buf,st)
216219
#endif
217220

218-
219-
#define rethrow() \
220-
ex_throw(ex_err.ex, ex_err.file, ex_err.line, ex_err.function, ex_err.panic)
221-
222221
#define ex_throw_loc(E, F, L, C) \
223222
do \
224223
{ \
@@ -237,13 +236,20 @@ throws an exception of given message. */
237236

238237
#ifdef _WIN32
239238
#define throw(E) raii_panic(EX_STR(E))
240-
#define ex_signal_block(ctrl) \
241-
CRITICAL_SECTION ctrl##__FUNCTION__; \
239+
240+
#define rethrow() \
241+
if (ex_err.caught > -1) \
242+
ex_err.state = ex_throw_st; \
243+
else \
244+
ex_throw(ex_err.ex, ex_err.file, ex_err.line, ex_err.function, ex_err.panic)
245+
246+
#define ex_signal_block(ctrl) \
247+
CRITICAL_SECTION ctrl##__FUNCTION__; \
242248
InitializeCriticalSection(&ctrl##__FUNCTION__); \
243249
EnterCriticalSection(&ctrl##__FUNCTION__);
244250

245-
#define ex_signal_unblock(ctrl) \
246-
LeaveCriticalSection(&ctrl##__FUNCTION__); \
251+
#define ex_signal_unblock(ctrl) \
252+
LeaveCriticalSection(&ctrl##__FUNCTION__); \
247253
DeleteCriticalSection(&ctrl##__FUNCTION__);
248254

249255
#define ex_try \
@@ -306,6 +312,7 @@ throws an exception of given message. */
306312
if (ex_context == &ex_err) \
307313
/* global context updated */ \
308314
ex_context = ex_err.next; \
315+
ex_err.caught = -1; \
309316
if ((ex_err.state & ex_throw_st) != 0) \
310317
rethrow(); \
311318
}
@@ -321,6 +328,9 @@ throws an exception of given message. */
321328
#define ex_signal_unblock(ctrl) \
322329
pthread_sigmask(SIG_SETMASK, &ctrl_all##__FUNCTION__, NULL);
323330

331+
#define rethrow() \
332+
ex_throw(ex_err.ex, ex_err.file, ex_err.line, ex_err.function, ex_err.panic)
333+
324334
#define throw(E) \
325335
ex_throw_loc(E, __FILE__, __LINE__, __FUNCTION__)
326336
#define ex_try \
@@ -400,6 +410,7 @@ struct ex_context_s {
400410
void *data;
401411
void *prev;
402412
bool is_unwind;
413+
int volatile caught;
403414

404415
/* The handler in the stack (which is a FILO container). */
405416
ex_context_t *next;

src/exception.c

Lines changed: 85 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,7 @@ ex_context_t *ex_init(void) {
204204
ex_signal_block(all);
205205
ex_context = &ex_context_buffer;
206206
ex_context->is_unwind = false;
207+
ex_context->caught = -1;
207208
ex_context->type = ex_context_st;
208209
ex_signal_unblock(all);
209210

@@ -259,8 +260,7 @@ void ex_throw(const char *exception, const char *file, int line, const char *fun
259260
ex_terminate();
260261

261262
#ifdef _WIN32
262-
if (!is_empty((void *)message))
263-
RaiseException(EXCEPTION_PANIC, 0, 0, 0);
263+
RaiseException(EXCEPTION_PANIC, 0, 0, 0);
264264
#endif
265265
ex_longjmp(ctx->buf, ctx->state | ex_throw_st);
266266
}
@@ -272,7 +272,10 @@ int catch_seh(const char *exception, DWORD code, struct _EXCEPTION_POINTERS *ep)
272272
int i;
273273

274274
for (i = 0; i < max_ex_sig; i++) {
275-
if (ex_sig[i].ex == exception || is_str_eq(ctx->panic, exception)) {
275+
if (is_str_eq(ex_sig[i].ex, exception)
276+
|| is_str_eq(ctx->panic, exception)
277+
|| ex_sig[i].seh == code
278+
|| ctx->caught == ex_sig[i].seh) {
276279
ctx->state = ex_throw_st;
277280
ctx->ex = ex_sig[i].ex;
278281
ctx->file = "unknown";
@@ -299,7 +302,7 @@ int catch_filter_seh(DWORD code, struct _EXCEPTION_POINTERS *ep) {
299302
}
300303

301304
for (i = 0; i < max_ex_sig; i++) {
302-
if (ex_sig[i].seh == code) {
305+
if (ex_sig[i].seh == code || ctx->caught == ex_sig[i].seh) {
303306
ctx->state = ex_throw_st;
304307
ctx->ex = ex_sig[i].ex;
305308
ctx->file = "unknown";
@@ -352,13 +355,34 @@ void ex_handler(int sig) {
352355
for (i = 0; i < max_ex_sig; i++) {
353356
if (ex_sig[i].sig == sig) {
354357
ex = ex_sig[i].ex;
358+
ex_init()->caught = sig;
355359
break;
356360
}
357361
}
358362

359363
ex_throw(ex, "unknown", 0, NULL, NULL);
360364
}
361365

366+
void ex_signal_reset(int sig) {
367+
#if defined(_WIN32) || defined(_WIN64)
368+
if (signal(sig, SIG_DFL) == SIG_ERR)
369+
fprintf(stderr, "Cannot install handler for signal no %d\n",
370+
sig);
371+
#else
372+
/*
373+
* Make signal handlers persistent.
374+
*/
375+
ex_sig_sa.sa_handler = SIG_DFL;
376+
if (sigemptyset(&ex_sig_sa.sa_mask) != 0)
377+
fprintf(stderr, "Cannot setup handler for signal no %d (%s)\n",
378+
sig, ex);
379+
else if (sigaction(sig, &ex_sig_sa, NULL) != 0)
380+
fprintf(stderr, "Cannot restore handler for signal no %d (%s)\n",
381+
sig, ex);
382+
#endif
383+
exception_signal_set = false;
384+
}
385+
362386
void ex_signal(int sig, const char *ex) {
363387
int i;
364388

@@ -468,3 +492,60 @@ void ex_signal_setup(void) {
468492
ex_signal(SIG_BUS, EX_NAME(sig_bus));
469493
#endif
470494
}
495+
496+
void ex_signal_default(void) {
497+
#ifdef SIGSEGV
498+
ex_signal_reset(SIGSEGV);
499+
#endif
500+
501+
#if defined(SIGABRT)
502+
ex_signal_reset(SIGABRT);
503+
#endif
504+
505+
#ifdef SIGFPE
506+
ex_signal_reset(SIGFPE);
507+
#endif
508+
509+
#ifdef SIGILL
510+
ex_signal_reset(SIGILL);
511+
#endif
512+
513+
#ifdef SIGBREAK
514+
ex_signal_reset(SIGBREAK);
515+
#endif
516+
517+
#ifdef SIGINT
518+
ex_signal_reset(SIGINT);
519+
#endif
520+
521+
#ifdef SIGTERM
522+
ex_signal_reset(SIGTERM);
523+
#endif
524+
525+
#if !defined(_WIN32)
526+
#ifdef SIGQUIT
527+
ex_signal_reset(SIGQUIT);
528+
#endif
529+
530+
#ifdef SIGHUP
531+
ex_signal_reset(SIGHUP);
532+
#endif
533+
534+
#ifdef SIGWINCH
535+
ex_signal_reset(SIGWINCH);
536+
#endif
537+
#ifdef SIGTRAP
538+
ex_signal_reset(SIGTRAP);
539+
#endif
540+
#endif
541+
542+
#ifdef SIGALRM
543+
ex_signal_reset(SIGALRM);
544+
#endif
545+
546+
#ifdef SIGBUS
547+
ex_signal_reset(SIGBUS);
548+
#elif SIG_BUS
549+
ex_signal_reset(SIG_BUS);
550+
#endif
551+
}

0 commit comments

Comments
 (0)