broker_ipc: add crate

Adds the broker_ipc crate, which is used for communication & setup tasks
shared between the broker (Windows orchestrator for crosvm & vhost-user
devices) and all other crosvm processes.

BUG=b:232318124
TEST=builds

Change-Id: I17d529305dd348a50574e6c3c082808e97ffff45
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3648474
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Commit-Queue: Noah Gold <nkgold@google.com>
This commit is contained in:
Noah Gold 2022-05-13 15:14:15 -07:00 committed by Chromeos LUCI
parent b803f10fa2
commit eac74eb836
4 changed files with 124 additions and 0 deletions

View file

@ -47,6 +47,7 @@ members = [
"argh_helpers",
"base",
"bit_field",
"broker_ipc",
"cros_async",
"crosvm-fuzz",
"crosvm_control",
@ -154,6 +155,7 @@ assertions = { path = "common/assertions" }
audio_streams = "*"
base = "*"
bit_field = { path = "bit_field" }
broker_ipc = { path = "broker_ipc" }
cfg-if = "1.0.0"
crosvm_plugin = { path = "crosvm_plugin", optional = true }
data_model = "*"

12
broker_ipc/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "broker_ipc"
authors = ["The Chromium OS Authors"]
version = "0.1.0"
edition = "2021"
[dependencies]
anyhow = "1.0.32"
base = { path = "../base" }
serde = { version = "1", features = [ "derive" ] }
metrics = { path = "../metrics" }

32
broker_ipc/src/generic.rs Normal file
View file

@ -0,0 +1,32 @@
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Generic implementation of product specific functions that are called on child process
//! initialization.
use crate::{log_file_from_path, CommonChildStartupArgs};
use base::Tube;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;
#[derive(Serialize, Deserialize)]
pub struct ProductAttributes {}
impl CommonChildStartupArgs {
pub fn new(syslog_path: Option<PathBuf>, metrics_tube: Option<Tube>) -> anyhow::Result<Self> {
Ok(Self {
product_attrs: ProductAttributes {},
metrics_tube,
syslog_file: log_file_from_path(syslog_path)?,
})
}
}
pub(crate) fn init_child_crash_reporting(_attrs: &ProductAttributes) {
// Do nothing. Crash reporting is implemented by a specific product.
}
pub(crate) fn product_child_setup(_attrs: &ProductAttributes) -> anyhow::Result<()> {
Ok(())
}

78
broker_ipc/src/lib.rs Normal file
View file

@ -0,0 +1,78 @@
// Copyright 2022 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//! Contains shared code between the broker & its children, specifically any IPC messages or common
//! bootstrapping code.
use anyhow::Context;
use base::{enable_high_res_timers, syslog, FromRawDescriptor, IntoRawDescriptor, SafeDescriptor};
use base::{EnabledHighResTimer, Tube};
use serde::{Deserialize, Serialize};
use std::fs::{File, OpenOptions};
mod generic;
use generic as product;
use product::{init_child_crash_reporting, product_child_setup, ProductAttributes};
use std::path::PathBuf;
/// Arguments that are common to all devices & helper processes.
#[derive(Serialize, Deserialize)]
pub struct CommonChildStartupArgs {
syslog_file: Option<SafeDescriptor>,
metrics_tube: Option<Tube>,
product_attrs: ProductAttributes,
}
pub struct ChildLifecycleCleanup {
_timer_resolution: Box<dyn EnabledHighResTimer>,
}
/// Initializes crash reporting, metrics, logging, and product specific features
/// for a process.
///
/// Returns a value that should be dropped when the process exits.
pub fn common_child_setup(args: CommonChildStartupArgs) -> anyhow::Result<ChildLifecycleCleanup> {
// Crash reporting should start as early as possible, in case other startup tasks fail.
init_child_crash_reporting(&args.product_attrs);
let mut cfg = syslog::LogConfig::default();
if let Some(log_file_descriptor) = args.syslog_file {
// Safe because we are taking ownership of a SafeDescriptor.
let log_file =
unsafe { File::from_raw_descriptor(log_file_descriptor.into_raw_descriptor()) };
cfg.pipe = Some(Box::new(log_file));
cfg.stderr = false;
} else {
cfg.stderr = true;
}
syslog::init_with(cfg)?;
// Initialize anything product specific.
product_child_setup(&args.product_attrs)?;
if let Some(metrics_tube) = args.metrics_tube {
metrics::initialize(metrics_tube);
}
let timer_resolution = enable_high_res_timers().context("failed to enable high res timer")?;
Ok(ChildLifecycleCleanup {
_timer_resolution: timer_resolution,
})
}
pub(crate) fn log_file_from_path(path: Option<PathBuf>) -> anyhow::Result<Option<SafeDescriptor>> {
Ok(match path {
Some(path) => Some(SafeDescriptor::from(
OpenOptions::new()
.append(true)
.create(true)
.open(path.as_path())
.context(format!("failed to open log file {}", path.display()))?,
)),
None => None,
})
}