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.
This commit is contained in:
Ponali
2025-10-04 18:36:57 +02:00
parent db01a8d741
commit d63941814f
2 changed files with 124 additions and 126 deletions
+124 -122
View File
@@ -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