emscripten-core / emscripten-core/emscripten
longjmp in Lua producing unexpected behavior in Emscripten 2.0.11
- Dominant language
- C++
- Stars
- 27.6k
- Forks
- 3.6k
- Avg merge
- 1d 1h
- Merged PRs (30d)
- 105
Description
I've been working on updating the WebAssembly version of an app I develop to the latest release, and I've run into an odd bug after updating to Emscripten 2.0.11. When calling `longjmp` to yield a coroutine in Lua, the execution appears to resume not at the `setjmp` as expected, but instead after the function (chain) the `longjmp` was triggered in. Here's the code that's getting run (with a bunch of `print` statements for debugging):
```c
void luaD_throw (lua_State *L, int errcode) {
struct lua_longjmp *lj = L->errorJmp;
if ((errcode >= LUA_ERRRUN && errcode <= LUA_ERREXC) && L->hookmask & LUA_MASKERROR)
luaD_callhook(L, LUA_HOOKERROR, -1);
if (lj) {
if (errcode == LUA_ERRRUN)
errcode = call_errfunc(L);
printf("throw %d %p\n", errcode, lj);
showStackTrace();
lj->status = errcode;
LUAI_THROW(L, lj); // macro for longjmp(lj->b, 1)
}
else {
L->status = cast_byte(errcode);
if (G(L)->panic) {
resetstack(L, errcode);
lua_unlock(L);
G(L)->panic(L);
}
exit(EXIT_FAILURE);
}
}
int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) {
struct lua_longjmp lj;
lj.status = 0;
lj.previous = L->errorJmp; /* chain new error handler */
L->errorJmp = &lj;
int status = setjmp((&lj)->b);
printf("rawrunprotected_setjmp %d\n", status);
if (status == 0) {
printf("rawrunprotected starting\n");
lj.status = (*f)(L, ud);
// after longjmp, execution resumes here
printf("rawrunprotected ok\n");
} else printf("longjmp triggered\n");
showStackTrace();
printf("rawrunprotected %d %p\n", lj.status, &lj);
L->errorJmp = lj.previous; /* restore old error handler */
return lj.status;
}
```
When this runs, I get output in the console similar to this:
```
throw 1 0xab9e60
rawrunprotected ok
rawrunprotected 0 0xab9e60
```
I'd expect the execution to restart at the `setjmp` call (double-returning, with a value of 1 in this case), but instead it continues from after the function's called.
I'm not sure why this is happening at all. The last version I tested this with was 1.40.1, which worked just fine (it's currently in production as well). I don't really have much time to try to bisect this issue right now, but I might be able to check later.
The code I'm using (minus the print statements) is available at [MCJack123/craftos2-lua](https://github.com/MCJack123/craftos2-lua). It's based on Lua 5.1.5, with a number of patches including a fix for yielding across C-calls. I've also attached the built Lua library (with prints) if desired: [liblua.a.gz](https://github.com/emscripten-core/emscripten/files/5759895/liblua.a.gz)
I'm running Emscripten 2.0.11 on macOS 11.0 x64, using emsdk to download the tools.
Contributor guide
Assessment
This issue has not been assessed yet.