can't use setjmp inside a function that is not the parent.
just write and use some macros.
Otherwise the "else" from handler.Set() was never reached, which caused a unit
test to fail.
... | ... |
@@ -176,15 +176,11 @@ void cli_dbgmsg_internal(const char *str, ...); |
176 | 176 |
|
177 | 177 |
class ScopedExceptionHandler { |
178 | 178 |
public: |
179 |
- bool Set() { |
|
180 |
- if (setjmp(env) == 0) { |
|
181 |
- /* set the exception handler's return location to here for the |
|
182 |
- * current thread */ |
|
183 |
- ExceptionReturn.set((const jmp_buf*)&env); |
|
184 |
- return true; |
|
185 |
- } |
|
186 |
- cli_warnmsg("[JIT]: recovered from error\n"); |
|
187 |
- return false; |
|
179 |
+ jmp_buf &getEnv() { return env;} |
|
180 |
+ void Set() { |
|
181 |
+ /* set the exception handler's return location to here for the |
|
182 |
+ * current thread */ |
|
183 |
+ ExceptionReturn.set((const jmp_buf*)&env); |
|
188 | 184 |
} |
189 | 185 |
~ScopedExceptionHandler() { |
190 | 186 |
/* leaving scope, remove exception handler for current thread */ |
... | ... |
@@ -193,10 +189,17 @@ class ScopedExceptionHandler { |
193 | 193 |
private: |
194 | 194 |
jmp_buf env; |
195 | 195 |
}; |
196 |
+#define HANDLER_TRY(handler) \ |
|
197 |
+ if (setjmp(handler.getEnv()) == 0) {\ |
|
198 |
+ handler.Set(); |
|
199 |
+ |
|
200 |
+#define HANDLER_END(handler) \ |
|
201 |
+ } else cli_warnmsg("[Bytecode JIT]: recovered from error\n"); |
|
202 |
+ |
|
196 | 203 |
|
197 | 204 |
void do_shutdown() { |
198 | 205 |
ScopedExceptionHandler handler; |
199 |
- if (handler.Set()) { |
|
206 |
+ HANDLER_TRY(handler) { |
|
200 | 207 |
// TODO: be on the safe side, and clear errors here, |
201 | 208 |
// otherwise destructor calls report_fatal_error |
202 | 209 |
((class raw_fd_ostream&)errs()).clear_error(); |
... | ... |
@@ -205,6 +208,7 @@ void do_shutdown() { |
205 | 205 |
|
206 | 206 |
((class raw_fd_ostream&)errs()).clear_error(); |
207 | 207 |
} |
208 |
+ HANDLER_END(handler); |
|
208 | 209 |
remove_fatal_error_handler(); |
209 | 210 |
} |
210 | 211 |
|
... | ... |
@@ -1836,12 +1840,13 @@ static int bytecode_execute(intptr_t code, struct cli_bc_ctx *ctx) |
1836 | 1836 |
{ |
1837 | 1837 |
ScopedExceptionHandler handler; |
1838 | 1838 |
// execute; |
1839 |
- if (handler.Set()) { |
|
1839 |
+ HANDLER_TRY(handler) { |
|
1840 | 1840 |
// setup exception handler to longjmp back here |
1841 | 1841 |
uint32_t result = ((uint32_t (*)(struct cli_bc_ctx *))(intptr_t)code)(ctx); |
1842 | 1842 |
*(uint32_t*)ctx->values = result; |
1843 | 1843 |
return 0; |
1844 | 1844 |
} |
1845 |
+ HANDLER_END(handler); |
|
1845 | 1846 |
cli_warnmsg("[Bytecode JIT]: JITed code intercepted runtime error!\n"); |
1846 | 1847 |
return CL_EBYTECODE; |
1847 | 1848 |
} |
... | ... |
@@ -1943,10 +1948,7 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) |
1943 | 1943 |
ScopedExceptionHandler handler; |
1944 | 1944 |
LLVMApiScopedLock scopedLock; |
1945 | 1945 |
// setup exception handler to longjmp back here |
1946 |
- if (!handler.Set()) { |
|
1947 |
- cli_errmsg("[Bytecode JIT] *** FATAL error encountered during bytecode generation\n"); |
|
1948 |
- return CL_EBYTECODE; |
|
1949 |
- } |
|
1946 |
+ HANDLER_TRY(handler) { |
|
1950 | 1947 |
// LLVM itself never throws exceptions, but operator new may throw bad_alloc |
1951 | 1948 |
try { |
1952 | 1949 |
Module *M = new Module("ClamAV jit module", bcs->engine->Context); |
... | ... |
@@ -2130,6 +2132,10 @@ int cli_bytecode_prepare_jit(struct cli_all_bc *bcs) |
2130 | 2130 |
cli_errmsg("[Bytecode JIT]: Unexpected unknown exception occured\n"); |
2131 | 2131 |
return CL_EBYTECODE; |
2132 | 2132 |
} |
2133 |
+ return 0; |
|
2134 |
+ } HANDLER_END(handler); |
|
2135 |
+ cli_errmsg("[Bytecode JIT] *** FATAL error encountered during bytecode generation\n"); |
|
2136 |
+ return CL_EBYTECODE; |
|
2133 | 2137 |
} |
2134 | 2138 |
|
2135 | 2139 |
int bytecode_init(void) |