From ecf6edb826727de884b87b339f7160b75cf3aca3 Mon Sep 17 00:00:00 2001 From: Daniel Hammer Date: Thu, 7 May 2026 07:32:44 +0200 Subject: [PATCH] fix: add start pending mode to mitigate Terminal output redirection issue --- kernel/src/Api/IoRedir.hpp | 15 ++++++++---- kernel/src/Api/Process.hpp | 9 ++++++-- kernel/src/Sched/Scheduler.cpp | 42 ++++++++++++++++++++++++++++++---- kernel/src/Sched/Scheduler.hpp | 4 +++- 4 files changed, 59 insertions(+), 11 deletions(-) diff --git a/kernel/src/Api/IoRedir.hpp b/kernel/src/Api/IoRedir.hpp index 369799f..2f5af9b 100644 --- a/kernel/src/Api/IoRedir.hpp +++ b/kernel/src/Api/IoRedir.hpp @@ -18,12 +18,15 @@ namespace Montauk { if (!ResolveProcessPath(path, resolved, sizeof(resolved))) return -1; int parentSlot = Ipc::CurrentSlot(); - int childPid = Sched::Spawn(resolved, args); + int childPid = Sched::Spawn(resolved, args, false); if (childPid < 0) return -1; auto* child = Sched::GetProcessByPid(childPid); int childSlot = Ipc::SlotForPid(childPid); - if (child == nullptr || childSlot < 0 || parentSlot < 0) return -1; + if (child == nullptr || childSlot < 0 || parentSlot < 0) { + Sched::KillProcess(childPid); + return -1; + } Ipc::Stream* outStream = Ipc::CreateStream(); Ipc::Stream* inStream = Ipc::CreateStream(); @@ -68,8 +71,12 @@ namespace Montauk { child->redirected = true; child->parentPid = Sched::GetCurrentPid(); - child->termCols = 0; - child->termRows = 0; + child->termCols = 80; + child->termRows = 25; + if (Sched::StartProcess(childPid) < 0) { + Sched::KillProcess(childPid); + return -1; + } return childPid; } diff --git a/kernel/src/Api/Process.hpp b/kernel/src/Api/Process.hpp index aa1d6b6..6025505 100644 --- a/kernel/src/Api/Process.hpp +++ b/kernel/src/Api/Process.hpp @@ -46,10 +46,11 @@ namespace Montauk { auto* parent = Sched::GetCurrentProcessPtr(); int parentSlot = Ipc::CurrentSlot(); - int childPid = Sched::Spawn(resolved, args); + bool inheritRedirection = parent && parent->redirected; + int childPid = Sched::Spawn(resolved, args, !inheritRedirection); if (childPid < 0) return childPid; - if (parent && parent->redirected) { + if (inheritRedirection) { auto* child = Sched::GetProcessByPid(childPid); int childSlot = Ipc::SlotForPid(childPid); if (child == nullptr || childSlot < 0 || parentSlot < 0) { @@ -71,6 +72,10 @@ namespace Montauk { child->parentPid = parent->pid; child->termCols = parent->termCols; child->termRows = parent->termRows; + if (Sched::StartProcess(childPid) < 0) { + Sched::KillProcess(childPid); + return -1; + } } return childPid; diff --git a/kernel/src/Sched/Scheduler.cpp b/kernel/src/Sched/Scheduler.cpp index 2bc975c..d868960 100644 --- a/kernel/src/Sched/Scheduler.cpp +++ b/kernel/src/Sched/Scheduler.cpp @@ -175,6 +175,7 @@ namespace Sched { processTable[i].runningOnCpu = -1; processTable[i].killPending = false; processTable[i].reapReady = false; + processTable[i].startPending = false; processTable[i].waitingForPid = -1; processTable[i].sleepUntilTick = 0; processTable[i].waitingOnObject = nullptr; @@ -203,7 +204,7 @@ namespace Sched { << " process slots, " << (uint64_t)TimeSliceMs << " ms time slice)"; } - int Spawn(const char* vfsPath, const char* args) { + int Spawn(const char* vfsPath, const char* args, bool startReady) { schedLock.Acquire(); int slot = -1; @@ -343,8 +344,9 @@ namespace Sched { Process& proc = processTable[slot]; proc.pid = nextPid++; - proc.state = ProcessState::Ready; - readyCount++; + proc.state = startReady ? ProcessState::Ready : ProcessState::Blocked; + if (startReady) + readyCount++; { int i = 0; for (; i < 63 && vfsPath[i]; i++) proc.name[i] = vfsPath[i]; @@ -363,6 +365,7 @@ namespace Sched { proc.runningOnCpu = -1; proc.killPending = false; proc.reapReady = false; + proc.startPending = !startReady; proc.waitingForPid = -1; proc.sleepUntilTick = 0; proc.waitingOnObject = nullptr; @@ -436,11 +439,39 @@ namespace Sched { int resultPid = proc.pid; schedLock.Release(); - KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1); + if (startReady) + KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1); return resultPid; } + int StartProcess(int pid) { + if (pid < 0) return -1; + + schedLock.Acquire(); + for (int i = 0; i < MaxProcesses; i++) { + if (processTable[i].pid != pid) continue; + if (processTable[i].state != ProcessState::Blocked || + !processTable[i].startPending) { + schedLock.Release(); + return -1; + } + + processTable[i].startPending = false; + processTable[i].waitingForPid = -1; + processTable[i].sleepUntilTick = 0; + processTable[i].waitingOnObject = nullptr; + processTable[i].state = ProcessState::Ready; + readyCount++; + schedLock.Release(); + KickOneIdleCpu(Smp::GetCurrentCpuData() ? Smp::GetCurrentCpuData()->cpuIndex : -1); + return 0; + } + + schedLock.Release(); + return -1; + } + // ==================================================================== // Schedule -- core context switch logic // @@ -470,6 +501,7 @@ namespace Sched { processTable[i].stackBase = 0; processTable[i].pml4Phys = 0; processTable[i].reapReady = false; + processTable[i].startPending = false; processTable[i].state = ProcessState::Free; // Release lock during PFA::Free to minimize hold time @@ -683,6 +715,7 @@ namespace Sched { Process& proc = processTable[slot]; proc.killPending = false; + proc.startPending = false; int exitingPid = proc.pid; // Clean up any windows owned by this process @@ -823,6 +856,7 @@ namespace Sched { readyCount--; proc.state = ProcessState::Terminated; proc.killPending = false; + proc.startPending = false; proc.reapReady = false; proc.waitingForPid = -1; proc.sleepUntilTick = 0; diff --git a/kernel/src/Sched/Scheduler.hpp b/kernel/src/Sched/Scheduler.hpp index 58ee9ff..d09cc32 100644 --- a/kernel/src/Sched/Scheduler.hpp +++ b/kernel/src/Sched/Scheduler.hpp @@ -55,6 +55,7 @@ namespace Sched { int runningOnCpu; // CPU index running this process (-1 if not running) bool killPending = false; // Set by Sys_Kill when target is running on another CPU bool reapReady = false; // Set once teardown is complete and BSP may free slot resources + bool startPending = false; // Spawned but not yet made runnable // I/O redirection for GUI terminal bool redirected = false; @@ -85,7 +86,8 @@ namespace Sched { }; void Initialize(); - int Spawn(const char* vfsPath, const char* args = nullptr); + int Spawn(const char* vfsPath, const char* args = nullptr, bool startReady = true); + int StartProcess(int pid); void Schedule(); // True when there is runnable work somewhere in the process table.