From bd8308c0085f24f9c18bc62b06046d7a1ab1a1f2 Mon Sep 17 00:00:00 2001 From: Aman Karmani Date: Mon, 18 Nov 2024 12:53:55 -0800 Subject: [PATCH] Profile child processes on macOS closes #419 --- Cargo.lock | 76 +++++++++++++++++++++++++++++- samply/Cargo.toml | 1 + samply/src/mac/process_launcher.rs | 24 +++++++++- 3 files changed, 98 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8bf0d9a4..e4a56149 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -183,6 +183,24 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "597bb81c80a54b6a4381b23faba8d7774b144c94cbd1d6fe3f1329bd776554ab" +[[package]] +name = "bindgen" +version = "0.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f49d8fed880d473ea71efb9bf597651e77201bdd4893efe54c9e5d65ae04ce6f" +dependencies = [ + "bitflags", + "cexpr", + "clang-sys", + "itertools", + "proc-macro2", + "quote", + "regex", + "rustc-hash 1.1.0", + "shlex", + "syn", +] + [[package]] name = "bitflags" version = "2.6.0" @@ -299,6 +317,15 @@ dependencies = [ "shlex", ] +[[package]] +name = "cexpr" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" +dependencies = [ + "nom", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -311,6 +338,17 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "613afe47fcd5fac7ccf1db93babcb082c5994d996f20b8b159f2ad1658eb5724" +[[package]] +name = "clang-sys" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b023947811758c97c59bf9d1c188fd619ad4718dcaa767947df1cadb14f39f4" +dependencies = [ + "glob", + "libc", + "libloading", +] + [[package]] name = "clap" version = "4.5.19" @@ -809,6 +847,12 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "glob" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" + [[package]] name = "h2" version = "0.4.6" @@ -1045,6 +1089,27 @@ version = "0.2.159" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +[[package]] +name = "libloading" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" +dependencies = [ + "cfg-if", + "windows-targets 0.52.6", +] + +[[package]] +name = "libproc" +version = "0.14.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78a09b56be5adbcad5aa1197371688dc6bb249a26da3bca2011ee2fb987ebfb" +dependencies = [ + "bindgen", + "errno", + "libc", +] + [[package]] name = "libredox" version = "0.1.3" @@ -1523,7 +1588,7 @@ dependencies = [ "pin-project-lite", "quinn-proto", "quinn-udp", - "rustc-hash", + "rustc-hash 2.0.0", "rustls", "socket2", "thiserror", @@ -1540,7 +1605,7 @@ dependencies = [ "bytes", "rand", "ring", - "rustc-hash", + "rustc-hash 2.0.0", "rustls", "slab", "thiserror", @@ -1772,6 +1837,12 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustc-hash" version = "2.0.0" @@ -1880,6 +1951,7 @@ dependencies = [ "hyper-util", "lazy_static", "libc", + "libproc", "linux-perf-data", "log", "mach", diff --git a/samply/Cargo.toml b/samply/Cargo.toml index f116522a..977c32be 100644 --- a/samply/Cargo.toml +++ b/samply/Cargo.toml @@ -65,6 +65,7 @@ lazy_static = "1.5.0" flate2 = "1.0" sysctl = "0.6.0" plist = "1.7.0" +libproc = "0.14.10" [target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] diff --git a/samply/src/mac/process_launcher.rs b/samply/src/mac/process_launcher.rs index 8fc56725..639a5a57 100644 --- a/samply/src/mac/process_launcher.rs +++ b/samply/src/mac/process_launcher.rs @@ -9,6 +9,7 @@ use std::sync::Arc; use std::time::Duration; use flate2::write::GzDecoder; +use libproc::processes; use mach::task::{task_resume, task_suspend}; use mach::traps::task_for_pid; use tempfile::tempdir; @@ -295,6 +296,23 @@ impl RootTaskRunner for ExistingProcessRunner { } impl ExistingProcessRunner { + fn get_all_descendant_pids(pid: u32) -> Vec { + let mut descendants = Vec::new(); + let mut queue = vec![pid]; + + while let Some(current_pid) = queue.pop() { + let filter = processes::ProcFilter::ByParentProcess { ppid: current_pid }; + if let Ok(child_pids) = processes::pids_by_type(filter) { + for child_pid in child_pids { + descendants.push(child_pid); + queue.push(child_pid); + } + } + } + + descendants + } + pub fn new(pid: u32, task_accepter: &mut TaskAccepter) -> ExistingProcessRunner { let mut queue_pid = |pid, failure_is_ok| { let task = unsafe { @@ -326,7 +344,11 @@ impl ExistingProcessRunner { // always root pid first queue_pid(pid, false); - // TODO: find all its children + // find all its descendants recursively + let descendant_pids = Self::get_all_descendant_pids(pid); + for pid in descendant_pids { + queue_pid(pid, true); + } ExistingProcessRunner { pid,