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
11 use anyhow::Context;
12 use base::enable_high_res_timers;
13 use base::syslog;
14 use base::EnabledHighResTimer;
15 use base::FromRawDescriptor;
16 use base::IntoRawDescriptor;
17 use base::SafeDescriptor;
18 use base::Tube;
19 use serde::Deserialize;
20 use serde::Serialize;
21
22 mod generic;
23 use std::path::PathBuf;
24
25 use generic as product;
26 use product::init_child_crash_reporting;
27 use product::product_child_setup;
28 use product::ProductAttributes;
29
30 /// Arguments that are common to all devices & helper processes.
31 #[derive(Serialize, Deserialize)]
32 pub struct CommonChildStartupArgs {
33 syslog_file: Option<SafeDescriptor>,
34 metrics_tube: Option<Tube>,
35 product_attrs: ProductAttributes,
36 }
37
38 pub struct ChildLifecycleCleanup {
39 _timer_resolution: Box<dyn EnabledHighResTimer>,
40 }
41
42 /// Initializes crash reporting, metrics, logging, and product specific features
43 /// for a process.
44 ///
45 /// Returns a value that should be dropped when the process exits.
common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup>46 pub fn common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup> {
47 // Logging must initialize first in case there are other startup errors.
48 let mut cfg = syslog::LogConfig::default();
49 if let Some(log_file_descriptor) = args.syslog_file {
50 // Safe because we are taking ownership of a SafeDescriptor.
51 let log_file =
52 unsafe { File::from_raw_descriptor(log_file_descriptor.into_raw_descriptor()) };
53 cfg.pipe = Some(Box::new(log_file));
54 cfg.stderr = false;
55 } else {
56 cfg.stderr = true;
57 }
58 syslog::init_with(cfg)?;
59
60 // Crash reporting should start as early as possible, in case other startup tasks fail.
61 init_child_crash_reporting(&args.product_attrs);
62
63 // Initialize anything product specific.
64 product_child_setup(&args.product_attrs)?;
65
66 if let Some(metrics_tube) = args.metrics_tube {
67 metrics::initialize(metrics_tube);
68 }
69
70 let timer_resolution = enable_high_res_timers().context("failed to enable high res timer")?;
71
72 Ok(ChildLifecycleCleanup {
73 _timer_resolution: timer_resolution,
74 })
75 }
76
log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>>77 pub(crate) fn log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>> {
78 Ok(match path {
79 Some(path) => Some(SafeDescriptor::from(
80 OpenOptions::new()
81 .append(true)
82 .create(true)
83 .open(path.as_path())
84 .context(format!("failed to open log file {}", path.display()))?,
85 )),
86 None => None,
87 })
88 }
89