diff --git a/include/luares.h b/include/luares.h index fcf54ee..15287d3 100644 --- a/include/luares.h +++ b/include/luares.h @@ -3,6 +3,7 @@ extern char lua_boot[]; extern char lua_component[]; extern char lua_computer[]; +extern char lua_debug[]; extern char lua_eeprom[]; extern char lua_filesystem[]; extern char lua_init[]; diff --git a/src/c/lnative.c b/src/c/lnative.c index d31877e..ce428d8 100644 --- a/src/c/lnative.c +++ b/src/c/lnative.c @@ -62,10 +62,20 @@ void logm(const char *message) { fclose(file); } } + +static int l_log (lua_State *L) { + const char* t = lua_tostring(L, 1); + logn(t); + return 0; +} + #else #define logn(m) #define logi(m) #define logm(m) +static int l_log (lua_State *L) { + return 0; +} #endif static int l_sleep (lua_State *L) { @@ -370,6 +380,7 @@ void luanative_start(lua_State *L) { lua_createtable (L, 0, 1); pushctuple(L, "sleep", l_sleep); + pushctuple(L, "log", l_log); pushctuple(L, "fs_exists", l_fs_exists); pushctuple(L, "fs_mkdir", l_fs_mkdir); @@ -397,5 +408,11 @@ void luanative_start(lua_State *L) { pushctuple(L, "freeMemory", l_freeMemory); pushctuple(L, "pull", l_pull); + #ifdef DEBUG + lua_pushstring(L, "debug"); + lua_pushboolean(L, 1); + lua_settable(L, -3); + #endif + lua_setglobal(L, "native"); } diff --git a/src/c/modules.c b/src/c/modules.c index 92645e0..8b371c4 100644 --- a/src/c/modules.c +++ b/src/c/modules.c @@ -13,6 +13,7 @@ void setup_modules(lua_State *L) { pushstuple(L, "color", lua_util_color); pushstuple(L, "component", lua_component); pushstuple(L, "computer", lua_computer); + pushstuple(L, "debug", lua_debug); pushstuple(L, "eeprom", lua_eeprom); pushstuple(L, "filesystem", lua_filesystem); pushstuple(L, "internet", lua_internet); diff --git a/src/lua/core/boot.lua b/src/lua/core/boot.lua index 46ed552..42b946b 100644 --- a/src/lua/core/boot.lua +++ b/src/lua/core/boot.lua @@ -5,20 +5,29 @@ function boot.boot() local w, h = gpu.getResolution() local function bsod(...) - gpu.setBackground(0x0000FF) - gpu.setForeground(0xFFFFFF) - gpu.fill(1, 1, w, h, " ") - gpu.set(2, 2, "CRITICAL ERROR OCCURED") - gpu.set(2, 3, "Lua BIOS has failed:") - for n, v in pairs({...}) do - gpu.set(2, 4 + n, tostring(v)) - end - gpu.set(2, h-1, "SYSTEM WILL STOP") - gpu.setForeground(0xFFFFFF) - gpu.setBackground(0x000000) + local arg = {...} + pcall(function() + native.log("> LuPI BSOD") + for n, v in pairs(arg) do + native.log(tostring(v)) + end + end) + pcall(function() + gpu.setBackground(0x0000FF) + gpu.setForeground(0xFFFFFF) + gpu.fill(1, 1, w, h, " ") + gpu.set(2, 2, "CRITICAL ERROR OCCURED") + gpu.set(2, 3, "Lua BIOS has failed:") + for n, v in pairs(arg) do + gpu.set(2, 4 + n, tostring(v)) + end + gpu.set(2, h-1, "SYSTEM WILL STOP") + gpu.setForeground(0xFFFFFF) + gpu.setBackground(0x000000) - native.sleep(4000000) - os.exit(1) + native.sleep(4000000) + os.exit(1) + end) end gpu.fill(1, 1, w, h, " ") @@ -31,6 +40,7 @@ function boot.boot() if not f then bsod(reason) else + local crash = false xpcall(f, function(e) local trace = {} @@ -38,9 +48,11 @@ function boot.boot() trace[#trace + 1] = s end bsod("System crashed", "Stack traceback:", table.unpack(trace)) - os.exit(4) --TODO: Run exit hooks + crash = true end) - bsod("System quit") + if not crash then + bsod("System quit") + end end end diff --git a/src/lua/core/component.lua b/src/lua/core/component.lua index cb6e90e..e429f7a 100644 --- a/src/lua/core/component.lua +++ b/src/lua/core/component.lua @@ -10,6 +10,29 @@ local componentCallback = { __tostring = function(self) return (components[self.address] ~= nil and components[self.address].doc[self.name] ~= nil) and components[self.address].doc[self.name] or "function" end } +if native.debug then + local start = native.uptime() + local last = native.uptime() + componentCallback.__call = function(self, ...) + local t = {} + for k,v in pairs({...}) do + if type(v) == "string" then + v = "\"" .. v .. "\"" + end + t[k] = tostring(v) + end + + local caller = debug.getinfo(2) + local msg = tostring((native.uptime() - start) / 1000) .. " [+" .. native.uptime() - last .. "] " .. caller.short_src .. ":".. caller.currentline .. " > invoke(" .. self.address .. "): " + .. components[self.address].type .. "." .. self.name + .. "(" .. table.concat(t, ", ") .. ")" + + native.log(msg) + last = native.uptime() + return components[self.address].rawproxy[self.name](...) + end +end + function component.prepare() print("Assembling initial component tree") end diff --git a/src/lua/core/computer.lua b/src/lua/core/computer.lua index aa62295..92f3025 100644 --- a/src/lua/core/computer.lua +++ b/src/lua/core/computer.lua @@ -118,12 +118,17 @@ function api.pushSignal(s, ...) end function api.pullSignal(timeout) - if signalQueue[1] then return table.unpack(table.remove(signalQueue, 1)) end + --native.log("pullSignal for " .. (timeout or " infinite") .. " s") + if signalQueue[1] then + native.log("pullSignal direct: " .. signalQueue[1][1]) + return table.unpack(table.remove(signalQueue, 1)) + end local timeoutuptime = math.huge if not timeout then timeout = -1 else + if timeout < 0 then timeout = 0 end timeout = timeout * 1000 timeoutuptime = native.uptime() + timeout end @@ -131,7 +136,11 @@ function api.pullSignal(timeout) repeat nevts = native.pull(timeout) until nevts > 0 or native.uptime() > timeoutuptime - if signalQueue[1] then return table.unpack(table.remove(signalQueue, 1)) end + if signalQueue[1] then + native.log("pullSignal native: " .. signalQueue[1][1]) + return table.unpack(table.remove(signalQueue, 1)) + end + --native.log("pullSignal timeout") end function api.uptime() @@ -158,6 +167,17 @@ function api.totalMemory() end function api.shutdown() + --TODO: Longjmp to init somehow? + print("Running shutdown hooks") + for k, hook in ipairs(deadhooks) do + local state, cause = pcall(hook) + if not state then + print("Shutdown hook with following error:") + print(cause) + end + end + print("Hooks executed: " .. #deadhooks) + os.exit(0) end diff --git a/src/lua/core/debug.lua b/src/lua/core/debug.lua new file mode 100644 index 0000000..4cec7de --- /dev/null +++ b/src/lua/core/debug.lua @@ -0,0 +1,26 @@ +local d = {} + +local function getCallerInfo() + local caller = debug.getinfo(3) + return caller.short_src .. ":".. caller.currentline +end + +function d.hook() + local sb = modules.sandbox + + local otb = sb.debug.traceback + function sb.debug.traceback(m, l, ...) + local s = otb(m, l and (type(l) == "number" and (l + 1) or l) or 2, ...) + native.log("Native traceback requested for:") + native.log(s) + return s --TODO: check if there actually is only one return value + end + + local oload = sb.load + function sb.load(ld, source, mode, env) + native.log("load from " .. getCallerInfo() .. ", loading \"" .. (source or type(ld)) .. "\"") + return oload(ld, source, mode, env) + end +end + +return d \ No newline at end of file diff --git a/src/lua/core/init.lua b/src/lua/core/init.lua index 631e14a..9d9bc83 100644 --- a/src/lua/core/init.lua +++ b/src/lua/core/init.lua @@ -17,12 +17,17 @@ end ------------------------------------------------------------------------------- math.randomseed(native.uptime())--TODO: Make it better? -print("LuPI L1 INIT") +lprint = function (...) + print(...) + native.log(table.concat({...}, " ")) +end + +lprint("LuPI L1 INIT") modules = {} deadhooks = {} local function loadModule(name) - print("LuPI L1 INIT > Load module > " .. name) + lprint("LuPI L1 INIT > Load module > " .. name) io.flush() --TODO: PRERELEASE: Module sandboxing, preferably secure-ish --TODO: ASAP: Handle load errors @@ -31,7 +36,7 @@ local function loadModule(name) end local code, reason = load(moduleCode[name], "=Module "..name) if not code then - print("Failed loading module " .. name .. ": " .. reason) + lprint("Failed loading module " .. name .. ": " .. reason) io.flush() else modules[name] = code() @@ -41,6 +46,9 @@ end function main() --Load modules --Utils + if native.debug then + loadModule("debug") + end loadModule("random") loadModule("color") loadModule("buffer") @@ -73,20 +81,30 @@ function main() modules.computer.tmp = modules.filesystem.register("/tmp/lupi-" .. modules.random.uuid()) modules.textgpu.start() + if native.debug then + modules.debug.hook() + end + modules.boot.boot() end -local state, cause = pcall(main) -if not state then - print("LuPI finished with following error:") - print(cause) -end +local tb = "" -print("Running shutdown hooks") +local state, cause = xpcall(main, function(e) + tb = debug.traceback(e, 2) +end) + +lprint("Running shutdown hooks") for k, hook in ipairs(deadhooks) do local state, cause = pcall(hook) if not state then - print("Shutdown hook with following error:") - print(cause) + lprint("Shutdown hook with following error:") + lprint(cause) end end +lprint("Hooks executed: " .. #deadhooks) + +if not state then + lprint("LuPI finished with following error:") + lprint(tb) +end \ No newline at end of file diff --git a/src/lua/core/sandbox.lua b/src/lua/core/sandbox.lua index f15dd60..c971151 100644 --- a/src/lua/core/sandbox.lua +++ b/src/lua/core/sandbox.lua @@ -241,7 +241,6 @@ sandbox = { end, }, checkArg = checkArg, - og = _G } sandbox._G = sandbox