]> Projects (at) Tadryanom (dot) Me - AdrOS.git/commit
fix: remove killed READY processes from runqueue before marking ZOMBIE
authorTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 09:00:13 +0000 (06:00 -0300)
committerTulio A M Mendes <[email protected]>
Fri, 13 Feb 2026 09:00:13 +0000 (06:00 -0300)
commit7b2a137f90710449a5b16878ad019805534e4821
tree5eb495701f313321f95ccd975e94ced0a03ddb26
parent462c65aedfb5e37b6b9cc26eec5f10c53f9f6e35
fix: remove killed READY processes from runqueue before marking ZOMBIE

Root cause of intermittent kernel panic (PAGE FAULT at 0x0, ESP=0):

When process_kill(SIGKILL) killed a READY process (sitting in
rq_active or rq_expired), it set state=ZOMBIE but did NOT remove
the process from the runqueue. Later, the parent reaped the ZOMBIE
via waitpid → process_reap_locked → kfree(p), freeing the struct.
But the freed pointer remained in the runqueue. rq_pick_next()
returned the dangling pointer, schedule() read sp=0 from freed
heap memory, and context_switch loaded ESP=0 → PAGE FAULT.

The 'ring3' cmdline flag masked this bug by changing scheduler
timing: with ring3, the BSP entered usermode immediately via iret,
altering the sequence of context switches such that the ZOMBIE was
typically dequeued before being reaped.

Fix:
- Add rq_remove_if_queued() helper: safely searches both rq_active
  and rq_expired for a process at its priority level before calling
  rq_dequeue()
- process_kill(SIGKILL): dequeue READY victims before setting ZOMBIE
- process_reap_locked(): dequeue as safety net before freeing

Verified: 10/10 boots without 'ring3' — zero panics (was ~50% fail).
Build: clean, cppcheck: clean, smoke: 19/19 pass
src/kernel/scheduler.c