1use std::thread::sleep;
6use std::time::Duration;
7
8use anyhow::anyhow;
9use anyhow::Context;
10use base::kill_process_group;
11use base::reap_child;
12use base::syslog;
13use base::syslog::LogArgs;
14use base::syslog::LogConfig;
15use base::warn;
16use devices::virtio::vhost_user_backend::run_console_device;
17use devices::virtio::vhost_user_backend::run_fs_device;
18use devices::virtio::vhost_user_backend::run_vsock_device;
19use devices::virtio::vhost_user_backend::run_wl_device;
20
21use crate::crosvm::sys::cmdline::Commands;
22use crate::crosvm::sys::cmdline::DeviceSubcommand;
23use crate::crosvm::sys::linux::start_devices;
24use crate::CommandStatus;
25use crate::Config;
26
27pub(crate) fn start_device(command: DeviceSubcommand) -> anyhow::Result<()> {
28 match command {
29 DeviceSubcommand::Console(cfg) => run_console_device(cfg),
30 DeviceSubcommand::Fs(cfg) => run_fs_device(cfg),
31 DeviceSubcommand::Vsock(cfg) => run_vsock_device(cfg),
32 DeviceSubcommand::Wl(cfg) => run_wl_device(cfg),
33 }
34}
35
36fn wait_all_children() -> bool {
39 const CHILD_WAIT_MAX_ITER: isize = 100;
40 const CHILD_WAIT_MS: u64 = 10;
41 for _ in 0..CHILD_WAIT_MAX_ITER {
42 loop {
43 match reap_child() {
44 Ok(0) => break,
45 Err(e) if e.errno() == libc::ECHILD => return true,
47 Err(e) => {
48 warn!("error while waiting for children: {}", e);
49 return false;
50 }
51 _ => {}
53 }
54 }
55 sleep(Duration::from_millis(CHILD_WAIT_MS));
58 }
59
60 false
62}
63
64pub(crate) fn cleanup() {
65 if !wait_all_children() {
69 warn!("not all child processes have exited; sending SIGKILL");
71 if let Err(e) = kill_process_group() {
72 warn!("unable to kill all child processes: {}", e);
74 }
75 }
76}
77
78pub(crate) fn run_command(command: Commands, _log_args: LogArgs) -> anyhow::Result<()> {
79 match command {
80 Commands::Devices(cmd) => start_devices(cmd).context("start_devices subcommand failed"),
81 }
82}
83
84pub(crate) fn init_log(log_config: LogConfig, _cfg: &Config) -> anyhow::Result<()> {
85 if let Err(e) = syslog::init_with(log_config) {
86 eprintln!("failed to initialize syslog: {e}");
87 return Err(anyhow!("failed to initialize syslog: {}", e));
88 }
89 Ok(())
90}
91
92pub(crate) fn error_to_exit_code(_res: &std::result::Result<CommandStatus, anyhow::Error>) -> i32 {
93 1
94}