Skip to content

Commit

Permalink
Merge pull request #51 from openebs/feature/io-engine-crash-fixes
Browse files Browse the repository at this point in the history
feat(composer): adding support for running with Address Sanitizer
  • Loading branch information
dsavitskiy authored Dec 5, 2023
2 parents fc24d16 + f65be5f commit b591fb0
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 4 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,4 @@ Cargo.lock
/rust-toolchain.toml
.idea
.vscode
.pregenerated
.pregenerated
9 changes: 9 additions & 0 deletions apis/events/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,17 @@ pub trait Bus {
}

/// Event module for the autogenerated event code.
#[cfg(target_os = "linux")]
pub mod event {
#![allow(clippy::derive_partial_eq_without_eq)]
#![allow(clippy::large_enum_variant)]
tonic::include_proto!("v1.event");
}

// In order to IDE to work properly with event definitions on non-Linux platform,
// one can copy generated bindings (v1.event.rs) from a Linux target and put them to .pregenerated
// directory. This has to be done every time event API is changed.
#[cfg(not(target_os = "linux"))]
pub mod event {
include!("../../../.pregenerated/v1.event.rs");
}
2 changes: 1 addition & 1 deletion apis/io-engine/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ include!(concat!(env!("OUT_DIR"), "/mayastor.rs"));
// This has to be done every time Mayastor API V0 is changed.
#[cfg(not(target_os = "linux"))]
mod v0_generated {
include!("../.pregenerated/mayastor.rs");
include!("../../../.pregenerated/mayastor.rs");
}

#[cfg(not(target_os = "linux"))]
Expand Down
2 changes: 1 addition & 1 deletion apis/io-engine/src/v1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mod pb {
// to .pregenerated directory.
// This has to be done every time Mayastor API V1 is changed.
#[cfg(not(target_os = "linux"))]
include!("../.pregenerated/mayastor.v1.rs");
include!("../../../.pregenerated/mayastor.v1.rs");
}

pub mod common {
Expand Down
64 changes: 63 additions & 1 deletion composer/src/composer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{
ffi::{OsStr, OsString},
net::Ipv4Addr,
path::{Path, PathBuf},
sync::Mutex,
thread,
time::Duration,
};
Expand Down Expand Up @@ -43,13 +44,26 @@ pub const TEST_NET_NAME: &str = "engine-testing-network";
pub const TEST_LABEL_PREFIX: &str = "io.composer.test";
pub const TEST_NET_NETWORK: &str = "10.1.0.0/16";

/// Additional configuration.
#[derive(Default, Debug)]
struct AdditionalConfig {
/// Secondary target directory.
target_dir: Option<OsString>,
/// Additional binds.
binds: Vec<(String, String)>,
/// Additional components of PATH env var.
paths: Vec<String>,
}

static PROJECT_ROOT: OnceCell<PathBuf> = OnceCell::new();
static ADDITIONAL_CONFIG: OnceCell<Mutex<AdditionalConfig>> = OnceCell::new();

/// Initialize the composer with target project root.
/// Must be called before any Binary object is constructed.
/// If initialised more than once, the `project_root` **MUST** match previous initialisations.
pub fn initialize<T: AsRef<Path>>(project_root: T) {
let project_root = project_root.as_ref().to_path_buf();
let bin_prefix = project_root.clone();
match PROJECT_ROOT.get() {
Some(root) => {
assert!(
Expand All @@ -65,6 +79,38 @@ pub fn initialize<T: AsRef<Path>>(project_root: T) {
PROJECT_ROOT.get_or_init(|| project_root);
}
}

let mut cfg = ADDITIONAL_CONFIG
.get_or_init(|| Mutex::new(AdditionalConfig::default()))
.lock()
.unwrap();

if std::env::var("ASAN_ENABLE").unwrap_or_default() == "1" {
// When AddressSanitized (ASAN) is enabled, the binary is put in a different target dir like
// this:
// "target/x86_64-unknown-linux-gnu/<debug|release|...>/deps/<bin>".
// If the binary has this form, use the second portion as an additional target path.
if let Ok(t) = executable_path().strip_prefix(bin_prefix) {
let parts: Vec<_> = t.components().map(|s| s.as_os_str()).collect();

if parts.len() == 5 && parts[0] == "target" && parts[3] == "deps" {
cfg.target_dir = Some(OsString::from(parts[1]));
}
}

// We also have to have `llvm-symbolizer` utility in PATH in order to decode correctly
// symbols in ASAN output.
if let Ok(path) = std::env::var("LLVM_SYMBOLIZER_DIR") {
let path = path.as_str().to_owned();
cfg.binds.push((path.clone(), path.clone()));
cfg.paths.push(path);
}
}
}

/// Returns path of the test's binary.
fn executable_path() -> PathBuf {
PathBuf::from(std::env::args_os().next().unwrap())
}

/// Path to local binary and arguments
Expand All @@ -85,12 +131,27 @@ impl Binary {
}
/// Setup local binary from target for the given build type.
pub fn from_build_type(build_type: &str, name: &str) -> Self {
let cfg = ADDITIONAL_CONFIG.get().unwrap().lock().unwrap();

let project_root = PROJECT_ROOT.get().expect("Project root is not initialized");
let mut path = project_root.clone();
path.push("target");

if let Some(tgt_dir) = &cfg.target_dir {
path.push(tgt_dir);
}

path.push(build_type);
path.push(name);
Self::new(&path, vec![])

let mut res = Self::new(&path, vec![]);

cfg.binds.iter().for_each(|(k, v)| {
res.binds.insert(k.clone(), v.clone());
});

let paths = cfg.paths.join(":");
res.with_env("PATH", &paths)
}
/// Setup binary from path
pub fn from_path<T: AsRef<Path>>(name: T) -> Self {
Expand Down Expand Up @@ -261,6 +322,7 @@ impl ContainerSpec {
if !env.contains_key("RUST_LOG") {
env.insert("RUST_LOG".to_string(), RUST_LOG_DEFAULT.to_string());
}

Self {
name: name.into(),
binary: Some(binary),
Expand Down

0 comments on commit b591fb0

Please sign in to comment.