1 // Copyright 2022 The ChromiumOS Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //! Contains shared code between the broker & its children, specifically any IPC messages or common
6 //! bootstrapping code.
7
8 use std::fs::File;
9 use std::fs::OpenOptions;
10 use std::path::PathBuf;
11
12 use anyhow::Context;
13 use base::enable_high_res_timers;
14 use base::syslog;
15 use base::syslog::LogArgs;
16 use base::EnabledHighResTimer;
17 use base::FromRawDescriptor;
18 use base::IntoRawDescriptor;
19 use base::SafeDescriptor;
20 use base::SendTube;
21 #[cfg(feature = "process-invariants")]
22 pub use broker_ipc_product::init_broker_process_invariants;
23 use broker_ipc_product::init_child_crash_reporting;
24 use broker_ipc_product::product_child_setup;
25 #[cfg(feature = "process-invariants")]
26 pub use broker_ipc_product::EmulatorProcessInvariants;
27 use broker_ipc_product::ProductAttributes;
28 use serde::Deserialize;
29 use serde::Serialize;
30
31 /// Arguments that are common to all devices & helper processes.
32 #[derive(Serialize, Deserialize)]
33 pub struct CommonChildStartupArgs {
34 log_args: LogArgs,
35 syslog_file: Option<SafeDescriptor>,
36 metrics_tube: Option<SendTube>,
37 product_attrs: ProductAttributes,
38 }
39
40 impl CommonChildStartupArgs {
41 #[allow(clippy::new_without_default)]
new( log_args: &LogArgs, syslog_path: Option<PathBuf>, #[cfg(feature = "crash-report")] _crash_attrs: crash_report::CrashReportAttributes, #[cfg(feature = "process-invariants")] _process_invariants: EmulatorProcessInvariants, metrics_tube: Option<SendTube>, ) -> anyhow::Result<Self>42 pub fn new(
43 log_args: &LogArgs,
44 syslog_path: Option<PathBuf>,
45 #[cfg(feature = "crash-report")] _crash_attrs: crash_report::CrashReportAttributes,
46 #[cfg(feature = "process-invariants")] _process_invariants: EmulatorProcessInvariants,
47 metrics_tube: Option<SendTube>,
48 ) -> anyhow::Result<Self> {
49 Ok(Self {
50 log_args: log_args.clone(),
51 product_attrs: ProductAttributes {},
52 metrics_tube,
53 syslog_file: log_file_from_path(syslog_path)?,
54 })
55 }
56 }
57
58 pub struct ChildLifecycleCleanup {
59 _timer_resolution: Box<dyn EnabledHighResTimer>,
60 }
61
62 /// Initializes crash reporting, metrics, logging, and product specific features
63 /// for a process.
64 ///
65 /// Returns a value that should be dropped when the process exits.
common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup>66 pub fn common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup> {
67 // Logging must initialize first in case there are other startup errors.
68 let mut cfg = syslog::LogConfig {
69 log_args: args.log_args,
70 ..Default::default()
71 };
72 if let Some(log_file_descriptor) = args.syslog_file {
73 let log_file =
74 // SAFETY:
75 // Safe because we are taking ownership of a SafeDescriptor.
76 unsafe { File::from_raw_descriptor(log_file_descriptor.into_raw_descriptor()) };
77 cfg.pipe = Some(Box::new(log_file));
78 cfg.log_args.stderr = false;
79 } else {
80 cfg.log_args.stderr = true;
81 }
82 syslog::init_with(cfg)?;
83
84 // Crash reporting should start as early as possible, in case other startup tasks fail.
85 init_child_crash_reporting(&args.product_attrs);
86
87 // Initialize anything product specific.
88 product_child_setup(&args.product_attrs)?;
89
90 if let Some(metrics_tube) = args.metrics_tube {
91 metrics::initialize(metrics_tube);
92 }
93
94 let timer_resolution = enable_high_res_timers().context("failed to enable high res timer")?;
95
96 Ok(ChildLifecycleCleanup {
97 _timer_resolution: timer_resolution,
98 })
99 }
100
log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>>101 pub(crate) fn log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>> {
102 Ok(match path {
103 Some(path) => Some(SafeDescriptor::from(
104 OpenOptions::new()
105 .append(true)
106 .create(true)
107 .open(path.as_path())
108 .context(format!("failed to open log file {}", path.display()))?,
109 )),
110 None => None,
111 })
112 }
113