kill: awake sleepy tasks on SIGKILL

If a SIGKILL has been received, ensure all sleepy tasks are set to
runnable so that they can action the signal.
This commit is contained in:
Matthew Leach
2026-01-11 20:32:33 +00:00
committed by Ashwin Naren
parent df578992b8
commit abbc8261c5
4 changed files with 36 additions and 20 deletions

View File

@@ -1,5 +1,5 @@
use super::{Task, Tid};
use crate::{memory::uaccess::UserCopyable, sync::SpinLock};
use super::{Task, TaskState, Tid};
use crate::{memory::uaccess::UserCopyable, sched::waker::create_waker, sync::SpinLock};
use alloc::{
collections::btree_map::BTreeMap,
sync::{Arc, Weak},
@@ -12,7 +12,7 @@ use core::{
};
use pid::PidT;
use rsrc_lim::ResourceLimits;
use signal::{SigSet, SignalActionState};
use signal::{SigId, SigSet, SignalActionState};
use wait::ChildNotifiers;
pub mod builder;
@@ -155,6 +155,30 @@ impl ThreadGroup {
pub fn get(id: Tgid) -> Option<Arc<Self>> {
TG_LIST.lock_save_irq().get(&id).and_then(|x| x.upgrade())
}
pub fn deliver_signal(&self, signal: SigId) {
match signal {
SigId::SIGKILL => {
// Set the sigkill marker in the pending signals and wake up all
// tasks in this group.
*self.pending_signals.lock_save_irq() = SigSet::SIGKILL;
for task in self.tasks.lock_save_irq().values() {
if let Some(task) = task.upgrade()
&& matches!(
*task.state.lock_save_irq(),
TaskState::Stopped | TaskState::Sleeping
)
{
create_waker(task.descriptor()).wake();
}
}
}
_ => {
self.pending_signals.lock_save_irq().set_signal(signal);
}
}
}
}
impl Drop for ThreadGroup {

View File

@@ -16,18 +16,15 @@ pub fn sys_kill(pid: PidT, signal: UserSigId) -> Result<usize> {
let current_task = current_task();
// Kill ourselves
if pid == current_task.process.tgid.value() as PidT {
current_task
.process
.pending_signals
.lock_save_irq()
.set_signal(signal);
current_task.process.deliver_signal(signal);
return Ok(0);
}
match pid {
p if p > 0 => {
let target_tg = ThreadGroup::get(Tgid(p as _)).ok_or(KernelError::NoProcess)?;
target_tg.pending_signals.lock_save_irq().set_signal(signal);
target_tg.deliver_signal(signal);
}
0 => {
@@ -41,7 +38,7 @@ pub fn sys_kill(pid: PidT, signal: UserSigId) -> Result<usize> {
if let Some(tg) = tg_weak.upgrade()
&& *tg.pgid.lock_save_irq() == our_pgid
{
tg.pending_signals.lock_save_irq().set_signal(signal);
tg.deliver_signal(signal);
}
}
}
@@ -55,7 +52,7 @@ pub fn sys_kill(pid: PidT, signal: UserSigId) -> Result<usize> {
if let Some(tg) = tg_weak.upgrade()
&& *tg.pgid.lock_save_irq() == target_pgid
{
tg.pending_signals.lock_save_irq().set_signal(signal);
tg.deliver_signal(signal);
}
}
}

View File

@@ -274,10 +274,7 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
.child_notifiers
.child_update(process.tgid, ChildState::Stop { signal });
parent
.pending_signals
.lock_save_irq()
.set_signal(SigId::SIGCHLD);
parent.deliver_signal(SigId::SIGCHLD);
}
for thr_weak in process.tasks.lock_save_irq().values() {
@@ -313,10 +310,8 @@ pub fn dispatch_userspace_task(ctx: *mut UserCtx) {
parent
.child_notifiers
.child_update(process.tgid, ChildState::Continue);
parent
.pending_signals
.lock_save_irq()
.set_signal(SigId::SIGCHLD);
parent.deliver_signal(SigId::SIGCHLD);
}
// Re-process kernel work for this task (there may be more to do).

View File

@@ -26,7 +26,7 @@ unsafe fn wake_waker(data: *const ()) {
match *state {
// If the task has been put to sleep, then wake it up.
TaskState::Sleeping => {
TaskState::Sleeping | TaskState::Stopped => {
if locus == CpuId::this() {
*state = TaskState::Runnable;
SCHED_STATE.borrow_mut().wakeup(desc);