My project is written in C++, and it makes use of dynamically generated code to glue some things together (using Fabrice Bellard's TCC and a bit of manually generated assembly thunks). Dynamically generated code sometimes jumps into "runtime helpers" implemented in C++ and back.
There's a feature that allows to abort dynamically generated code altogether, wherever it is, jumping back to C++ (the caller). To achieve that, I'm simply using C++ exceptions: a runtime helper (posing as a C function) simply throws a C++ exception, and it propagates through generated functions back to C++. I'm using SJLJ and everything works OK so far, but I don't want to depend on a particilar implementation (I read that that's safe only with SJLJ).
Other than the aborting scheme above, my C++ code uses exceptions mostly in critical situations, it's not used for general purpose control flow. However, I rely on RAII to automatically destruct objects on stack.
My question is: Is it theoretically and practically safe to use longjmp/setjmp instead, provided setjmp is set right before calling a dynamically generated function, and provided that longjmp never propagates through C++ functions that rely on RAII (I must make sure that none of runtime helpers implemented in C++ make use of it) and always lands in setjmp (set right before the function)?
Or C++ is so fragile that even this isn't guaranteed to work well and will corrupt something? Or maybe C++ breaks only if actual exceptions are thrown? What if the exceptions are thrown locally and caught immediatelly (in runtime helpers called by generated assembly), is it safe? Or maybe just because there are a few foreign frames up the stack, it will refuse to work?
EG:
jmp_buf buf; // thread-local
char* msg; // thread-local
// ... some C++ code here, potentially some RAII thingy
GeneratedFunc func = (GeneratedFunc)compile_stuff();
if (!setjmp(buf)) {
// somewhere deep inside, it calls longjmp to jump back to the top function in case a problem happens
func();
} else {
printf("error: %s\n", msg);
// do something about the error here
}
// some other C++ code