From 6414111cc57b42db2bae1a0c8b01b85c3830a3b3 Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Wed, 7 Aug 2024 09:17:46 +0000 Subject: [PATCH] Support flag SA_RESETHAND --- kernel/aster-nix/src/process/signal/mod.rs | 44 +++++++++++++------ .../src/process/signal/sig_action.rs | 6 +-- 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/kernel/aster-nix/src/process/signal/mod.rs b/kernel/aster-nix/src/process/signal/mod.rs index a53dcf201..f1407a28e 100644 --- a/kernel/aster-nix/src/process/signal/mod.rs +++ b/kernel/aster-nix/src/process/signal/mod.rs @@ -60,7 +60,8 @@ pub fn handle_pending_signal( let sig_num = signal.num(); trace!("sig_num = {:?}, sig_name = {}", sig_num, sig_num.sig_name()); let current = posix_thread.process(); - let sig_action = current.sig_dispositions().lock().get(sig_num); + let mut sig_dispositions = current.sig_dispositions().lock(); + let sig_action = sig_dispositions.get(sig_num); trace!("sig action: {:x?}", sig_action); match sig_action { SigAction::Ign => { @@ -71,16 +72,30 @@ pub fn handle_pending_signal( flags, restorer_addr, mask, - } => handle_user_signal( - sig_num, - handler_addr, - flags, - restorer_addr, - mask, - context, - signal.to_info(), - )?, + } => { + if flags.contains(SigActionFlags::SA_RESETHAND) { + // In Linux, SA_RESETHAND corresponds to SA_ONESHOT, + // which means the user handler will be executed only once and then reset to the default. + // Refer to https://elixir.bootlin.com/linux/v6.0.9/source/kernel/signal.c#L2761. + sig_dispositions.set_default(sig_num); + } + + drop(sig_dispositions); + + handle_user_signal( + posix_thread, + sig_num, + handler_addr, + flags, + restorer_addr, + mask, + context, + signal.to_info(), + )? + } SigAction::Dfl => { + drop(sig_dispositions); + let sig_default_action = SigDefaultAction::from_signum(sig_num); trace!("sig_default_action: {:?}", sig_default_action); match sig_default_action { @@ -116,7 +131,9 @@ pub fn handle_pending_signal( Ok(()) } +#[allow(clippy::too_many_arguments)] pub fn handle_user_signal( + posix_thread: &PosixThread, sig_num: SigNum, handler_addr: Vaddr, flags: SigActionFlags, @@ -131,15 +148,14 @@ pub fn handle_user_signal( debug!("restorer_addr = 0x{:x}", restorer_addr); // FIXME: How to respect flags? if flags.contains_unsupported_flag() { - println!("flags = {:?}", flags); - panic!("Unsupported Signal flags"); + warn!("Unsupported Signal flags: {:?}", flags); } + if !flags.contains(SigActionFlags::SA_NODEFER) { // add current signal to mask mask += sig_num; } - let current_thread = current_thread!(); - let posix_thread = current_thread.as_posix_thread().unwrap(); + // block signals in sigmask when running signal handler let old_mask = posix_thread.sig_mask().load(Ordering::Relaxed); posix_thread diff --git a/kernel/aster-nix/src/process/signal/sig_action.rs b/kernel/aster-nix/src/process/signal/sig_action.rs index 52293ce41..73711b235 100644 --- a/kernel/aster-nix/src/process/signal/sig_action.rs +++ b/kernel/aster-nix/src/process/signal/sig_action.rs @@ -103,11 +103,7 @@ impl SigActionFlags { } pub fn contains_unsupported_flag(&self) -> bool { - self.intersects( - SigActionFlags::SA_NOCLDSTOP - | SigActionFlags::SA_NOCLDWAIT - | SigActionFlags::SA_RESETHAND, - ) + self.intersects(SigActionFlags::SA_NOCLDSTOP | SigActionFlags::SA_NOCLDWAIT) } }