ref: 9ab99ec017481375b87617ba167609f613adace8
parent: 76d765700afcf35a6cd8b44593697c5e36186498
author: phil9 <[email protected]>
date: Thu Dec 1 01:02:05 EST 2022
handle error in lua calls to prevent crashes calls to lua code are now protected and errors reported instead of crashing slug.
--- a/slug.c
+++ b/slug.c
@@ -4,23 +4,57 @@
Keyboardctl *kc;
int drawing;
-void
-lsetup(lua_State *L)
+lua_State*
+linit(int argc, char *argv[])
{
- lua_getglobal(L, "setup");
- if(!lua_isfunction(L, -1))
- return;
- lua_call(L, 0, 0);
- drawcanvas();
+ lua_State *L;
+ const char *s;
+ int r;
+
+ L = luaL_newstate();
+ luaL_openlibs(L);
+ r = luaL_dofile(L, argc > 1 ? argv[1] : NULL);
+ if(r != LUA_OK){
+ s = luaL_checkstring(L, lua_gettop(L));
+ fprint(2, "error: %s\n", s);
+ }
+ return L;
}
+int
+lcallerror(lua_State *L)
+{
+ const char *m;
+
+ m = lua_tostring(L, 1);
+ if(m == nil){
+ if(luaL_callmeta(L, 1, "__tostring") && lua_type(L, -1) == LUA_TSTRING)
+ return 1;
+ else
+ m = lua_pushfstring(L, "(error object is a %s value)", luaL_typename(L, 1));
+ }
+ luaL_traceback(L, L, m, 1);
+ return 1;
+}
+
void
-ldraw(lua_State *L)
+lcall(lua_State *L, char *fn)
{
- lua_getglobal(L, "draw");
+ int r, base;
+
+ lua_getglobal(L, fn);
if(!lua_isfunction(L, -1))
return;
- lua_call(L, 0, 0);
+ base = lua_gettop(L);
+ lua_pushcfunction(L, lcallerror);
+ lua_insert(L, base);
+ r = lua_pcall(L, 0, 0, base);
+ lua_remove(L, base);
+ if(r != LUA_OK){
+ fprint(2, "error: %s\n", lua_tostring(L, -1));
+ lua_pop(L, 1);
+ return;
+ }
drawcanvas();
}
@@ -49,8 +83,6 @@
lua_State *L;
Mouse m;
Rune k;
- const char *s;
- int r;
Alt alts[] = {
{ nil, &m, CHANRCV },
{ nil, nil, CHANRCV },
@@ -68,21 +100,15 @@
alts[0].c = mc->c;
alts[1].c = mc->resizec;
alts[2].c = kc->c;
- L = luaL_newstate();
- luaL_openlibs(L);
- r = luaL_dofile(L, argc > 1 ? argv[1] : NULL);
- if(r != LUA_OK){
- s = luaL_checkstring(L, lua_gettop(L));
- fprint(2, "error: %s\n", s);
- }
+ L = linit(argc, argv);
registerfuncs(L);
initstate();
resize(L, width, height);
drawing = 0;
- lsetup(L);
+ lcall(L, "setup");
drawing = 1;
for(;;){
- ldraw(L);
+ lcall(L, "draw");
switch(alt(alts)){
case 0:
break;
@@ -100,6 +126,6 @@
}
Done:
lua_close(L);
- threadexitsall(r == LUA_OK ? nil : "error");
+ threadexitsall(nil);
}