emscripten-core / emscripten-core/emscripten

longjmp in Lua producing unexpected behavior in Emscripten 2.0.11

Aperta
#13,166 6 commenti 0 reazioni 0 assegnatari Vedi su GitHub
Lingua principale
C++
Stelle
27.6k
Fork
3.6k
Merge medio
1g 14h
PR unite (30g)
125

Descrizione

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.

Guida per i contributori

Apri la guida per i contributori

Direzione di ricerca

Inizia con luaD_throw e luaD_rawrunprotected nel codice craftos2-lua collegato, quindi riproduci il percorso della coroutine con Emscripten 2.0.11 e confrontalo con 1.40.1. Traccia il comportamento di setjmp/longjmp e identifica la regressione o il percorso di runtime interessato; il lavoro è completato quando il percorso segnalato riprende correttamente ed è coperto da una verifica riproducibile.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Valutazione

Stack tecnologico
c, wasm
Ambito
compilers
Tipo di issue
Bug
Difficoltà
4/5
Tempo stimato
3-5 giorni
Stato di attività
Ferma
Chiarezza
Da chiarire
Idoneità per principianti
25/100

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.