Skip to content

Test "checkStackOrError should raise an error for stack overflow" started to panic on Linux since Zig 0.15.1 upgrade #20

@thsackos

Description

@thsackos

Probably related to the libunwind upgrade and/or LLVM upgrade in Zig 15.
https://ziglang.org/download/0.15.1/release-notes.html#LLVM-20

Change notes for libunwind should be researched:
https://github.com/libunwind/libunwind/releases/tag/v1.8.0

I don't see any other meaningful mentions of changed behavior. I saw that .unwind_tables has been moved around a bit and now lives in the Zig Module system, I've tried adding various combinations of flags for .unwind_tables to the relevant sections of build.zig but not able to get the test passing again on linux.

Attaching GDB to an exe reproducing the test cast, I can see that we are exiting the process at the bottom of this call stack in LuaJIT. It definitely seems like something changed around the unwind tables behavior in Zig 15, need to find out what and how to replace it with the old behavior.

LUALIB_API void luaL_checkstack(lua_State *L, int size, const char *msg)
{
  if (!lua_checkstack(L, size))
    lj_err_callerv(L, LJ_ERR_STKOVM, msg);
}

LJ_NOINLINE void lj_err_callerv(lua_State *L, ErrMsg em, ...)
{
  const char *msg;
  va_list argp;
  va_start(argp, em);
  msg = lj_strfmt_pushvf(L, err2msg(em), argp);
  va_end(argp);
  lj_err_callermsg(L, msg);
}

LJ_NOINLINE void lj_err_callermsg(lua_State *L, const char *msg)
{
  TValue *frame = NULL, *pframe = NULL;
  if (!(LJ_HASJIT && tvref(G(L)->jit_base))) {
    frame = L->base-1;
    if (frame_islua(frame)) {
      pframe = frame_prevl(frame);
    } else if (frame_iscont(frame)) {
      if (frame_iscont_fficb(frame)) {
    pframe = frame;
    frame = NULL;
      } else {
    pframe = frame_prevd(frame);
#if LJ_HASFFI
    /* Remove frame for FFI metamethods. */
    if (frame_func(frame)->c.ffid >= FF_ffi_meta___index &&
        frame_func(frame)->c.ffid <= FF_ffi_meta___tostring) {
      L->base = pframe+1;
      L->top = frame;
      setcframe_pc(cframe_raw(L->cframe), frame_contpc(frame));
    }
#endif
      }
    }
  }
  lj_debug_addloc(L, msg, pframe, frame);
  lj_err_run(L);
}

LJ_NOINLINE void LJ_FASTCALL lj_err_run(lua_State *L)
{
  ptrdiff_t ef = (LJ_HASJIT && tvref(G(L)->jit_base)) ? 0 : finderrfunc(L);
  if (ef) {
    TValue *errfunc, *top;
    lj_state_checkstack(L, LUA_MINSTACK * 2);  /* Might raise new error. */
    lj_trace_abort(G(L));
    errfunc = restorestack(L, ef);
    top = L->top;
    if (!tvisfunc(errfunc) || L->status == LUA_ERRERR) {
      setstrV(L, top-1, lj_err_str(L, LJ_ERR_ERRERR));
      lj_err_throw(L, LUA_ERRERR);
    }
    L->status = LUA_ERRERR;
    copyTV(L, top+LJ_FR2, top-1);
    copyTV(L, top-1, errfunc);
    if (LJ_FR2) setnilV(top++);
    L->top = top+1;
    lj_vm_call(L, top, 1+1);  /* Stack: |errfunc|msg| -> |msg| */
  }
  lj_err_throw(L, LUA_ERRRUN);
}

LJ_NOINLINE void LJ_FASTCALL lj_err_throw(lua_State *L, int errcode)
{
  global_State *g = G(L);
  lj_trace_abort(g);
  L->status = LUA_OK;
#if LJ_UNWIND_EXT
  err_raise_ext(g, errcode);
  /*
  ** A return from this function signals a corrupt C stack that cannot be
  ** unwound. We have no choice but to call the panic function and exit.
  **
  ** Usually this is caused by a C function without unwind information.
  ** This may happen if you've manually enabled LUAJIT_UNWIND_EXTERNAL
  ** and forgot to recompile *every* non-C++ file with -funwind-tables.
  */
  if (G(L)->panic)
    G(L)->panic(L);
#else
#if LJ_HASJIT
  setmref(g->jit_base, NULL);
#endif
  {
    void *cf = err_unwind(L, NULL, errcode);
    if (cframe_unwind_ff(cf))
      lj_vm_unwind_ff(cframe_raw(cf));
    else
      lj_vm_unwind_c(cframe_raw(cf), errcode);
  }
#endif
  exit(EXIT_FAILURE);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    help wantedExtra attention is needed

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions