From d63941814f5a680a09d850f7e8a9c4d958ac6420 Mon Sep 17 00:00:00 2001 From: Ponali Date: Sat, 4 Oct 2025 18:36:57 +0200 Subject: [PATCH] fix tsched crashing when a process gets removed when a process removes another process, the amount of processes tsched has decrements, but the for loop doesn't update. a check has been implemented to check for when the task that's getting looked up doesn't exist. --- halyde/kernel/tsched.lua | 246 ++++++++++++++++++++------------------- halyde/system.log | 4 - 2 files changed, 124 insertions(+), 126 deletions(-) delete mode 100644 halyde/system.log diff --git a/halyde/kernel/tsched.lua b/halyde/kernel/tsched.lua index 8bf9643..773654a 100644 --- a/halyde/kernel/tsched.lua +++ b/halyde/kernel/tsched.lua @@ -14,139 +14,141 @@ local gpu = component.gpu local log = require("log") function _G._PUBLIC.tsched.runAsTask(path, ...) - local args = { ... } - local function taskFunction() - local result, errorMessage = xpcall(function(...) - local args = table.pack(...) - if not filesystem.exists(path) then - error("No such file: " .. path) - end - local handle, data, tmpdata = filesystem.open(path), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() + local args = { ... } + local function taskFunction() + local result, errorMessage = xpcall(function(...) + local args = table.pack(...) + if not filesystem.exists(path) then + error("No such file: " .. path) + end + local handle, data, tmpdata = filesystem.open(path), "", nil + repeat + tmpdata = handle:read(math.huge or math.maxinteger) + data = data .. (tmpdata or "") + until not tmpdata + handle:close() - -- Userland environment definition - local userland = table.copy(_PUBLIC) - userland._G = userland - userland.load = function(chunk, chunkname, mode, env) - if not env or env == _G then - env = userland - end -- if they SOMEHOW get the kernel environment they're not running jack shit - return load(chunk, chunkname, mode, env) - end - userland.require = reqgen(userland.load) + -- Userland environment definition + local userland = table.copy(_PUBLIC) + userland._G = userland + userland.load = function(chunk, chunkname, mode, env) + if not env or env == _G then + env = userland + end -- if they SOMEHOW get the kernel environment they're not running jack shit + return load(chunk, chunkname, mode, env) + end + userland.require = reqgen(userland.load) - assert(load(data, "=" .. path, "t", userland))(table.unpack(args)) - end, function(errorMessage) - return errorMessage .. "\n \n" .. debug.traceback() - end, --[[ path,]] table.unpack(args)) - if not result then - if print then - gpu.freeAllBuffers() - print("\n\27[91m" .. errorMessage) - else - error(errorMessage) - end - end - --require(path, table.unpack(args)) - end - local _, taskInfo = _PUBLIC.tsched.addTask(taskFunction, string.match(tostring(path), "([^/]+)%.lua$")) - taskInfo.path = path - taskInfo.args = table.copy(args) + assert(load(data, "=" .. path, "t", userland))(table.unpack(args)) + end, function(errorMessage) + return errorMessage .. "\n \n" .. debug.traceback() + end, --[[ path,]] table.unpack(args)) + if not result then + if print then + gpu.freeAllBuffers() + print("\n\27[91m" .. errorMessage) + else + error(errorMessage) + end + end + --require(path, table.unpack(args)) + end + local _, taskInfo = _PUBLIC.tsched.addTask(taskFunction, string.match(tostring(path), "([^/]+)%.lua$")) + taskInfo.path = path + taskInfo.args = table.copy(args) end function _G._PUBLIC.tsched.addTask(func, name) - local task = coroutine.create(func) - local taskInfo = { ["task"] = task, ["name"] = name, ["id"] = idCounter } - if currentTask and type(currentTask.id) == "number" then - taskInfo.parent = currentTask.id - end - table.insert(tsched.tasks, taskInfo) - idCounter = idCounter + 1 - if taskInfo.parent then - log.kernel.info( - "Created task " .. name .. " with PID " .. idCounter - 1 .. " by parent with PID " .. taskInfo.parent - ) - else - log.kernel.info("Created task " .. name .. " with PID " .. idCounter - 1 .. " (no parent found)") - end - return task, taskInfo + local task = coroutine.create(func) + local taskInfo = { ["task"] = task, ["name"] = name, ["id"] = idCounter } + if currentTask and type(currentTask.id) == "number" then + taskInfo.parent = currentTask.id + end + table.insert(tsched.tasks, taskInfo) + idCounter = idCounter + 1 + if taskInfo.parent then + log.kernel.info( + "Created task " .. name .. " with PID " .. idCounter - 1 .. " by parent with PID " .. taskInfo.parent + ) + else + log.kernel.info("Created task " .. name .. " with PID " .. idCounter - 1 .. " (no parent found)") + end + return task, taskInfo end function _G._PUBLIC.tsched.removeTask(id) - -- TODO: Check for user permissions before running - for index, task in pairs(tsched.tasks) do - if task.id == id then - table.remove(tsched.tasks, index) - log.kernel.info("Removed task with PID " .. id) - return true - end - end - log.kernel.warn("Tried to remove task that doesn't exist - PID " .. id) - return false + -- TODO: Check for user permissions before running + for index, task in pairs(tsched.tasks) do + if task.id == id then + table.remove(tsched.tasks, index) + log.kernel.info("Removed task with PID " .. id) + return true + end + end + log.kernel.warn("Tried to remove task that doesn't exist - PID " .. id) + return false end function handleError(errormsg) - if errormsg == nil then -- TODO: Replace with proper error handling - print("\27[91munknown error" .. "\n \n" .. debug.traceback()) - else - print("\27[91m" .. tostring(errormsg) .. "\n \n" .. debug.traceback()) - end + if errormsg == nil then -- TODO: Replace with proper error handling + print("\27[91munknown error" .. "\n \n" .. debug.traceback()) + else + print("\27[91m" .. tostring(errormsg) .. "\n \n" .. debug.traceback()) + end end local function runTasks() - for i = 1, #_G.tsched.tasks do - if tsched.tasks[i] then - currentTask = tsched.tasks[i] - local result, errorMessage = coroutine.resume(tsched.tasks[i].task) - if not result then - handleError(errorMessage) - end - if coroutine.status(tsched.tasks[i].task) == "dead" then - _PUBLIC.tsched.removeTask(tsched.tasks[i].id) - --ocelot.log("Removed coroutine") - i = i - 1 - end - --computer.pullSignal(0) - --coroutine.yield() - end - end + for i = 1, #_G.tsched.tasks do + if tsched.tasks[i] then + currentTask = tsched.tasks[i] + local result, errorMessage = coroutine.resume(tsched.tasks[i].task) + if not result then + handleError(errorMessage) + end + if not tsched.tasks[i] then + log.kernel.warn("Attempted to update a non-existent task. This is likely because it was removed.") + elseif coroutine.status(tsched.tasks[i].task) == "dead" then + _PUBLIC.tsched.removeTask(tsched.tasks[i].id) + --ocelot.log("Removed coroutine") + i = i - 1 + end + --computer.pullSignal(0) + --coroutine.yield() + end + end end function _G._PUBLIC.tsched.getCurrentTask() - return table.copy(currentTask) + return table.copy(currentTask) end function _G._PUBLIC.tsched.getTasks() - return table.copy(tsched.tasks) + return table.copy(tsched.tasks) end local function taskFunction() - local result, errorMessage = xpcall(function() - if not filesystem.exists("/halyde/kernel/evmgr.lua") then - error("No such file: /halyde/kernel/evmgr.lua") - end - local handle, data, tmpdata = filesystem.open("/halyde/kernel/evmgr.lua"), "", nil - repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") - until not tmpdata - handle:close() - assert(load(data, "=/halyde/kernel/evmgr.lua"))() - end, function(errorMessage) - return errorMessage .. "\n \n" .. debug.traceback() - end, "/halyde/kernel/evmgr.lua") - if not result then - if print then - gpu.freeAllBuffers() - print("\n\27[91m" .. errorMessage) - else - error(errorMessage) - end - end + local result, errorMessage = xpcall(function() + if not filesystem.exists("/halyde/kernel/evmgr.lua") then + error("No such file: /halyde/kernel/evmgr.lua") + end + local handle, data, tmpdata = filesystem.open("/halyde/kernel/evmgr.lua"), "", nil + repeat + tmpdata = handle:read(math.huge or math.maxinteger) + data = data .. (tmpdata or "") + until not tmpdata + handle:close() + assert(load(data, "=/halyde/kernel/evmgr.lua"))() + end, function(errorMessage) + return errorMessage .. "\n \n" .. debug.traceback() + end, "/halyde/kernel/evmgr.lua") + if not result then + if print then + gpu.freeAllBuffers() + print("\n\27[91m" .. errorMessage) + else + error(errorMessage) + end + end end _PUBLIC.tsched.addTask(taskFunction, "evmgr") package.preload("event") @@ -154,26 +156,26 @@ package.preload("event") log.kernel.info("Starting startup apps...") local handle, data, tmpdata = filesystem.open("/halyde/config/startupapps.json", "r"), "", nil repeat - tmpdata = handle:read(math.huge or math.maxinteger) - data = data .. (tmpdata or "") + tmpdata = handle:read(math.huge or math.maxinteger) + data = data .. (tmpdata or "") until not tmpdata handle:close() for _, line in ipairs(json.decode(data)) do - if line ~= "" then - --[[ if _G.print then + if line ~= "" then + --[[ if _G.print then print(line) end ]] - _G._PUBLIC.tsched.runAsTask(line) - runTasks() - end + _G._PUBLIC.tsched.runAsTask(line) + runTasks() + end end -- _G.cormgr.loadCoroutine("/halyde/core/shell.lua") log.setPrintLogs(false) while true do - runTasks() - if #_G.tsched.tasks == 0 then - log.kernel.warn("No more tasks left! Shutting down...") - computer.shutdown() - end + runTasks() + if #_G.tsched.tasks == 0 then + log.kernel.warn("No more tasks left! Shutting down...") + computer.shutdown() + end end diff --git a/halyde/system.log b/halyde/system.log deleted file mode 100644 index 5e48223..0000000 --- a/halyde/system.log +++ /dev/null @@ -1,4 +0,0 @@ -[00:00:04:12] Debug! -[00:00:04:19] Info! -[00:00:04:25] Warning! -[00:00:04:32] Error!