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 device_virtio_console::vhost_user::run_console_device;
17use devices::virtio::vhost_user_backend::run_fs_device;
18use devices::virtio::vhost_user_backend::run_vsock_device;
19#[cfg(feature = "virtio_wl")]
20use devices::virtio::vhost_user_backend::run_wl_device;
21
22use crate::crosvm::sys::cmdline::Commands;
23use crate::crosvm::sys::cmdline::DeviceSubcommand;
24use crate::crosvm::sys::linux::start_devices;
25use crate::CommandStatus;
26use crate::Config;
27
28pub(crate) fn start_device(command: DeviceSubcommand) -> anyhow::Result<()> {
29 match command {
30 DeviceSubcommand::Console(cfg) => run_console_device(cfg),
31 DeviceSubcommand::Fs(cfg) => run_fs_device(cfg),
32 DeviceSubcommand::Vsock(cfg) => run_vsock_device(cfg),
33 #[cfg(feature = "virtio_wl")]
34 DeviceSubcommand::Wl(cfg) => run_wl_device(cfg),
35 }
36}
37
38fn wait_all_children() -> bool {
41 const CHILD_WAIT_MAX_ITER: isize = 100;
42 const CHILD_WAIT_MS: u64 = 10;
43 for _ in 0..CHILD_WAIT_MAX_ITER {
44 loop {
45 match reap_child() {
46 Ok(0) => break,
47 Err(e) if e.errno() == libc::ECHILD => return true,
49 Err(e) => {
50 warn!("error while waiting for children: {}", e);
51 return false;
52 }
53 _ => {}
55 }
56 }
57 sleep(Duration::from_millis(CHILD_WAIT_MS));
60 }
61
62 false
64}
65
66pub(crate) fn cleanup() {
67 if !wait_all_children() {
71 warn!("not all child processes have exited; sending SIGKILL");
73 if let Err(e) = kill_process_group() {
74 warn!("unable to kill all child processes: {}", e);
76 }
77 }
78}
79
80pub(crate) fn run_command(command: Commands, _log_args: LogArgs) -> anyhow::Result<()> {
81 match command {
82 Commands::Devices(cmd) => start_devices(cmd).context("start_devices subcommand failed"),
83 }
84}
85
86pub(crate) fn init_log(log_config: LogConfig, _cfg: &Config) -> anyhow::Result<()> {
87 if let Err(e) = syslog::init_with(log_config) {
88 eprintln!("failed to initialize syslog: {e}");
89 return Err(anyhow!("failed to initialize syslog: {}", e));
90 }
91 Ok(())
92}
93
94pub(crate) fn error_to_exit_code(_res: &std::result::Result<CommandStatus, anyhow::Error>) -> i32 {
95 1
96}