• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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