Gregory Junker
2011-Oct-28 06:00 UTC
[LLVMdev] Proper way to handle JIT codegen exceptions?
I am looking through the source and Support/ErrorHandling.cpp/.h says, in so many words, "don't throw exceptions from inside an installed fatal error handling routine". So how are people handling errors during JIT? For command-line compilers, calling exit() or abort() isn't as big a deal -- the compiler is probably going to exit anyway. But say, for instance, the host application is Firefox -- my guess is that just letting exit() handle the situation isn't the solution. So what is the "proper" way to handle exceptional LLVM conditions ("cannot select", for instance)? Yes, I know this is something that needs to be brought to the programmer's attention, but having the user's application crash out on them isn't the way I expect most actual LLVM-JIT-based applications are handling these things... Thanks Greg
On 10/28/2011 09:00 AM, Gregory Junker wrote:> I am looking through the source and Support/ErrorHandling.cpp/.h says, in so > many words, "don't throw exceptions from inside an installed fatal error > handling routine". > > So how are people handling errors during JIT? For command-line compilers, > calling exit() or abort() isn't as big a deal -- the compiler is probably > going to exit anyway. But say, for instance, the host application is Firefox > -- my guess is that just letting exit() handle the situation isn't the > solution. > > So what is the "proper" way to handle exceptional LLVM conditions ("cannot > select", for instance)? Yes, I know this is something that needs to be > brought to the programmer's attention, but having the user's application > crash out on them isn't the way I expect most actual LLVM-JIT-based > applications are handling these things...I use setjmp/longjmp in ClamAV. Would be better if instead of throwing a fatal error the code generators would simply return an error code, but that would be too much work. Although this might leak memory in the case of a fatal error, it is better than crashing (for example in ClamAV we simply turn off the JIT and fallback to our own interpreter). I wrap all my toplevel functions that call into LLVM with (there are only 3): HANDLER_TRY(handler) { ... return 0; } HANDLER_END(handler); return ...some_errorcode... class ScopedExceptionHandler { public: jmp_buf &getEnv() { return env;} void Set() { /* set the exception handler's return location to here for the * current thread */ ExceptionReturn.set((const jmp_buf*)&env); } ~ScopedExceptionHandler() { /* leaving scope, remove exception handler for current thread */ ExceptionReturn.erase(); } private: jmp_buf env; }; static sys::ThreadLocal<const jmp_buf> ExceptionReturn; static void NORETURN jit_exception_handler(void) { jmp_buf* buf = const_cast<jmp_buf*>(ExceptionReturn.get()); if (buf) { // For errors raised during bytecode generation and execution. longjmp(*buf, 1); } else { // Oops, got no error recovery pointer set up, // this is probably an error raised during shutdown. cli_errmsg("[Bytecode JIT]: exception handler called, but no recovery point set up"); // should never happen, we remove the error handler when we don't use // LLVM anymore, and when we use it, we do set an error recovery point. llvm_unreachable("Bytecode JIT]: no exception handler recovery installed, but exception hit!"); } } void llvm_error_handler(void *user_data, const std::string &reason) { // Output it to stderr, it might exceed the 1k/4k limit of cli_errmsg cli_errmsg("[Bytecode JIT]: [LLVM error] %s\n", reason.c_str()); jit_exception_handler(); } }; #define HANDLER_TRY(handler) \ if (setjmp(handler.getEnv()) == 0) {\ handler.Set(); #define HANDLER_END(handler) \ } else cli_warnmsg("[Bytecode JIT]: recovered from error\n");
Reid Kleckner
2011-Oct-28 13:41 UTC
[LLVMdev] Proper way to handle JIT codegen exceptions?
The best way to reliably isolate software errors without leaking memory is to give the code it's own address space which you can cleanly throw away afterwards. In other words, fork a child process. --- I'm just being cheeky, I agree it would be nice if there were better error recovery mechanisms. The current philosophy is that once you shake out the bugs in your frontend so you always generate valid IR, LLVM *shouldn't* generate fatal errors. A fatal error is just as unexpected as a crash, and trying to recover from either is just as dicey as the other. Reid On Fri, Oct 28, 2011 at 2:00 AM, Gregory Junker <gjunker at dayark.com> wrote:> I am looking through the source and Support/ErrorHandling.cpp/.h says, in > so > many words, "don't throw exceptions from inside an installed fatal error > handling routine". > > So how are people handling errors during JIT? For command-line compilers, > calling exit() or abort() isn't as big a deal -- the compiler is probably > going to exit anyway. But say, for instance, the host application is > Firefox > -- my guess is that just letting exit() handle the situation isn't the > solution. > > So what is the "proper" way to handle exceptional LLVM conditions ("cannot > select", for instance)? Yes, I know this is something that needs to be > brought to the programmer's attention, but having the user's application > crash out on them isn't the way I expect most actual LLVM-JIT-based > applications are handling these things... > > Thanks > Greg > > _______________________________________________ > LLVM Developers mailing list > LLVMdev at cs.uiuc.edu http://llvm.cs.uiuc.edu > http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20111028/a23c3a0c/attachment.html>