Skip to content

longjmp in Lua producing unexpected behavior in Emscripten 2.0.11 #13166

Open
@MCJack123

Description

@MCJack123

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):

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. 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

I'm running Emscripten 2.0.11 on macOS 11.0 x64, using emsdk to download the tools.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions