Debugging improvements

This commit is contained in:
Łukasz Magiera 2016-02-09 17:40:51 +01:00
parent 247e10e20c
commit 12bbefc034
9 changed files with 146 additions and 29 deletions

View File

@ -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[];

View File

@ -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");
}

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

26
src/lua/core/debug.lua Normal file
View File

@ -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

View File

@ -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

View File

@ -241,7 +241,6 @@ sandbox = {
end,
},
checkArg = checkArg,
og = _G
}
sandbox._G = sandbox