I was trying to use setjmp/longjmp on a C++ project compiled with emscripten (version 1.39.16-fastcomp, can't use WebAssembly), and I came across instances of the program crashing after longjmp. I tried compiling in WebAssembly just for reference and the crash went away, so it looks like a bug on emscripten side. Maybe someone can provide a workaround.
Here's a snippet that reproduces the bug:
#include <cstdlib>
#include <cstdio>
#include <csetjmp>
#include <emscripten.h>
jmp_buf buffer;
int iterations;
void check() {
emscripten_sleep(100);
if (iterations < 10) {
printf("~ jump attempt ~\n");
longjmp(buffer, 1);
}
}
void run() {
printf("%d\n", iterations);
check();
}
int main() {
if (setjmp(buffer) == 0) {
iterations = 0;
} else {
iterations++;
}
run();
return 0;
}
And here are the flags used for compilation:
emcc -O0 -s EMTERPRETIFY=1 -s EMTERPRETIFY_ASYNC=1 -s WASM=0 c.cpp -o c.js
In essence, longjmp() is used to increment the counter, and the program should enumerate the numbers from 0 to 10 with "~ jump attempt ~" mixed in between.
However, when running c.js with node, I get the following output:
0
~ jump attempt ~
1
undefined
undefined
/Users/tsr/dev/c.js:89
throw ex;
^
abort(undefined) at Error
at jsStackTrace
at stackTrace
at abort
at emterpAssert
at emterpret
at emterpret
at _setThrew
at asm._setThrew
at _longjmp
at emterpret
This error happened during an emterpreter-async operation. Was there non-emterpreted code
on the stack during save (which is unallowed)? If so, you may want to adjust
EMTERPRETIFY_BLACKLIST, EMTERPRETIFY_WHITELIST. For reference, this is what the stack
looked like when we tried to save it: 2,Error
at Object.handle
at _emscripten_sleep
at emterpret
at emterpret
at emterpret
at Array.__Z3runv
at dynCall_v
at invoke_v
at emterpret
at Object.asm.emterpret
make: *** [c.js_run] Error 7
The first call to longjmp() seems to have worked, since the number "1" was printed, but then the program crashes somewhere in the emscripten_sleep (adding prints around the call makes it certain).
I'm quite puzzled as to why this does not work, especially since there are other setjmp/longjmp constructs that EMTERPRETER is capable of handling perfectly well.