From 3ae286980ee8d26223176d8a7ce8b775b123e59c Mon Sep 17 00:00:00 2001 From: li041 Date: Wed, 21 Jan 2026 02:07:40 +0000 Subject: [PATCH] Genericize `kill*` functions with `Signal` trait --- kernel/src/process/exit.rs | 4 +-- kernel/src/process/kill.rs | 39 +++++++++++---------- kernel/src/process/process/mod.rs | 6 ++-- kernel/src/process/process/process_group.rs | 2 +- kernel/src/process/process/timer_manager.rs | 2 +- kernel/src/syscall/kill.rs | 9 +++-- kernel/src/syscall/tgkill.rs | 7 ++-- kernel/src/syscall/timer_create.rs | 4 +-- 8 files changed, 42 insertions(+), 31 deletions(-) diff --git a/kernel/src/process/exit.rs b/kernel/src/process/exit.rs index 3ae906044..ee64e6366 100644 --- a/kernel/src/process/exit.rs +++ b/kernel/src/process/exit.rs @@ -49,7 +49,7 @@ fn send_parent_death_signal(current_process: &Process) { }; // FIXME: Set `si_pid` in the `siginfo_t` argument. - let signal = KernelSignal::new(signum); + let signal = Box::new(KernelSignal::new(signum)); child.enqueue_signal(signal); } } @@ -142,7 +142,7 @@ fn send_child_death_signal(current_process: &Process) { }; if let Some(signal) = current_process.exit_signal().map(KernelSignal::new) { - parent.enqueue_signal(signal); + parent.enqueue_signal(Box::new(signal)); }; parent.children_wait_queue().wake_all(); } diff --git a/kernel/src/process/kill.rs b/kernel/src/process/kill.rs index bb2921b9c..c96bc0194 100644 --- a/kernel/src/process/kill.rs +++ b/kernel/src/process/kill.rs @@ -4,11 +4,7 @@ use super::{ Pgid, Pid, Process, posix_thread::{AsPosixThread, thread_table}, process_table, - signal::{ - constants::SIGCONT, - sig_num::SigNum, - signals::{Signal, user::UserSignal}, - }, + signal::{constants::SIGCONT, sig_num::SigNum, signals::Signal}, }; use crate::{ prelude::*, @@ -23,8 +19,8 @@ use crate::{ /// /// If `signal` is `None`, this method will only check permission without sending /// any signal. -pub fn kill(pid: Pid, signal: Option, ctx: &Context) -> Result<()> { - // Fast path: If the signal is sent to self, we can skip most check. +pub fn kill(pid: Pid, signal: Option>, ctx: &Context) -> Result<()> { + // Fast path: If the signal is sent to self, we can skip most checks. if pid == ctx.process.pid() { let Some(signal) = signal else { return Ok(()); @@ -32,7 +28,7 @@ pub fn kill(pid: Pid, signal: Option, ctx: &Context) -> Result<()> { if !ctx.posix_thread.has_signal_blocked(signal.num()) { // Killing the current thread does not raise any permission issues. - ctx.posix_thread.enqueue_signal(Box::new(signal)); + ctx.posix_thread.enqueue_signal(signal); return Ok(()); } @@ -40,7 +36,6 @@ pub fn kill(pid: Pid, signal: Option, ctx: &Context) -> Result<()> { } // Slow path - let process = process_table::get_process(pid) .ok_or_else(|| Error::with_message(Errno::ESRCH, "the target process does not exist"))?; @@ -55,7 +50,7 @@ pub fn kill(pid: Pid, signal: Option, ctx: &Context) -> Result<()> { /// /// If `signal` is `None`, this method will only check permission without sending /// any signal. -pub fn kill_group(pgid: Pgid, signal: Option, ctx: &Context) -> Result<()> { +pub fn kill_group(pgid: Pgid, signal: Option, ctx: &Context) -> Result<()> { let process_group = process_table::get_process_group(&pgid) .ok_or_else(|| Error::with_message(Errno::ESRCH, "the target group does not exist"))?; @@ -63,7 +58,11 @@ pub fn kill_group(pgid: Pgid, signal: Option, ctx: &Context) -> Resu let inner = process_group.lock(); for process in inner.iter() { - let res = kill_process(process, signal, ctx); + let res = kill_process( + process, + signal.clone().map(|s| Box::new(s) as Box), + ctx, + ); if res.is_err_and(|err| err.error() != Errno::EPERM) { result = res; } @@ -77,7 +76,7 @@ pub fn kill_group(pgid: Pgid, signal: Option, ctx: &Context) -> Resu /// /// If `signal` is `None`, this method will only check permission without sending /// any signal. -pub fn tgkill(tid: Tid, tgid: Pid, signal: Option, ctx: &Context) -> Result<()> { +pub fn tgkill(tid: Tid, tgid: Pid, signal: Option>, ctx: &Context) -> Result<()> { let thread = thread_table::get_thread(tid) .ok_or_else(|| Error::with_message(Errno::ESRCH, "the target thread does not exist"))?; let target_posix_thread = thread.as_posix_thread().unwrap(); @@ -92,7 +91,7 @@ pub fn tgkill(tid: Tid, tgid: Pid, signal: Option, ctx: &Context) -> } // Check permission - let signum = signal.map(|signal| signal.num()); + let signum = signal.as_ref().map(|signal| signal.num()); check_signal_perm(target_posix_thread, ctx, signum)?; if thread.is_exited() { @@ -102,7 +101,7 @@ pub fn tgkill(tid: Tid, tgid: Pid, signal: Option, ctx: &Context) -> if let Some(signal) = signal { // We've checked the permission issues above. // FIXME: We should take some lock while checking the permission to avoid race conditions. - target_posix_thread.enqueue_signal(Box::new(signal)); + target_posix_thread.enqueue_signal(signal); } Ok(()) @@ -113,7 +112,7 @@ pub fn tgkill(tid: Tid, tgid: Pid, signal: Option, ctx: &Context) -> /// /// The credentials of the current process will be checked to determine /// if it is authorized to send the signal to the target group. -pub fn kill_all(signal: Option, ctx: &Context) -> Result<()> { +pub fn kill_all(signal: Option, ctx: &Context) -> Result<()> { let mut result = Ok(()); for process in process_table::process_table_mut().iter() { @@ -121,7 +120,11 @@ pub fn kill_all(signal: Option, ctx: &Context) -> Result<()> { continue; } - let res = kill_process(process, signal, ctx); + let res = kill_process( + process, + signal.clone().map(|s| Box::new(s) as Box), + ctx, + ); if res.is_err_and(|err| err.error() != Errno::EPERM) { result = res; } @@ -130,8 +133,8 @@ pub fn kill_all(signal: Option, ctx: &Context) -> Result<()> { result } -fn kill_process(process: &Process, signal: Option, ctx: &Context) -> Result<()> { - let signum = signal.map(|signal| signal.num()); +fn kill_process(process: &Process, signal: Option>, ctx: &Context) -> Result<()> { + let signum = signal.as_ref().map(|signal| signal.num()); let target_main_thread = process.main_thread(); check_signal_perm(target_main_thread.as_posix_thread().unwrap(), ctx, signum)?; diff --git a/kernel/src/process/process/mod.rs b/kernel/src/process/process/mod.rs index 8c61b23bf..9e8617f79 100644 --- a/kernel/src/process/process/mod.rs +++ b/kernel/src/process/process/mod.rs @@ -634,12 +634,12 @@ impl Process { /// This method does not perform permission checks on user signals. /// Therefore, unless the caller can ensure that there are no permission issues, /// this method should be used to enqueue kernel signals or fault signals. - pub fn enqueue_signal(&self, signal: impl Signal + Clone + 'static) { + pub fn enqueue_signal(&self, signal: Box) { if self.status.is_zombie() { return; } - self.sig_queues.enqueue(Box::new(signal)); + self.sig_queues.enqueue(signal); for task in self.tasks.lock().as_slice() { let posix_thread = task.as_posix_thread().unwrap(); @@ -819,7 +819,7 @@ pub fn enqueue_signal_async(process: Weak, signum: SigNum) { work_queue::submit_work_func( move || { if let Some(process) = process.upgrade() { - process.enqueue_signal(KernelSignal::new(signum)); + process.enqueue_signal(Box::new(KernelSignal::new(signum))); } }, work_queue::WorkPriority::High, diff --git a/kernel/src/process/process/process_group.rs b/kernel/src/process/process/process_group.rs index 438a86e7c..9612ce40b 100644 --- a/kernel/src/process/process/process_group.rs +++ b/kernel/src/process/process/process_group.rs @@ -66,7 +66,7 @@ impl ProcessGroup { // TODO: Do some checks to forbid user signals. pub fn broadcast_signal(&self, signal: impl Signal + Clone + 'static) { for process in self.inner.lock().processes.values() { - process.enqueue_signal(signal.clone()); + process.enqueue_signal(Box::new(signal.clone())); } } } diff --git a/kernel/src/process/process/timer_manager.rs b/kernel/src/process/process/timer_manager.rs index 4fa345d0e..e65bb86cc 100644 --- a/kernel/src/process/process/timer_manager.rs +++ b/kernel/src/process/process/timer_manager.rs @@ -107,7 +107,7 @@ fn create_process_timer_callback( let sent_signal = move || { let signal = KernelSignal::new(SIGALRM); if let Some(process) = current_process.upgrade() { - process.enqueue_signal(signal); + process.enqueue_signal(Box::new(signal)); } }; diff --git a/kernel/src/syscall/kill.rs b/kernel/src/syscall/kill.rs index 90257bdbb..f1b3a5f8e 100644 --- a/kernel/src/syscall/kill.rs +++ b/kernel/src/syscall/kill.rs @@ -7,7 +7,10 @@ use crate::{ ProcessFilter, kill, kill_all, kill_group, signal::{ sig_num::SigNum, - signals::user::{UserSignal, UserSignalKind}, + signals::{ + Signal, + user::{UserSignal, UserSignalKind}, + }, }, }, }; @@ -36,7 +39,9 @@ pub fn do_sys_kill(filter: ProcessFilter, sig_num: Option, ctx: &Context match filter { ProcessFilter::Any => kill_all(signal, ctx)?, - ProcessFilter::WithPid(pid) => kill(pid, signal, ctx)?, + ProcessFilter::WithPid(pid) => { + kill(pid, signal.map(|s| Box::new(s) as Box), ctx)? + } ProcessFilter::WithPgid(pgid) => kill_group(pgid, signal, ctx)?, ProcessFilter::WithPidfd(_) => unreachable!(), } diff --git a/kernel/src/syscall/tgkill.rs b/kernel/src/syscall/tgkill.rs index ed88a4df9..ae89dbcdb 100644 --- a/kernel/src/syscall/tgkill.rs +++ b/kernel/src/syscall/tgkill.rs @@ -7,7 +7,10 @@ use crate::{ Pid, signal::{ sig_num::SigNum, - signals::user::{UserSignal, UserSignalKind}, + signals::{ + Signal, + user::{UserSignal, UserSignalKind}, + }, }, tgkill, }, @@ -30,7 +33,7 @@ pub fn sys_tgkill(tgid: Pid, tid: Tid, sig_num: u8, ctx: &Context) -> Result }); tgkill(tid, tgid, signal, ctx)?; Ok(SyscallReturn::Return(0)) diff --git a/kernel/src/syscall/timer_create.rs b/kernel/src/syscall/timer_create.rs index 70d448310..c0e9ff2c6 100644 --- a/kernel/src/syscall/timer_create.rs +++ b/kernel/src/syscall/timer_create.rs @@ -47,7 +47,7 @@ pub fn sys_timer_create( let process = current_process.clone(); let signal = KernelSignal::new(SIGALRM); Box::new(move || { - process.enqueue_signal(signal); + process.enqueue_signal(Box::new(signal)); }) // Determine the timeout action through `sigevent`. } else { @@ -62,7 +62,7 @@ pub fn sys_timer_create( let process = current_process.clone(); let signal = KernelSignal::new(SigNum::try_from(signo as u8)?); Box::new(move || { - process.enqueue_signal(signal); + process.enqueue_signal(Box::new(signal)); }) } // Spawn a posix thread to run the `sigev_function`, which is stored in