From 78aa79ff81cc577a5502165f2e419bcbb6bfa820 Mon Sep 17 00:00:00 2001 From: Rob Day Date: Mon, 4 Sep 2023 19:07:19 +0100 Subject: [PATCH] Switch to SwCpuClock on ENOENT error The `perf_event_open` manpage says that ENOENT is "Returned if the type setting is not valid.". Prior to this fix, samply only switched to SwCpuClick on an EPERM error. This fix means that we try it speculatively whatever the error, unless it's a EPERM that can be fixed by changing the paranoia level. --- samply/src/linux/profiler.rs | 59 ++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/samply/src/linux/profiler.rs b/samply/src/linux/profiler.rs index cc6574777..9df898cd5 100644 --- a/samply/src/linux/profiler.rs +++ b/samply/src/linux/profiler.rs @@ -353,11 +353,10 @@ fn init_profiler( attach_mode, ); - let mut perf = match perf { - Ok(perf) => perf, - Err(error) if error.kind() == std::io::ErrorKind::PermissionDenied => { - match paranoia_level() { - Some(level) if level > 1 => { + if let Err(error) = &perf { + if error.kind() == std::io::ErrorKind::PermissionDenied { + if let Some(level) = paranoia_level() { + if level > 1 { eprintln!(); eprintln!( "'/proc/sys/kernel/perf_event_paranoid' is currently set to {level}." @@ -369,32 +368,34 @@ fn init_profiler( eprintln!(); std::process::exit(1); } - _ => { - // Permission denied even though parania was probably not the reason. - // Another reason for the error could be the type of perf event: - // The "Hardware CPU cycles" event is not supported in some contexts, for example in VMs. - // Try a different event type. - let perf = PerfGroup::open( - pid, - frequency, - stack_size, - EventSource::SwCpuClock, - regs_mask, - attach_mode, - ); - match perf { - Ok(perf) => perf, // Success! - Err(error) => { - eprintln!("Failed to start profiling: {error}"); - std::process::exit(1); - } - } - } } } - Err(error) => { - eprintln!("Failed to start profiling: {error}"); - std::process::exit(1); + } + + let mut perf = match perf { + Ok(perf) => perf, + Err(_) => { + // We've already checked for permission denied due to paranoia + // level, and exited with a warning in that case. + + // Another reason for the error could be the type of perf event: + // The "Hardware CPU cycles" event is not supported in some contexts, for example in VMs. + // Try a different event type. + let perf = PerfGroup::open( + pid, + frequency, + stack_size, + EventSource::SwCpuClock, + regs_mask, + attach_mode, + ); + match perf { + Ok(perf) => perf, // Success! + Err(error) => { + eprintln!("Failed to start profiling: {error}"); + std::process::exit(1); + } + } } };