mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-06 10:32:10 +00:00
crosvm: clean up waiting for children
Signed-off-by: Stephen Barber <smbarber@chromium.org> BUG=none TEST=run and kill block device process Change-Id: I1a4e98cb1985bfeb2303428f95f3bae27dccf803 Reviewed-on: https://chromium-review.googlesource.com/576463 Commit-Ready: Stephen Barber <smbarber@chromium.org> Tested-by: Stephen Barber <smbarber@chromium.org> Reviewed-by: Dylan Reid <dgreid@chromium.org>
This commit is contained in:
parent
56fbf09eac
commit
a00753ba37
1 changed files with 42 additions and 30 deletions
72
src/main.rs
72
src/main.rs
|
@ -143,6 +143,47 @@ fn create_base_minijail(root: &Path, seccomp_policy: &Path) -> Result<Minijail>
|
||||||
Ok(j)
|
Ok(j)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Wait for all children to exit. Return true if they have all exited, false
|
||||||
|
// otherwise.
|
||||||
|
fn wait_all_children() -> bool {
|
||||||
|
const CHILD_WAIT_MAX_ITER: isize = 10;
|
||||||
|
const CHILD_WAIT_MS: u64 = 10;
|
||||||
|
for _ in 0..CHILD_WAIT_MAX_ITER {
|
||||||
|
// waitpid() is safe when used in this manner; we will check
|
||||||
|
// without blocking if there are any child processes that
|
||||||
|
// are still running or need their exit statuses reaped.
|
||||||
|
loop {
|
||||||
|
let ret = unsafe {
|
||||||
|
libc::waitpid(-1, ptr::null_mut(), libc::WNOHANG)
|
||||||
|
};
|
||||||
|
// waitpid() returns -1 when there are no children left, and
|
||||||
|
// returns 0 when there are children alive but not yet exited.
|
||||||
|
if ret < 0 {
|
||||||
|
let err = sys_util::Error::last().errno();
|
||||||
|
// We expect ECHILD which indicates that there were
|
||||||
|
// no children left.
|
||||||
|
if err == libc::ECHILD {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
warn!("waitpid returned {} while waiting for children",
|
||||||
|
err);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if ret == 0 {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// There's no timeout option for waitpid, so our only recourse
|
||||||
|
// is to use WNOHANG and sleep while waiting for the children
|
||||||
|
// to exit.
|
||||||
|
sleep(Duration::from_millis(CHILD_WAIT_MS));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've made it to this point, not all of the children have exited.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
fn run_config(cfg: Config) -> Result<()> {
|
fn run_config(cfg: Config) -> Result<()> {
|
||||||
let socket = if let Some(ref socket_path) = cfg.socket_path {
|
let socket = if let Some(ref socket_path) = cfg.socket_path {
|
||||||
Some(ControlSocketRecv::new(socket_path)
|
Some(ControlSocketRecv::new(socket_path)
|
||||||
|
@ -596,36 +637,7 @@ fn main() {
|
||||||
// all devices should have been dropped in the main process and
|
// all devices should have been dropped in the main process and
|
||||||
// told to shutdown. Try over a period of 100ms, since it may
|
// told to shutdown. Try over a period of 100ms, since it may
|
||||||
// take some time for the processes to shut down.
|
// take some time for the processes to shut down.
|
||||||
let mut all_children_exited: bool = false;
|
if !wait_all_children() {
|
||||||
const CHILD_WAIT_MAX_ITER: isize = 10;
|
|
||||||
const CHILD_WAIT_MS: u64 = 10;
|
|
||||||
for _ in 0..CHILD_WAIT_MAX_ITER {
|
|
||||||
// waitpid() is safe when used in this manner; we will check
|
|
||||||
// without blocking if there are any child processes that
|
|
||||||
// are still running or need their exit statuses reaped.
|
|
||||||
let ret = unsafe {
|
|
||||||
libc::waitpid(-1, ptr::null_mut(), libc::WNOHANG)
|
|
||||||
};
|
|
||||||
// waitpid() returns -1 when there are no children left.
|
|
||||||
if ret < 0 {
|
|
||||||
let err = sys_util::Error::last().errno();
|
|
||||||
// We expect ECHILD which indicates that there were
|
|
||||||
// no children left.
|
|
||||||
if err == libc::ECHILD {
|
|
||||||
all_children_exited = true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
warn!("waitpid returned {} while waiting for children",
|
|
||||||
err);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
// There's no timeout option for waitpid, so our only recourse
|
|
||||||
// is to use WNOHANG and sleep while waiting for the children
|
|
||||||
// to exit.
|
|
||||||
sleep(Duration::from_millis(CHILD_WAIT_MS));
|
|
||||||
}
|
|
||||||
if !all_children_exited {
|
|
||||||
// We gave them a chance, and it's too late.
|
// We gave them a chance, and it's too late.
|
||||||
// A pid of 0 will kill any processes left in our process group,
|
// A pid of 0 will kill any processes left in our process group,
|
||||||
// which is safe for us to do (we spawned them).
|
// which is safe for us to do (we spawned them).
|
||||||
|
|
Loading…
Reference in a new issue