1use std::fs::File;
18use std::fs::OpenOptions;
19use std::path::PathBuf;
20
21use anyhow::Context;
22use base::enable_high_res_timers;
23use base::syslog;
24use base::syslog::LogArgs;
25use base::EnabledHighResTimer;
26use base::FromRawDescriptor;
27use base::IntoRawDescriptor;
28use base::SafeDescriptor;
29use base::SendTube;
30#[cfg(feature = "process-invariants")]
31pub use proc_init_product::init_broker_process_invariants;
32use proc_init_product::init_child_crash_reporting;
33use proc_init_product::product_child_setup;
34#[cfg(feature = "process-invariants")]
35pub use proc_init_product::EmulatorProcessInvariants;
36use proc_init_product::ProductAttributes;
37use proc_init_product::ProductProcessState;
38use serde::Deserialize;
39use serde::Serialize;
40
41#[derive(Serialize, Deserialize)]
43pub struct CommonChildStartupArgs {
44 log_args: LogArgs,
45 syslog_file: Option<SafeDescriptor>,
46 metrics_tube: Option<SendTube>,
47 product_attrs: ProductAttributes,
48}
49
50impl CommonChildStartupArgs {
51 #[allow(clippy::new_without_default)]
52 pub fn new(
53 log_args: &LogArgs,
54 syslog_path: Option<PathBuf>,
55 #[cfg(feature = "crash-report")] _crash_attrs: crash_report::CrashReportAttributes,
56 #[cfg(feature = "process-invariants")] _process_invariants: EmulatorProcessInvariants,
57 metrics_tube: Option<SendTube>,
58 ) -> anyhow::Result<Self> {
59 Ok(Self {
60 log_args: log_args.clone(),
61 product_attrs: ProductAttributes {},
62 metrics_tube,
63 syslog_file: log_file_from_path(syslog_path)?,
64 })
65 }
66}
67
68pub struct ChildLifecycleCleanup {
69 _timer_resolution: Box<dyn EnabledHighResTimer>,
70 _product_state: ProductProcessState,
71}
72
73pub fn common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup> {
78 let mut cfg = syslog::LogConfig {
80 log_args: args.log_args,
81 ..Default::default()
82 };
83 if let Some(log_file_descriptor) = args.syslog_file {
84 let log_file =
85 unsafe { File::from_raw_descriptor(log_file_descriptor.into_raw_descriptor()) };
88 cfg.pipe = Some(Box::new(log_file));
89 cfg.log_args.stderr = false;
90 } else {
91 cfg.log_args.stderr = true;
92 }
93 syslog::init_with(cfg)?;
94
95 init_child_crash_reporting(&args.product_attrs);
97
98 let product_proc_state = product_child_setup(&args.product_attrs)?;
100
101 if let Some(metrics_tube) = args.metrics_tube {
102 metrics::initialize(metrics_tube);
103 }
104
105 let timer_resolution = enable_high_res_timers().context("failed to enable high res timer")?;
106
107 Ok(ChildLifecycleCleanup {
108 _timer_resolution: timer_resolution,
109 _product_state: product_proc_state,
110 })
111}
112
113pub(crate) fn log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>> {
114 Ok(match path {
115 Some(path) => Some(SafeDescriptor::from(
116 OpenOptions::new()
117 .append(true)
118 .create(true)
119 .open(path.as_path())
120 .with_context(|| format!("failed to open log file {}", path.display()))?,
121 )),
122 None => None,
123 })
124}