From f3fd9c3cd1f2e15e89f9cd96d07c1ba957ae7c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc=20Andr=C3=A9=20Tanner?= Date: Fri, 24 Mar 2017 12:51:43 +0100 Subject: vis-lua: register a panic handler 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. --- vis-lua.c | 32 +++++++++++++++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) (limited to 'vis-lua.c') diff --git a/vis-lua.c b/vis-lua.c index 7099af3..dbb5d86 100644 --- a/vis-lua.c +++ b/vis-lua.c @@ -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) @@ -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 @@ -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 -- cgit v1.2.3