From 57fc6a5402caf04e219ac5fb1d55a87ae0170a5d Mon Sep 17 00:00:00 2001 From: Jianfeng Jiang Date: Mon, 8 Jan 2024 03:36:16 +0000 Subject: [PATCH] Support parent death signal & Refactor do_exit --- kernel/aster-nix/src/process/clone.rs | 5 +- kernel/aster-nix/src/process/exit.rs | 27 ++++--- .../src/process/posix_thread/builder.rs | 10 --- .../src/process/posix_thread/exit.rs | 65 ++++++++++++++++ .../aster-nix/src/process/posix_thread/mod.rs | 77 +++---------------- .../aster-nix/src/process/process/builder.rs | 4 +- kernel/aster-nix/src/process/process/mod.rs | 37 +++++++-- .../aster-nix/src/process/signal/sig_num.rs | 49 ++++++++++++ kernel/aster-nix/src/syscall/execve.rs | 22 ++++-- kernel/aster-nix/src/syscall/exit.rs | 12 +-- kernel/aster-nix/src/syscall/prctl.rs | 33 +++++++- kernel/aster-nix/src/thread/mod.rs | 10 ++- regression/apps/scripts/process.sh | 1 + .../apps/signal_c/parent_death_signal.c | 49 ++++++++++++ 14 files changed, 281 insertions(+), 120 deletions(-) create mode 100644 kernel/aster-nix/src/process/posix_thread/exit.rs create mode 100644 regression/apps/signal_c/parent_death_signal.c diff --git a/kernel/aster-nix/src/process/clone.rs b/kernel/aster-nix/src/process/clone.rs index dbbedfa64..646bafcf8 100644 --- a/kernel/aster-nix/src/process/clone.rs +++ b/kernel/aster-nix/src/process/clone.rs @@ -181,8 +181,6 @@ fn clone_child_thread(parent_context: &UserContext, clone_args: CloneArgs) -> Re let child_tid = allocate_tid(); let child_thread = { - let is_main_thread = child_tid == current.pid(); - let credentials = { let credentials = credentials(); Credentials::new_from(&credentials) @@ -190,8 +188,7 @@ fn clone_child_thread(parent_context: &UserContext, clone_args: CloneArgs) -> Re let thread_builder = PosixThreadBuilder::new(child_tid, child_user_space, credentials) .process(Arc::downgrade(¤t)) - .sig_mask(sig_mask) - .is_main_thread(is_main_thread); + .sig_mask(sig_mask); thread_builder.build() }; diff --git a/kernel/aster-nix/src/process/exit.rs b/kernel/aster-nix/src/process/exit.rs index e6a34530b..dce7a559f 100644 --- a/kernel/aster-nix/src/process/exit.rs +++ b/kernel/aster-nix/src/process/exit.rs @@ -4,7 +4,7 @@ use super::{process_table, Pid, Process, TermStatus}; use crate::{ prelude::*, process::{ - posix_thread::PosixThreadExt, + posix_thread::do_exit, signal::{constants::SIGCHLD, signals::kernel::KernelSignal}, }, }; @@ -20,17 +20,22 @@ pub fn do_exit_group(term_status: TermStatus) { // Exit all threads let threads = current.threads().lock().clone(); for thread in threads { - if thread.status().is_exited() { - continue; + if let Err(e) = do_exit(thread, term_status) { + debug!("Ignore error when call exit: {:?}", e); } + } - thread.exit(); - if let Some(posix_thread) = thread.as_posix_thread() { - let tid = thread.tid(); - if let Err(e) = posix_thread.exit(tid, term_status) { - debug!("Ignore error when call exit: {:?}", e); - } - } + // Sends parent-death signal + // FIXME: according to linux spec, the signal should be sent when a posix thread which + // creates child process exits, not when the whole process exits group. + for (_, child) in current.children().lock().iter() { + let Some(signum) = child.parent_death_signal() else { + continue; + }; + + // FIXME: set pid of the signal + let signal = KernelSignal::new(signum); + child.enqueue_signal(signal); } // Close all files then exit the process @@ -61,7 +66,7 @@ pub fn do_exit_group(term_status: TermStatus) { const INIT_PROCESS_PID: Pid = 1; -/// Get the init process +/// Gets the init process fn get_init_process() -> Option> { process_table::get_process(INIT_PROCESS_PID) } diff --git a/kernel/aster-nix/src/process/posix_thread/builder.rs b/kernel/aster-nix/src/process/posix_thread/builder.rs index a06f33289..a807a37e4 100644 --- a/kernel/aster-nix/src/process/posix_thread/builder.rs +++ b/kernel/aster-nix/src/process/posix_thread/builder.rs @@ -30,7 +30,6 @@ pub struct PosixThreadBuilder { clear_child_tid: Vaddr, sig_mask: SigMask, sig_queues: SigQueues, - is_main_thread: bool, } impl PosixThreadBuilder { @@ -45,7 +44,6 @@ impl PosixThreadBuilder { clear_child_tid: 0, sig_mask: SigMask::new_empty(), sig_queues: SigQueues::new(), - is_main_thread: true, } } @@ -69,12 +67,6 @@ impl PosixThreadBuilder { self } - #[allow(clippy::wrong_self_convention)] - pub fn is_main_thread(mut self, is_main_thread: bool) -> Self { - self.is_main_thread = is_main_thread; - self - } - pub fn sig_mask(mut self, sig_mask: SigMask) -> Self { self.sig_mask = sig_mask; self @@ -91,7 +83,6 @@ impl PosixThreadBuilder { clear_child_tid, sig_mask, sig_queues, - is_main_thread, } = self; let thread = Arc::new_cyclic(|thread_ref| { @@ -104,7 +95,6 @@ impl PosixThreadBuilder { let posix_thread = PosixThread { process, - is_main_thread, name: Mutex::new(thread_name), set_child_tid: Mutex::new(set_child_tid), clear_child_tid: Mutex::new(clear_child_tid), diff --git a/kernel/aster-nix/src/process/posix_thread/exit.rs b/kernel/aster-nix/src/process/posix_thread/exit.rs new file mode 100644 index 000000000..9a006860c --- /dev/null +++ b/kernel/aster-nix/src/process/posix_thread/exit.rs @@ -0,0 +1,65 @@ +// SPDX-License-Identifier: MPL-2.0 + +use super::{futex::futex_wake, robust_list::wake_robust_futex, PosixThread, PosixThreadExt}; +use crate::{ + prelude::*, + process::{do_exit_group, TermStatus}, + thread::{thread_table, Thread, Tid}, + util::write_val_to_user, +}; + +/// Exits the thread if the thread is a POSIX thread. +/// +/// # Panics +/// +/// If the thread is not a POSIX thread, this method will panic. +pub fn do_exit(thread: Arc, term_status: TermStatus) -> Result<()> { + if thread.status().is_exited() { + return Ok(()); + } + thread.exit(); + + let tid = thread.tid(); + + let posix_thread = thread.as_posix_thread().unwrap(); + + let mut clear_ctid = posix_thread.clear_child_tid().lock(); + // If clear_ctid !=0 ,do a futex wake and write zero to the clear_ctid addr. + if *clear_ctid != 0 { + futex_wake(*clear_ctid, 1)?; + // FIXME: the correct write length? + write_val_to_user(*clear_ctid, &0u32).unwrap(); + *clear_ctid = 0; + } + // exit the robust list: walk the robust list; mark futex words as dead and do futex wake + wake_robust_list(posix_thread, tid); + + if tid != posix_thread.process().pid() { + // We don't remove main thread. + // The main thread is removed when the process is reaped. + thread_table::remove_thread(tid); + } + + if posix_thread.is_main_thread(tid) || posix_thread.is_last_thread() { + // exit current process. + do_exit_group(term_status); + } + + futex_wake(Arc::as_ptr(&posix_thread.process()) as Vaddr, 1)?; + Ok(()) +} + +/// Walks the robust futex list, marking futex dead and wake waiters. +/// It corresponds to Linux's exit_robust_list(), errors are silently ignored. +fn wake_robust_list(thread: &PosixThread, tid: Tid) { + let mut robust_list = thread.robust_list.lock(); + let list_head = match *robust_list { + Some(robust_list_head) => robust_list_head, + None => return, + }; + trace!("wake the rubust_list: {:?}", list_head); + for futex_addr in list_head.futexes() { + wake_robust_futex(futex_addr, tid).unwrap(); + } + *robust_list = None; +} diff --git a/kernel/aster-nix/src/process/posix_thread/mod.rs b/kernel/aster-nix/src/process/posix_thread/mod.rs index 593a4857b..4af180e55 100644 --- a/kernel/aster-nix/src/process/posix_thread/mod.rs +++ b/kernel/aster-nix/src/process/posix_thread/mod.rs @@ -3,11 +3,8 @@ #![allow(dead_code)] use aster_rights::{ReadOp, WriteOp}; -use futex::futex_wake; -use robust_list::wake_robust_futex; use super::{ - do_exit_group, kill::SignalSenderIds, signal::{ sig_mask::{SigMask, SigSet}, @@ -16,24 +13,25 @@ use super::{ signals::Signal, SigEvents, SigEventsFilter, SigStack, }, - Credentials, Process, TermStatus, + Credentials, Process, }; use crate::{ events::Observer, prelude::*, process::signal::constants::SIGCONT, - thread::{thread_table, Tid}, + thread::Tid, time::{clocks::ProfClock, Timer, TimerManager}, - util::write_val_to_user, }; mod builder; +mod exit; pub mod futex; mod name; mod posix_thread_ext; mod robust_list; pub use builder::PosixThreadBuilder; +pub use exit::do_exit; pub use name::{ThreadName, MAX_THREAD_NAME_LEN}; pub use posix_thread_ext::PosixThreadExt; pub use robust_list::RobustListHead; @@ -41,7 +39,6 @@ pub use robust_list::RobustListHead; pub struct PosixThread { // Immutable part process: Weak, - is_main_thread: bool, // Mutable part name: Mutex>, @@ -224,13 +221,13 @@ impl PosixThread { &self.robust_list } - /// Whether the thread is main thread. For Posix thread, If a thread's tid is equal to pid, it's main thread. - pub fn is_main_thread(&self) -> bool { - self.is_main_thread + fn is_main_thread(&self, tid: Tid) -> bool { + let process = self.process(); + let pid = process.pid(); + tid == pid } - /// whether the thread is the last running thread in process - pub fn is_last_thread(&self) -> bool { + fn is_last_thread(&self) -> bool { let process = self.process.upgrade().unwrap(); let threads = process.threads().lock(); threads @@ -240,62 +237,6 @@ impl PosixThread { == 0 } - /// Walks the robust futex list, marking futex dead and wake waiters. - /// It corresponds to Linux's exit_robust_list(), errors are silently ignored. - pub fn wake_robust_list(&self, tid: Tid) { - let mut robust_list = self.robust_list.lock(); - let list_head = match *robust_list { - None => { - return; - } - Some(robust_list_head) => robust_list_head, - }; - debug!("wake the rubust_list: {:?}", list_head); - for futex_addr in list_head.futexes() { - // debug!("futex addr = 0x{:x}", futex_addr); - wake_robust_futex(futex_addr, tid).unwrap(); - } - debug!("wake robust futex success"); - *robust_list = None; - } - - /// Posix thread does not contains tid info. So we require tid as a parameter. - pub fn exit(&self, tid: Tid, term_status: TermStatus) -> Result<()> { - let mut clear_ctid = self.clear_child_tid().lock(); - // If clear_ctid !=0 ,do a futex wake and write zero to the clear_ctid addr. - debug!("wake up ctid"); - if *clear_ctid != 0 { - debug!("futex wake"); - futex_wake(*clear_ctid, 1)?; - debug!("write ctid"); - // FIXME: the correct write length? - debug!("ctid = 0x{:x}", *clear_ctid); - write_val_to_user(*clear_ctid, &0u32).unwrap(); - debug!("clear ctid"); - *clear_ctid = 0; - } - debug!("wake up ctid succeeds"); - // exit the robust list: walk the robust list; mark futex words as dead and do futex wake - self.wake_robust_list(tid); - - if tid != self.process().pid() { - // If the thread is not main thread. We don't remove main thread. - // Main thread are removed when the whole process is reaped. - thread_table::remove_thread(tid); - } - - if self.is_main_thread() || self.is_last_thread() { - // exit current process. - debug!("self is main thread or last thread"); - debug!("main thread: {}", self.is_main_thread()); - debug!("last thread: {}", self.is_last_thread()); - do_exit_group(term_status); - } - debug!("perform futex wake"); - futex_wake(Arc::as_ptr(&self.process()) as Vaddr, 1)?; - Ok(()) - } - /// Gets the read-only credentials of the thread. pub fn credentials(&self) -> Credentials { self.credentials.dup().restrict() diff --git a/kernel/aster-nix/src/process/process/builder.rs b/kernel/aster-nix/src/process/process/builder.rs index e8ea5ec3b..87504dde4 100644 --- a/kernel/aster-nix/src/process/process/builder.rs +++ b/kernel/aster-nix/src/process/process/builder.rs @@ -181,12 +181,12 @@ impl<'a> ProcessBuilder<'a> { threads, executable_path.to_string(), process_vm, - file_table, fs, + file_table, umask, - sig_dispositions, resource_limits, nice, + sig_dispositions, ) }; diff --git a/kernel/aster-nix/src/process/process/mod.rs b/kernel/aster-nix/src/process/process/mod.rs index f6b6a5c94..4f5a2bd09 100644 --- a/kernel/aster-nix/src/process/process/mod.rs +++ b/kernel/aster-nix/src/process/process/mod.rs @@ -7,7 +7,11 @@ use super::{ process_vm::{Heap, InitStackReader, ProcessVm}, rlimit::ResourceLimits, signal::{ - constants::SIGCHLD, sig_disposition::SigDispositions, sig_mask::SigMask, signals::Signal, + constants::SIGCHLD, + sig_disposition::SigDispositions, + sig_mask::SigMask, + sig_num::{AtomicSigNum, SigNum}, + signals::Signal, Pauser, }, status::ProcessStatus, @@ -89,6 +93,8 @@ pub struct Process { // Signal /// Sig dispositions sig_dispositions: Arc>, + /// The signal that the process should receive when parent process exits. + parent_death_signal: AtomicSigNum, /// A profiling clock measures the user CPU time and kernel CPU time of the current process. prof_clock: Arc, @@ -105,12 +111,14 @@ impl Process { threads: Vec>, executable_path: String, process_vm: ProcessVm, - file_table: Arc>, + fs: Arc>, + file_table: Arc>, + umask: Arc>, - sig_dispositions: Arc>, resource_limits: ResourceLimits, nice: Nice, + sig_dispositions: Arc>, ) -> Arc { let children_pauser = { // SIGCHID does not interrupt pauser. Child process will @@ -135,6 +143,7 @@ impl Process { fs, umask, sig_dispositions, + parent_death_signal: AtomicSigNum::new_empty(), resource_limits: Mutex::new(resource_limits), nice: Atomic::new(nice), timer_manager: PosixTimerManager::new(&prof_clock, process_ref), @@ -587,6 +596,24 @@ impl Process { posix_thread.enqueue_signal(Box::new(signal)); } + /// Clears the parent death signal. + pub fn clear_parent_death_signal(&self) { + self.parent_death_signal.clear(); + } + + /// Sets the parent death signal as `signum`. + pub fn set_parent_death_signal(&self, sig_num: SigNum) { + self.parent_death_signal.set(sig_num); + } + + /// Returns the parent death signal. + /// + /// The parent death signal is the signal will be sent to child processes + /// when the process exits. + pub fn parent_death_signal(&self) -> Option { + self.parent_death_signal.as_sig_num() + } + // ******************* Status ******************** fn set_runnable(&self) { @@ -642,12 +669,12 @@ mod test { vec![], String::new(), ProcessVm::alloc(), - Arc::new(Mutex::new(FileTable::new())), Arc::new(RwMutex::new(FsResolver::new())), + Arc::new(Mutex::new(FileTable::new())), Arc::new(RwLock::new(FileCreationMask::default())), - Arc::new(Mutex::new(SigDispositions::default())), ResourceLimits::default(), Nice::default(), + Arc::new(Mutex::new(SigDispositions::default())), ) } diff --git a/kernel/aster-nix/src/process/signal/sig_num.rs b/kernel/aster-nix/src/process/signal/sig_num.rs index f93c764d7..631f5f8ea 100644 --- a/kernel/aster-nix/src/process/signal/sig_num.rs +++ b/kernel/aster-nix/src/process/signal/sig_num.rs @@ -1,5 +1,11 @@ // SPDX-License-Identifier: MPL-2.0 +#![allow(dead_code)] + +use core::sync::atomic::AtomicU8; + +use atomic::Ordering; + use super::constants::*; use crate::prelude::*; @@ -77,3 +83,46 @@ impl SigNum { } } } + +/// Atomic signal number. +/// +/// This struct represents a signal number and is different from [SigNum] +/// in that it allows for an empty signal number. +pub struct AtomicSigNum(AtomicU8); + +impl AtomicSigNum { + /// Creates a new empty atomic signal number + pub const fn new_empty() -> Self { + Self(AtomicU8::new(0)) + } + + /// Creates a new signal number with the specified value + pub const fn new(sig_num: SigNum) -> Self { + Self(AtomicU8::new(sig_num.as_u8())) + } + + /// Determines whether the signal number is empty + pub fn is_empty(&self) -> bool { + self.0.load(Ordering::Relaxed) == 0 + } + + /// Returns the corresponding [`SigNum`] + pub fn as_sig_num(&self) -> Option { + let sig_num = self.0.load(Ordering::Relaxed); + if sig_num == 0 { + return None; + } + + Some(SigNum::from_u8(sig_num)) + } + + /// Sets the new `sig_num` + pub fn set(&self, sig_num: SigNum) { + self.0.store(sig_num.as_u8(), Ordering::Relaxed) + } + + /// Clears the signal number + pub fn clear(&self) { + self.0.store(0, Ordering::Relaxed) + } +} diff --git a/kernel/aster-nix/src/syscall/execve.rs b/kernel/aster-nix/src/syscall/execve.rs index 892542e8a..23a991c9c 100644 --- a/kernel/aster-nix/src/syscall/execve.rs +++ b/kernel/aster-nix/src/syscall/execve.rs @@ -16,7 +16,7 @@ use crate::{ process::{ check_executable_file, credentials_mut, load_program_to_vm, posix_thread::{PosixThreadExt, ThreadName}, - Credentials, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER, MAX_ENV_LEN, + Credentials, Process, MAX_ARGV_NUMBER, MAX_ARG_LEN, MAX_ENVP_NUMBER, MAX_ENV_LEN, }, util::{read_cstring_from_user, read_val_from_user}, }; @@ -118,8 +118,8 @@ fn do_execve( debug!("load elf in execve succeeds"); let credentials = credentials_mut(); - set_uid_from_elf(&credentials, &elf_file)?; - set_gid_from_elf(&credentials, &elf_file)?; + set_uid_from_elf(¤t, &credentials, &elf_file)?; + set_gid_from_elf(¤t, &credentials, &elf_file)?; // set executable path current.set_executable_path(new_executable_path); @@ -177,10 +177,16 @@ fn read_cstring_vec( } /// Sets uid for credentials as the same of uid of elf file if elf file has `set_uid` bit. -fn set_uid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { +fn set_uid_from_elf( + current: &Arc, + credentials: &Credentials, + elf_file: &Arc, +) -> Result<()> { if elf_file.mode()?.has_set_uid() { let uid = elf_file.owner()?; credentials.set_euid(uid); + + current.clear_parent_death_signal(); } // No matter whether the elf_file has `set_uid` bit, suid should be reset. @@ -189,10 +195,16 @@ fn set_uid_from_elf(credentials: &Credentials, elf_file: &Arc) } /// Sets gid for credentials as the same of gid of elf file if elf file has `set_gid` bit. -fn set_gid_from_elf(credentials: &Credentials, elf_file: &Arc) -> Result<()> { +fn set_gid_from_elf( + current: &Arc, + credentials: &Credentials, + elf_file: &Arc, +) -> Result<()> { if elf_file.mode()?.has_set_gid() { let gid = elf_file.group()?; credentials.set_egid(gid); + + current.clear_parent_death_signal(); } // No matter whether the the elf file has `set_gid` bit, sgid should be reset. diff --git a/kernel/aster-nix/src/syscall/exit.rs b/kernel/aster-nix/src/syscall/exit.rs index 94b451467..ad28a786f 100644 --- a/kernel/aster-nix/src/syscall/exit.rs +++ b/kernel/aster-nix/src/syscall/exit.rs @@ -2,7 +2,7 @@ use crate::{ prelude::*, - process::{posix_thread::PosixThreadExt, TermStatus}, + process::{posix_thread::do_exit, TermStatus}, syscall::SyscallReturn, }; @@ -10,14 +10,8 @@ pub fn sys_exit(exit_code: i32) -> Result { debug!("exid code = {}", exit_code); let current_thread = current_thread!(); - current_thread.exit(); - - let tid = current_thread.tid(); - let pid = current!().pid(); - debug!("tid = {}, pid = {}", tid, pid); - - let posix_thread = current_thread.as_posix_thread().unwrap(); - posix_thread.exit(tid, TermStatus::Exited(exit_code as _))?; + let term_status = TermStatus::Exited(exit_code as _); + do_exit(current_thread, term_status)?; Ok(SyscallReturn::Return(0)) } diff --git a/kernel/aster-nix/src/syscall/prctl.rs b/kernel/aster-nix/src/syscall/prctl.rs index 09a23ec71..f76c7ef15 100644 --- a/kernel/aster-nix/src/syscall/prctl.rs +++ b/kernel/aster-nix/src/syscall/prctl.rs @@ -6,15 +6,35 @@ use super::SyscallReturn; use crate::{ prelude::*, - process::posix_thread::{PosixThreadExt, MAX_THREAD_NAME_LEN}, - util::{read_cstring_from_user, write_bytes_to_user}, + process::{ + posix_thread::{PosixThreadExt, MAX_THREAD_NAME_LEN}, + signal::sig_num::SigNum, + }, + util::{read_cstring_from_user, write_bytes_to_user, write_val_to_user}, }; + pub fn sys_prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> Result { let prctl_cmd = PrctlCmd::from_args(option, arg2, arg3, arg4, arg5)?; debug!("prctl cmd = {:x?}", prctl_cmd); let current_thread = current_thread!(); let posix_thread = current_thread.as_posix_thread().unwrap(); match prctl_cmd { + PrctlCmd::PR_SET_PDEATHSIG(signum) => { + let current = current!(); + current.set_parent_death_signal(signum); + } + PrctlCmd::PR_GET_PDEATHSIG(write_to_addr) => { + let write_val = { + let current = current!(); + + match current.parent_death_signal() { + None => 0i32, + Some(signum) => signum.as_u8() as i32, + } + }; + + write_val_to_user(write_to_addr, &write_val)?; + } PrctlCmd::PR_GET_NAME(write_to_addr) => { let thread_name = posix_thread.thread_name().lock(); if let Some(thread_name) = &*thread_name { @@ -35,6 +55,8 @@ pub fn sys_prctl(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> Res Ok(SyscallReturn::Return(0)) } +const PR_SET_PDEATHSIG: i32 = 1; +const PR_GET_PDEATHSIG: i32 = 2; const PR_SET_NAME: i32 = 15; const PR_GET_NAME: i32 = 16; const PR_SET_TIMERSLACK: i32 = 29; @@ -43,6 +65,8 @@ const PR_GET_TIMERSLACK: i32 = 30; #[allow(non_camel_case_types)] #[derive(Debug, Clone, Copy)] pub enum PrctlCmd { + PR_SET_PDEATHSIG(SigNum), + PR_GET_PDEATHSIG(Vaddr), PR_SET_NAME(Vaddr), PR_GET_NAME(Vaddr), PR_SET_TIMERSLACK(u64), @@ -52,6 +76,11 @@ pub enum PrctlCmd { impl PrctlCmd { fn from_args(option: i32, arg2: u64, arg3: u64, arg4: u64, arg5: u64) -> Result { match option { + PR_SET_PDEATHSIG => { + let signum = SigNum::try_from(arg2 as u8)?; + Ok(PrctlCmd::PR_SET_PDEATHSIG(signum)) + } + PR_GET_PDEATHSIG => Ok(PrctlCmd::PR_GET_PDEATHSIG(arg2 as _)), PR_SET_NAME => Ok(PrctlCmd::PR_SET_NAME(arg2 as _)), PR_GET_NAME => Ok(PrctlCmd::PR_GET_NAME(arg2 as _)), PR_GET_TIMERSLACK => todo!(), diff --git a/kernel/aster-nix/src/thread/mod.rs b/kernel/aster-nix/src/thread/mod.rs index 1525fc672..55f4f2bca 100644 --- a/kernel/aster-nix/src/thread/mod.rs +++ b/kernel/aster-nix/src/thread/mod.rs @@ -65,13 +65,13 @@ impl Thread { &self.task } - /// Run this thread at once. + /// Runs this thread at once. pub fn run(&self) { self.set_status(ThreadStatus::Running); self.task.run(); } - pub fn exit(&self) { + pub(super) fn exit(&self) { self.set_status(ThreadStatus::Exited); } @@ -98,14 +98,16 @@ impl Thread { self.tid } - // The return type must be borrowed box, otherwise the downcast_ref will fail + /// Returns the associated data. + /// + /// The return type must be borrowed box, otherwise the `downcast_ref` will fail. #[allow(clippy::borrowed_box)] pub fn data(&self) -> &Box { &self.data } } -/// allocate a new pid for new process +/// Allocates a new tid for the new thread pub fn allocate_tid() -> Tid { TID_ALLOCATOR.fetch_add(1, Ordering::SeqCst) } diff --git a/regression/apps/scripts/process.sh b/regression/apps/scripts/process.sh index 274d32a8d..7812569a9 100755 --- a/regression/apps/scripts/process.sh +++ b/regression/apps/scripts/process.sh @@ -23,6 +23,7 @@ itimer/timer_create mmap/map_shared_anon pthread/pthread_test pty/open_pty +signal_c/parent_death_signal signal_c/signal_test " diff --git a/regression/apps/signal_c/parent_death_signal.c b/regression/apps/signal_c/parent_death_signal.c new file mode 100644 index 000000000..ea5531067 --- /dev/null +++ b/regression/apps/signal_c/parent_death_signal.c @@ -0,0 +1,49 @@ +// SPDX-License-Identifier: MPL-2.0 + +#define _GNU_SOURCE +#include +#include +#include +#include +#include + +void signal_handler(int signum) +{ + if (signum == SIGTERM) { + printf("child process reveives SIGTERM\n"); + exit(EXIT_SUCCESS); + } +} + +int main() +{ + pid_t pid = fork(); + + if (pid == -1) { + perror("fork"); + return EXIT_FAILURE; + } + + if (pid > 0) { + printf("Parent PID: %d\n", getpid()); + // Ensure parent won't exit before child process runs + sleep(1); + } else { + printf("CHild PID: %d\n", getpid()); + + prctl(PR_SET_PDEATHSIG, SIGTERM); + + struct sigaction sa; + sa.sa_handler = signal_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = 0; + sigaction(SIGTERM, &sa, NULL); + + // Child waits for signal from parent death + while (1) { + sleep(1); + } + } + + return EXIT_SUCCESS; +} \ No newline at end of file