diff --git a/src/libos/src/process/do_exit.rs b/src/libos/src/process/do_exit.rs index 299d73ae..8492bff2 100644 --- a/src/libos/src/process/do_exit.rs +++ b/src/libos/src/process/do_exit.rs @@ -1,10 +1,11 @@ +use crate::signal::constants::*; use std::intrinsics::atomic_store; use super::do_futex::futex_wake; -use super::process::ProcessFilter; +use super::process::{Process, ProcessFilter}; use super::{table, TermStatus, ThreadRef, ThreadStatus}; use crate::prelude::*; -use crate::signal::SigNum; +use crate::signal::{KernelSignal, SigNum}; pub fn do_exit_group(status: i32) { let term_status = TermStatus::Exited(status as u8); @@ -84,6 +85,9 @@ fn exit_process(thread: &ThreadRef, term_status: TermStatus) { let mut parent_inner = parent.inner(); process.inner().exit(term_status); + //Send SIGCHLD to parent + send_sigchld_to(&parent); + // Wake up the parent if it is waiting on this child let waiting_children = parent_inner.waiting_children_mut().unwrap(); waiting_children.del_and_wake_one_waiter(|waiter_data| -> Option { @@ -103,3 +107,9 @@ fn exit_process(thread: &ThreadRef, term_status: TermStatus) { Some(process.pid()) }); } + +fn send_sigchld_to(parent: &Arc) { + let signal = Box::new(KernelSignal::new(SigNum::from(SIGCHLD))); + let mut sig_queues = parent.sig_queues().lock().unwrap(); + sig_queues.enqueue(signal); +} diff --git a/test/signal/main.c b/test/signal/main.c index e5f74fc5..8ef4fc1c 100644 --- a/test/signal/main.c +++ b/test/signal/main.c @@ -325,6 +325,34 @@ int test_sigaltstack() { return 0; } +// ============================================================================ +// Test SIGCHLD signal +// ============================================================================ +int sigchld = 0; + +void proc_exit() { + sigchld = 1; +} + +int test_sigchld() { + signal(SIGCHLD, proc_exit); + + int ret, child_pid; + printf("Run a parent process has pid = %d and ppid = %d\n", getpid(), getppid()); + + ret = posix_spawn(&child_pid, "/bin/getpid", NULL, NULL, NULL, NULL); + if (ret < 0){ + printf("ERROR: failed to spawn a child process\n"); + return -1; + } + printf("Spawn a new proces successfully (pid = %d)\n", child_pid); + + wait(NULL); + if (sigchld == 0) THROW_ERROR("Did not receive SIGCHLD"); + + return 0; +} + // ============================================================================ // Test suite main // ============================================================================ @@ -336,6 +364,7 @@ static test_case_t test_cases[] = { TEST_CASE(test_kill), TEST_CASE(test_catch_fault), TEST_CASE(test_sigaltstack), + TEST_CASE(test_sigchld), }; int main(int argc, const char* argv[]) {