emscripten-core / emscripten-core/emscripten

longjmp in Lua producing unexpected behavior in Emscripten 2.0.11

Open
#13,166 6 comments 0 reactions 0 assignees View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.