Send SIGCHLD to parent process

This commit is contained in:
Zongmin 2020-05-13 18:26:41 +08:00
parent 459ca45ab9
commit 17b4912055
2 changed files with 41 additions and 2 deletions

@ -1,10 +1,11 @@
use crate::signal::constants::*;
use std::intrinsics::atomic_store; use std::intrinsics::atomic_store;
use super::do_futex::futex_wake; use super::do_futex::futex_wake;
use super::process::ProcessFilter; use super::process::{Process, ProcessFilter};
use super::{table, TermStatus, ThreadRef, ThreadStatus}; use super::{table, TermStatus, ThreadRef, ThreadStatus};
use crate::prelude::*; use crate::prelude::*;
use crate::signal::SigNum; use crate::signal::{KernelSignal, SigNum};
pub fn do_exit_group(status: i32) { pub fn do_exit_group(status: i32) {
let term_status = TermStatus::Exited(status as u8); 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(); let mut parent_inner = parent.inner();
process.inner().exit(term_status); process.inner().exit(term_status);
//Send SIGCHLD to parent
send_sigchld_to(&parent);
// Wake up the parent if it is waiting on this child // Wake up the parent if it is waiting on this child
let waiting_children = parent_inner.waiting_children_mut().unwrap(); let waiting_children = parent_inner.waiting_children_mut().unwrap();
waiting_children.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> { waiting_children.del_and_wake_one_waiter(|waiter_data| -> Option<pid_t> {
@ -103,3 +107,9 @@ fn exit_process(thread: &ThreadRef, term_status: TermStatus) {
Some(process.pid()) Some(process.pid())
}); });
} }
fn send_sigchld_to(parent: &Arc<Process>) {
let signal = Box::new(KernelSignal::new(SigNum::from(SIGCHLD)));
let mut sig_queues = parent.sig_queues().lock().unwrap();
sig_queues.enqueue(signal);
}

@ -325,6 +325,34 @@ int test_sigaltstack() {
return 0; 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 // Test suite main
// ============================================================================ // ============================================================================
@ -336,6 +364,7 @@ static test_case_t test_cases[] = {
TEST_CASE(test_kill), TEST_CASE(test_kill),
TEST_CASE(test_catch_fault), TEST_CASE(test_catch_fault),
TEST_CASE(test_sigaltstack), TEST_CASE(test_sigaltstack),
TEST_CASE(test_sigchld),
}; };
int main(int argc, const char* argv[]) { int main(int argc, const char* argv[]) {