From b0db0b86bd5514bbb5e8c2a4ccdebc8cf1fc3182 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Fri, 8 May 2020 22:32:44 -0600 Subject: [PATCH] kernel improvements --- sys/apps/network/telnet.lua | 7 ++- sys/autorun/log.lua | 2 +- sys/init/2.vfs.lua | 4 +- sys/init/7.multishell.lua | 43 ++++------------ sys/kernel.lua | 93 ++++++++++++++++++++--------------- sys/modules/opus/injector.lua | 2 +- sys/modules/opus/trace.lua | 19 ++++++- 7 files changed, 87 insertions(+), 83 deletions(-) diff --git a/sys/apps/network/telnet.lua b/sys/apps/network/telnet.lua index 9aec83c..87ab04d 100644 --- a/sys/apps/network/telnet.lua +++ b/sys/apps/network/telnet.lua @@ -42,17 +42,16 @@ local function telnetHost(socket, mode) end local shellThread = kernel.run({ - terminal = win, window = win, title = mode .. ' client', hidden = true, - co = coroutine.create(function() - Util.run(_ENV, Alt.get('shell'), table.unpack(termInfo.program)) + fn = function() + Util.run(kernel.makeEnv(), Alt.get('shell'), table.unpack(termInfo.program)) if socket.queue then socket:write(socket.queue) end socket:close() - end) + end, }) Event.addRoutine(function() diff --git a/sys/autorun/log.lua b/sys/autorun/log.lua index 5e2b5e7..9e5b04e 100644 --- a/sys/autorun/log.lua +++ b/sys/autorun/log.lua @@ -26,7 +26,7 @@ local function systemLog() if y > 1 then local currentTab = kernel.getFocused() if currentTab == routine then - if currentTab.terminal.scrollUp and not currentTab.terminal.noAutoScroll then + if currentTab.terminal.scrollUp then if dir == -1 then currentTab.terminal.scrollUp() else diff --git a/sys/init/2.vfs.lua b/sys/init/2.vfs.lua index 9dc946d..b0e2ea7 100644 --- a/sys/init/2.vfs.lua +++ b/sys/init/2.vfs.lua @@ -104,12 +104,12 @@ function nativefs.delete(node, dir) -- if a file is mounted over an existing directory -- ie. sys/apps/MOUNT.LUA -- then sys and sys/apps are created as temp nodes - -- therefore, trying to delete sys will was only + -- therefore, trying to delete sys was only -- removing the node and not deleting the directory -- Need a better way to backfill nodes in a way -- that preserves the vfs functionality - -- perhaps a flag that denotes that this is a + -- perhaps a flag that denotes that this -- file/directory is the actual mount -- this hack will not fix diff --git a/sys/init/7.multishell.lua b/sys/init/7.multishell.lua index 4b581bd..e81b8ca 100644 --- a/sys/init/7.multishell.lua +++ b/sys/init/7.multishell.lua @@ -1,6 +1,5 @@ local Blit = require('opus.ui.blit') local Config = require('opus.config') -local trace = require('opus.trace') local Util = require('opus.util') local colors = _G.colors @@ -103,48 +102,25 @@ function multishell.launch( tProgramEnv, sProgramPath, ... ) }) end -local function xprun(env, path, ...) - setmetatable(env, { __index = _G }) - local fn, m = loadfile(path, env) - if fn then - return trace(fn, ...) - end - return fn, m -end - function multishell.openTab(tab) if not tab.title and tab.path then tab.title = fs.getName(tab.path):match('([^%.]+)') end tab.title = tab.title or 'untitled' tab.window = tab.window or window.create(parentTerm, 1, 2, w, h - 1, false) - tab.terminal = tab.terminal or tab.window - - local routine = kernel.newRoutine(tab) - - routine.co = coroutine.create(function() - local result, err - - if tab.fn then - result, err = Util.runFunction(routine.env, tab.fn, table.unpack(tab.args or { } )) - elseif tab.path then - result, err = xprun(routine.env, tab.path, table.unpack(tab.args or { } )) - else - err = 'multishell: invalid tab' - end - + tab.onExit = function(self, result, err) if not result and err and err ~= 'Terminated' or (err and err ~= 0) then - tab.terminal.setBackgroundColor(colors.black) + self.terminal.setBackgroundColor(colors.black) if tonumber(err) then - tab.terminal.setTextColor(colors.orange) + self.terminal.setTextColor(colors.orange) print('Process exited with error code: ' .. err) elseif err then printError(tostring(err)) end - tab.terminal.setTextColor(colors.white) + self.terminal.setTextColor(colors.white) print('\nPress enter to close') - routine.isDead = true - routine.hidden = false + self.isDead = true + self.hidden = false redrawMenu() while true do local e, code = os.pullEventRaw('key') @@ -153,9 +129,9 @@ function multishell.openTab(tab) end end end - end) + end - kernel.launch(routine) + local routine = kernel.run(tab) if tab.focused then multishell.setFocus(routine.uid) @@ -256,9 +232,10 @@ kernel.hook('multishell_redraw', function() if currentTab then if currentTab.sx then + local textColor = currentTab.isDead and _colors.errorColor or _colors.focusTextColor blit:write(currentTab.sx - 1, ' ' .. currentTab.title:sub(1, currentTab.width - 1) .. ' ', - _colors.focusBackgroundColor, _colors.focusTextColor) + _colors.focusBackgroundColor, textColor) end if not currentTab.noTerminate then blit:write(w, closeInd, nil, _colors.focusTextColor) diff --git a/sys/kernel.lua b/sys/kernel.lua index 51cba75..7bb0aa5 100644 --- a/sys/kernel.lua +++ b/sys/kernel.lua @@ -1,5 +1,6 @@ local Array = require('opus.array') local Terminal = require('opus.terminal') +local trace = require('opus.trace') local Util = require('opus.util') _G.kernel = { @@ -67,8 +68,6 @@ function kernel.unhook(event, fn) end end -local Routine = { } - local function switch(routine, previous) if routine then if previous and previous.window then @@ -86,6 +85,8 @@ local function switch(routine, previous) end end +local Routine = { } + function Routine:resume(event, ...) if not self.co or coroutine.status(self.co) == 'dead' then return @@ -95,38 +96,33 @@ function Routine:resume(event, ...) local previousTerm = term.redirect(self.terminal) local previous = kernel.running - kernel.running = self -- stupid shell set title + kernel.running = self local ok, result = coroutine.resume(self.co, event, ...) kernel.running = previous - if ok then - self.filter = result - else - _G.printError(result) - end - + self.filter = result self.terminal = term.current() term.redirect(previousTerm) - if not ok and self.haltOnError then - error(result, -1) - end - if coroutine.status(self.co) == 'dead' then - Array.removeByValue(kernel.routines, self) - if self.onDestroy then - pcall(self.onDestroy, self) - end - if #kernel.routines > 0 then - switch(kernel.routines[1]) - end - if self.haltOnExit then - kernel.halt() - end - end return ok, result end end +-- override if any post processing is required +-- routine:cleanup must be called explicitly if overridden +function Routine:onExit(status, message) -- self, status, message + if not status and message ~= 'Terminated' then + _G.printError(message) + end +end + +function Routine:cleanup() + Array.removeByValue(kernel.routines, self) + if #kernel.routines > 0 then + switch(kernel.routines[1]) + end +end + function kernel.getFocused() return kernel.routines[1] end @@ -147,17 +143,26 @@ function kernel.newRoutine(args) local routine = setmetatable({ uid = kernel.UID, timestamp = os.clock(), - terminal = kernel.window, window = kernel.window, title = 'untitled', }, { __index = Routine }) Util.merge(routine, args) routine.env = args.env or shell.makeEnv() + routine.terminal = routine.terminal or routine.window return routine end +local function xprun(env, path, ...) + setmetatable(env, { __index = _G }) + local fn, m = loadfile(path, env) + if fn then + return trace(fn, ...) + end + return fn, m +end + function kernel.launch(routine) routine.co = routine.co or coroutine.create(function() local result, err @@ -165,14 +170,13 @@ function kernel.launch(routine) if routine.fn then result, err = Util.runFunction(routine.env, routine.fn, table.unpack(routine.args or { } )) elseif routine.path then - result, err = Util.run(routine.env, routine.path, table.unpack(routine.args or { } )) + result, err = xprun(routine.env, routine.path, table.unpack(routine.args or { } )) else err = 'kernel: invalid routine' end - if not result and err ~= 'Terminated' then - error(err or 'Error occurred', 2) - end + pcall(routine.onExit, routine, result, err) + routine:cleanup() end) table.insert(kernel.routines, routine) @@ -203,8 +207,6 @@ function kernel.raise(uid) end switch(routine, previous) --- local previous = eventData[2] --- local routine = kernel.find(previous) return true end return false @@ -232,8 +234,8 @@ function kernel.find(uid) return Util.find(kernel.routines, 'uid', uid) end -function kernel.halt() - os.queueEvent('kernel_halt') +function kernel.halt(status, message) + os.queueEvent('kernel_halt', status, message) end function kernel.event(event, eventData) @@ -275,15 +277,20 @@ function kernel.event(event, eventData) end function kernel.start() - local s, m = pcall(function() + local s, m + pcall(function() repeat local eventData = { os.pullEventRaw() } local event = table.remove(eventData, 1) kernel.event(event, eventData) + if event == 'kernel_halt' then + s = eventData[1] + m = eventData[2] + end until event == 'kernel_halt' end) - if not s then + if not s and m then kernel.window.setVisible(true) term.redirect(kernel.window) print('\nCrash detected\n') @@ -320,15 +327,15 @@ local function init(...) term.redirect(kernel.window) shell.run('sys/apps/autorun.lua') - local shellWindow = window.create(kernel.terminal, 1, 1, w, h, false) + local win = window.create(kernel.terminal, 1, 1, w, h, true) local s, m = kernel.run({ title = args[1], path = 'sys/apps/shell.lua', args = args, - haltOnExit = true, - haltOnError = true, - terminal = shellWindow, - window = shellWindow, + window = win, + onExit = function(_, s, m) + kernel.halt(s, m) + end, }) if s then kernel.raise(s.uid) @@ -342,8 +349,12 @@ end kernel.run({ fn = init, title = 'init', - haltOnError = true, args = { ... }, + onExit = function(_, status, message) + if not status then + kernel.halt(status, message) + end + end, }) kernel.start() diff --git a/sys/modules/opus/injector.lua b/sys/modules/opus/injector.lua index e93e5d1..aea109a 100644 --- a/sys/modules/opus/injector.lua +++ b/sys/modules/opus/injector.lua @@ -79,7 +79,7 @@ return function(env) -- place package and require function into env env.package = { - path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH, + path = env.LUA_PATH or _G.LUA_PATH or DEFAULT_PATH, config = '/\n:\n?\n!\n-', preload = { }, loaded = { diff --git a/sys/modules/opus/trace.lua b/sys/modules/opus/trace.lua index 5673b6d..c8cf2a9 100644 --- a/sys/modules/opus/trace.lua +++ b/sys/modules/opus/trace.lua @@ -37,6 +37,22 @@ local function trim_traceback(target, marker) for line in target:gmatch("([^\n]*)\n?") do ttarget[#ttarget + 1] = line end for line in marker:gmatch("([^\n]*)\n?") do tmarker[#tmarker + 1] = line end +--[[ + TODO : fix this trace + Anavrins - if you could take a look, it would be appreciated + -- basically i want the stack logged in a more readable + -- format and the normal code/error message to be returned + + -- unsure why the traceback method concatenates the stack + -- when it can just be returned as a table - would make + -- filtering much simpler + + -- the following seems to reduce the stacktrace way too + -- much - losing most of the relevant call stack + + -- i have modified this a bit from the original - not sure + -- if my changes are causing the issues or not + -- Trim identical suffixes local t_len, m_len = #ttarget, #tmarker while t_len >= 3 and ttarget[t_len] == tmarker[m_len] do @@ -50,7 +66,7 @@ local function trim_traceback(target, marker) table.remove(ttarget, t_len) t_len = t_len - 1 end - +]] ttarget[#ttarget] = nil -- remove 2 calls added by the added xpcall ttarget[#ttarget] = nil @@ -84,6 +100,7 @@ return function (fn, ...) if trace[i] == "stack traceback:" then trace_starts = i; break end end + _G._syslog('') for _, line in pairs(trace) do _G._syslog(line) end