mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-24 01:43:22 +00:00
Support timeout for WaitQueue
This commit is contained in:
committed by
Tate, Hongliang Tian
parent
d28f0db419
commit
bd6a4d34ff
@ -187,8 +187,7 @@ impl From<jinux_frame::Error> for Error {
|
||||
jinux_frame::Error::IoError => Error::new(Errno::EIO),
|
||||
jinux_frame::Error::NotEnoughResources => Error::new(Errno::EBUSY),
|
||||
jinux_frame::Error::PageFault => Error::new(Errno::EFAULT),
|
||||
jinux_frame::Error::InvalidVmpermBits => Error::new(Errno::EINVAL),
|
||||
jinux_frame::Error::NoChild => Error::new(Errno::ECHILD),
|
||||
jinux_frame::Error::TimeOut => Error::new(Errno::ETIME),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -203,14 +203,19 @@ impl EventCounter {
|
||||
}
|
||||
|
||||
pub fn read(&self) -> usize {
|
||||
self.wait_queue.wait_until(|| {
|
||||
let val = self.counter.swap(0, Ordering::Relaxed);
|
||||
if val > 0 {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
self.wait_queue
|
||||
.wait_until(
|
||||
|| {
|
||||
let val = self.counter.swap(0, Ordering::Relaxed);
|
||||
if val > 0 {
|
||||
Some(val)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
None,
|
||||
)
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn write(&self) {
|
||||
|
@ -26,46 +26,51 @@ pub fn wait_child_exit(
|
||||
wait_options: WaitOptions,
|
||||
) -> Result<(Pid, ExitCode)> {
|
||||
let current = current!();
|
||||
let (pid, exit_code) = current.waiting_children().wait_until(|| {
|
||||
let children_lock = current.children().lock();
|
||||
let unwaited_children = children_lock
|
||||
.iter()
|
||||
.filter(|(pid, child)| match child_filter {
|
||||
ProcessFilter::Any => true,
|
||||
ProcessFilter::WithPid(pid) => child.pid() == pid,
|
||||
ProcessFilter::WithPgid(pgid) => child.pgid() == pgid,
|
||||
})
|
||||
.map(|(_, child)| child.clone())
|
||||
.collect::<Vec<_>>();
|
||||
// we need to drop the lock here, since reap child process need to acquire this lock again
|
||||
drop(children_lock);
|
||||
let (pid, exit_code) = current.waiting_children().wait_until(
|
||||
|| {
|
||||
let unwaited_children = current
|
||||
.children()
|
||||
.lock()
|
||||
.values()
|
||||
.filter(|child| match child_filter {
|
||||
ProcessFilter::Any => true,
|
||||
ProcessFilter::WithPid(pid) => child.pid() == pid,
|
||||
ProcessFilter::WithPgid(pgid) => child.pgid() == pgid,
|
||||
})
|
||||
.cloned()
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
if unwaited_children.is_empty() {
|
||||
return Some(Err(jinux_frame::Error::NoChild));
|
||||
}
|
||||
|
||||
// return immediately if we find a zombie child
|
||||
let zombie_child = unwaited_children.iter().find(|child| child.is_zombie());
|
||||
|
||||
if let Some(zombie_child) = zombie_child {
|
||||
let zombie_pid = zombie_child.pid();
|
||||
let exit_code = zombie_child.exit_code().unwrap();
|
||||
if wait_options.contains(WaitOptions::WNOWAIT) {
|
||||
// does not reap child, directly return
|
||||
return Some(Ok((zombie_pid, exit_code)));
|
||||
} else {
|
||||
let exit_code = reap_zombie_child(¤t, zombie_pid);
|
||||
return Some(Ok((zombie_pid, exit_code)));
|
||||
if unwaited_children.is_empty() {
|
||||
return Some(Err(Error::with_message(
|
||||
Errno::ECHILD,
|
||||
"the process has no child to wait",
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
if wait_options.contains(WaitOptions::WNOHANG) {
|
||||
return Some(Ok((0, 0)));
|
||||
}
|
||||
// return immediately if we find a zombie child
|
||||
let zombie_child = unwaited_children.iter().find(|child| child.is_zombie());
|
||||
|
||||
// wait
|
||||
None
|
||||
})?;
|
||||
if let Some(zombie_child) = zombie_child {
|
||||
let zombie_pid = zombie_child.pid();
|
||||
let exit_code = zombie_child.exit_code().unwrap();
|
||||
if wait_options.contains(WaitOptions::WNOWAIT) {
|
||||
// does not reap child, directly return
|
||||
return Some(Ok((zombie_pid, exit_code)));
|
||||
} else {
|
||||
let exit_code = reap_zombie_child(¤t, zombie_pid);
|
||||
return Some(Ok((zombie_pid, exit_code)));
|
||||
}
|
||||
}
|
||||
|
||||
if wait_options.contains(WaitOptions::WNOHANG) {
|
||||
return Some(Ok((0, 0)));
|
||||
}
|
||||
|
||||
// wait
|
||||
None
|
||||
},
|
||||
None,
|
||||
)??;
|
||||
|
||||
Ok((pid, exit_code as _))
|
||||
}
|
||||
|
Reference in New Issue
Block a user