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
|
/*
* sys-setjmp - wrap system setjmp or compiler C try/catch mechanism
*
* Copyright(c) 2022 Glenn Strauss gstrauss()gluelogic.com All rights reserved
* License: BSD 3-clause (same as lighttpd)
*/
#include "first.h"
#include "sys-setjmp.h"
#ifndef _MSC_VER
#ifdef HAVE_SIGNAL
#include <signal.h> /* sig_atomic_t */
#else
typedef int sig_atomic_t;
#endif
#include <errno.h>
#include <setjmp.h> /* sigjmp_buf sigsetjmp() siglongjmp() */
#include "ck.h"
/*(note: would need to be thread-local to be thread-safe)*/
static volatile sig_atomic_t sys_setjmp_sigbus_jmp_valid;
#ifdef _WIN32
static jmp_buf sys_setjmp_sigbus_jmp_buf;
#else
static sigjmp_buf sys_setjmp_sigbus_jmp_buf;
#endif
__attribute_noreturn__
void sys_setjmp_sigbus (int sig)
{
UNUSED(sig);
#ifdef _WIN32
if (sys_setjmp_sigbus_jmp_valid) longjmp(sys_setjmp_sigbus_jmp_buf, 1);
#else
if (sys_setjmp_sigbus_jmp_valid) siglongjmp(sys_setjmp_sigbus_jmp_buf, 1);
#endif
ck_bt_abort(__FILE__, __LINE__, "SIGBUS");
}
/* Note: must have configured signal handler for macros to be effective
* e.g. signal(SIGBUS, sys_setjmp_sigbus)
*/
/* Note: should not 'return', 'break', 'continue', 'goto' out of try block,
* or else sys_setjmp_sigbus_jmp_valid will not be unset. However, those
* are permitted from catch block when using these macros. (In practice,
* unsetting sys_setjmp_sigbus_jmp_valid is not critical, since SIGBUS
* should not be received outside of the protected blocks, or else
* something (elsewhere) is missing protection to catch SIGBUS.)
*/
/* Note: sigaction() config in server.c sets SA_NODEFER and empty signal mask
* so we avoid saving and restoring signal mask on systems with sigaction() */
#ifdef _WIN32
#define if_SYS_SETJMP_TRY() if ((sys_setjmp_sigbus_jmp_valid = \
!setjmp(sys_setjmp_sigbus_jmp_buf))) {
#elif defined(HAVE_SIGACTION)
#define if_SYS_SETJMP_TRY() if ((sys_setjmp_sigbus_jmp_valid = \
!sigsetjmp(sys_setjmp_sigbus_jmp_buf, 0))) {
#else
#define if_SYS_SETJMP_TRY() if ((sys_setjmp_sigbus_jmp_valid = \
!sigsetjmp(sys_setjmp_sigbus_jmp_buf, 1))) {
#endif
#define else_SYS_SETJMP_CATCH() } \
else { \
#define fi_SYS_SETJMP_END() } \
sys_setjmp_sigbus_jmp_valid = 0;
#else /* _MSC_VER */
#include <windows.h> /* winnt.h EXCEPTION_IN_PAGE_ERROR */
#include <excpt.h>
#define if_SYS_SETJMP_TRY() __try {
#define else_SYS_SETJMP_CATCH() } \
__except ( \
GetExceptionCode()==EXCEPTION_IN_PAGE_ERROR \
? EXCEPTION_EXECUTE_HANDLER \
: EXCEPTION_CONTINUE_SEARCH ) {
#define fi_SYS_SETJMP_END() }
#endif /* _MSC_VER */
off_t sys_setjmp_eval3(off_t(*cb)(void *, const void *, off_t), void *dst, const void *src, off_t len)
{
off_t rv;
if_SYS_SETJMP_TRY()
rv = cb(dst, src, len);
else_SYS_SETJMP_CATCH() {
#ifndef _MSC_VER
errno = EFAULT;
#endif
return -1;
}
fi_SYS_SETJMP_END()
return rv;
}
|