mirror of
https://github.com/hexagonal-sun/moss-kernel.git
synced 2026-01-30 17:11:47 -05:00
syscalls: wait4: make interruptable()
Make the `sys_wait4` system call interruptable via signal delivery. Also include some a test in `usertest` to ensure proper functionality.
This commit is contained in:
@@ -1,3 +1,7 @@
|
||||
use super::{
|
||||
Pgid, Tgid, ThreadGroup,
|
||||
signal::{InterruptResult, Interruptable, SigId},
|
||||
};
|
||||
use crate::clock::timespec::TimeSpec;
|
||||
use crate::memory::uaccess::copy_to_user;
|
||||
use crate::sched::current::current_task_shared;
|
||||
@@ -10,10 +14,6 @@ use libkernel::{
|
||||
memory::address::TUA,
|
||||
};
|
||||
|
||||
use super::Tgid;
|
||||
use super::signal::SigId;
|
||||
use super::{Pgid, ThreadGroup};
|
||||
|
||||
pub type PidT = i32;
|
||||
|
||||
#[repr(C)]
|
||||
@@ -201,11 +201,17 @@ pub async fn sys_wait4(
|
||||
None => return Ok(0),
|
||||
}
|
||||
} else {
|
||||
task.process
|
||||
match task
|
||||
.process
|
||||
.child_notifiers
|
||||
.inner
|
||||
.wait_until(|state| do_wait(state, pid, flags))
|
||||
.interruptable()
|
||||
.await
|
||||
{
|
||||
InterruptResult::Interrupted => return Err(KernelError::Interrupted),
|
||||
InterruptResult::Uninterrupted(r) => r,
|
||||
}
|
||||
};
|
||||
|
||||
if !stat_addr.is_null() {
|
||||
|
||||
@@ -7,7 +7,9 @@ use std::{
|
||||
};
|
||||
|
||||
use futex_bitset::test_futex_bitset;
|
||||
use signals::{test_interruptible_nanosleep, test_interruptible_read_pipe};
|
||||
use signals::{
|
||||
test_interruptible_nanosleep, test_interruptible_read_pipe, test_interruptible_waitpid,
|
||||
};
|
||||
|
||||
mod futex_bitset;
|
||||
mod signals;
|
||||
@@ -824,6 +826,7 @@ fn main() {
|
||||
run_test(test_thread_with_name);
|
||||
run_test(test_interruptible_nanosleep);
|
||||
run_test(test_interruptible_read_pipe);
|
||||
run_test(test_interruptible_waitpid);
|
||||
let end = std::time::Instant::now();
|
||||
println!("All tests passed in {} ms", (end - start).as_millis());
|
||||
}
|
||||
|
||||
@@ -112,3 +112,49 @@ pub fn test_interruptible_read_pipe() {
|
||||
}
|
||||
println!(" OK");
|
||||
}
|
||||
|
||||
pub fn test_interruptible_waitpid() {
|
||||
print!("Testing interruptible waitpid ...");
|
||||
|
||||
register_handler(libc::SIGALRM, false);
|
||||
|
||||
unsafe {
|
||||
let ppid = libc::getpid();
|
||||
let cpid = libc::fork();
|
||||
|
||||
if cpid == 0 {
|
||||
// in child.
|
||||
let req = libc::timespec {
|
||||
tv_sec: 1,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
|
||||
libc::nanosleep(&req, ptr::null_mut());
|
||||
libc::kill(ppid, libc::SIGALRM);
|
||||
let req = libc::timespec {
|
||||
tv_sec: 10,
|
||||
tv_nsec: 0,
|
||||
};
|
||||
libc::nanosleep(&req, ptr::null_mut());
|
||||
libc::exit(0);
|
||||
};
|
||||
|
||||
// parent.
|
||||
let mut status = 0;
|
||||
let ret = libc::waitpid(cpid, &mut status, 0); // Blocking wait
|
||||
let err = std::io::Error::last_os_error();
|
||||
|
||||
if ret == -1 && err.raw_os_error() == Some(libc::EINTR) {
|
||||
// Now we must actually kill/wait the child to clean up zombies
|
||||
libc::kill(cpid, libc::SIGKILL);
|
||||
libc::waitpid(cpid, &mut status, 0);
|
||||
} else {
|
||||
panic!(
|
||||
"waitpid returned {:?} (errno: {:?}) instead of -1/EINTR",
|
||||
ret,
|
||||
err.raw_os_error()
|
||||
);
|
||||
}
|
||||
}
|
||||
println!(" OK");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user