blob: f70aefe16263bacb82fe8c3c905e6356f7cbedc8 [file] [log] [blame]
// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// TODO Follow 2018 idioms
#![allow(elided_lifetimes_in_paths)]
use {
anyhow::{Context as _, Error},
component_manager_lib::{
builtin_environment::BuiltinEnvironment,
elf_runner::{ElfRunner, ProcessLauncherConnector},
klog,
model::{
binding::Binder,
model::{ComponentManagerConfig, Model},
moniker::AbsoluteMoniker,
realm::BindReason,
},
startup,
},
fuchsia_async as fasync,
fuchsia_runtime::{job_default, process_self},
fuchsia_trace_provider as trace_provider,
fuchsia_zircon::JobCriticalOptions,
log::*,
std::{panic, process, sync::Arc, thread, time::Duration},
};
const NUM_THREADS: usize = 2;
fn main() -> Result<(), Error> {
// Make sure we exit if there is a panic. Add this hook before we init the
// KernelLogger because it installs its own hook and then calls any
// existing hook.
panic::set_hook(Box::new(|_| {
println!("Panic in component_manager, aborting process.");
// TODO remove after 43671 is resolved
std::thread::spawn(move || {
let mut nap_duration = Duration::from_secs(1);
// Do a short sleep, hopefully under "normal" circumstances the
// process will exit before this is printed
thread::sleep(nap_duration);
println!("component manager abort was started");
// set a fairly long duration so we don't spam logs
nap_duration = Duration::from_secs(30);
loop {
thread::sleep(nap_duration);
println!("component manager alive long after abort");
}
});
process::abort();
}));
// Set ourselves as critical to our job. If we do not fail gracefully, our
// job will be killed.
if let Err(err) =
job_default().set_critical(JobCriticalOptions::RETCODE_NONZERO, &process_self())
{
panic!("Component manager failed to set itself as critical: {:?}", err);
}
klog::KernelLogger::init();
let args = match startup::Arguments::from_args() {
Ok(args) => args,
Err(err) => {
error!("{}\n{}", err, startup::Arguments::usage());
return Err(err);
}
};
info!("Component manager is starting up...");
// Enable tracing in Component Manager
trace_provider::trace_provider_create_with_fdio();
let mut executor = fasync::Executor::new().context("error creating executor")?;
let fut = async {
match run_root(args).await {
Ok((_model, builtin_environment)) => {
builtin_environment.wait_for_root_realm_stop().await;
}
Err(err) => {
panic!("Component manager setup failed: {:?}", err);
}
}
};
executor.run(fut, NUM_THREADS);
Ok(())
}
async fn run_root(args: startup::Arguments) -> Result<(Arc<Model>, BuiltinEnvironment), Error> {
let model = startup::model_setup(&args).await.context("failed to set up model")?;
// Create an ELF runner for the root component.
let launcher_connector = ProcessLauncherConnector::new(&args);
let runner = Arc::new(ElfRunner::new(launcher_connector));
let builtin_environment = BuiltinEnvironment::new(
&args,
&model,
ComponentManagerConfig::default(),
&vec![("elf".into(), runner as _)].into_iter().collect(),
)
.await?;
builtin_environment.bind_service_fs_to_out().await?;
let root_moniker = AbsoluteMoniker::root();
model
.bind(&root_moniker, &BindReason::Root)
.await
.map_err(|e| Error::from(e))
.context(format!("failed to bind to root component {}", args.root_component_url))?;
Ok((model, builtin_environment))
}