Skip to content

Commit

Permalink
vis-lua: register a panic handler
Browse files Browse the repository at this point in the history
The intention here is to catch any errors in unprotected mode,
close the lua state and jump back to the mainloop to give the
user the opportunity to take care of unsaved changes.

We abuse the infrastructure Lua provides for custom memory
allocators to associate our vis instance pointer with the lua
state. In the panic handler we can then use lua_getallocf to
get our context back. The actual memory allocater is equivalent
to the one used by default and just forwards everything to the
libc.
  • Loading branch information
martanne committed Mar 24, 2017
1 parent 4c4bd8e commit f3fd9c3
Showing 1 changed file with 31 additions and 1 deletion.
32 changes: 31 additions & 1 deletion vis-lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,25 @@ static void stack_dump(lua_State *L, const char *format, ...) {

#endif

static int panic_handler(lua_State *L) {
void *ud = NULL;
lua_getallocf(L, &ud);
if (ud) {
Vis *vis = ud;
vis->lua = NULL;
if (vis->event)
vis->event->win_status = window_status_update;
const char *msg = NULL;
if (lua_type(L, -1) == LUA_TSTRING)
msg = lua_tostring(L, -1);
vis_info_show(vis, "Fatal Lua error: %s", msg ? msg : "unknown reason");
lua_close(L);
if (vis->running)
siglongjmp(vis->sigbus_jmpbuf, 1);
}
return 0;
}

static int error_handler(lua_State *L) {
Vis *vis = lua_touserdata(L, lua_upvalueindex(1));
if (vis->errorhandler)
Expand Down Expand Up @@ -2408,6 +2427,15 @@ static bool package_exist(Vis *vis, lua_State *L, const char *name) {
return ret;
}

static void *alloc_lua(void *ud, void *ptr, size_t osize, size_t nsize) {
if (nsize == 0) {
free(ptr);
return NULL;
} else {
return realloc(ptr, nsize);
}
}

/***
* Editor initialization completed.
* This event is emitted immediately after `visrc.lua` has been sourced, but
Expand All @@ -2418,10 +2446,12 @@ static bool package_exist(Vis *vis, lua_State *L, const char *name) {
* @function init
*/
void vis_lua_init(Vis *vis) {
lua_State *L = luaL_newstate();
lua_State *L = lua_newstate(alloc_lua, vis);
if (!L)
return;
vis->lua = L;
lua_atpanic(L, &panic_handler);

luaL_openlibs(L);

#if CONFIG_LPEG
Expand Down

0 comments on commit f3fd9c3

Please sign in to comment.