From c4a362b5aeabbf06708098c631be4f1c3f662e43 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Tue, 7 Jan 2020 09:10:02 +0100 Subject: [PATCH 1/9] option for not using SIGSTOP because not all apps take it well --- src/args.rs | 6 +++++- src/cmd_record.rs | 2 +- src/perf_group.rs | 17 +++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/src/args.rs b/src/args.rs index 48f2335..de85f19 100644 --- a/src/args.rs +++ b/src/args.rs @@ -195,7 +195,11 @@ pub struct RecordArgs { pub discard_all: bool, #[structopt(flatten)] - pub profiler_args: GenericProfilerArgs + pub profiler_args: GenericProfilerArgs, + + #[structopt(long)] + /// Do not stop processes before gathering its info + pub dont_stop_processes: bool } #[derive(StructOpt, Debug)] diff --git a/src/cmd_record.rs b/src/cmd_record.rs index 3bd2a60..e9ca9d8 100644 --- a/src/cmd_record.rs +++ b/src/cmd_record.rs @@ -59,7 +59,7 @@ pub fn main( args: args::RecordArgs ) -> Result< (), Box< dyn Error > > { }); info!( "Opening perf events for process with PID {}...", controller.pid() ); - let mut perf = match PerfGroup::open( controller.pid(), args.frequency, args.stack_size, args.event_source ) { + let mut perf = match PerfGroup::open( controller.pid(), args.frequency, args.stack_size, args.event_source, !args.dont_stop_processes ) { Ok( perf ) => perf, Err( error ) => { error!( "Failed to start profiling: {}", error ); diff --git a/src/perf_group.rs b/src/perf_group.rs index bb2a485..9057878 100644 --- a/src/perf_group.rs +++ b/src/perf_group.rs @@ -102,7 +102,8 @@ pub struct PerfGroup { stack_size: u32, event_source: EventSource, initial_events: Vec< Event< 'static > >, - stopped_processes: Vec< StoppedProcess > + stopped_processes: Vec< StoppedProcess >, + stop_processes: bool } fn poll_events< 'a, I >( poll_fds: &mut Vec< libc::pollfd >, iter: I ) where I: IntoIterator< Item = &'a Member >, ::IntoIter: Clone { @@ -163,7 +164,7 @@ fn get_threads( pid: u32 ) -> Result< Vec< (u32, Option< Vec< u8 > >) >, io::Err } impl PerfGroup { - pub fn new( frequency: u32, stack_size: u32, event_source: EventSource ) -> Self { + pub fn new( frequency: u32, stack_size: u32, event_source: EventSource, stop_processes: bool ) -> Self { let group = PerfGroup { event_buffer: Vec::new(), members: Default::default(), @@ -172,20 +173,24 @@ impl PerfGroup { stack_size, event_source, initial_events: Vec::new(), - stopped_processes: Vec::new() + stopped_processes: Vec::new(), + stop_processes: stop_processes }; group } - pub fn open( pid: u32, frequency: u32, stack_size: u32, event_source: EventSource ) -> Result< Self, io::Error > { - let mut group = PerfGroup::new( frequency, stack_size, event_source ); + pub fn open( pid: u32, frequency: u32, stack_size: u32, event_source: EventSource, stop_processes: bool ) -> Result< Self, io::Error > { + let mut group = PerfGroup::new( frequency, stack_size, event_source, stop_processes ); group.open_process( pid )?; Ok( group ) } pub fn open_process( &mut self, pid: u32 ) -> Result< (), io::Error > { - self.stopped_processes.push( StoppedProcess::new( pid )? ); + if self.stop_processes { + self.stopped_processes.push( StoppedProcess::new( pid )? ); + } + let mut perf_events = Vec::new(); let threads = get_threads( pid )?; From ef29cdb11056c3d00c3fea3984b065deb888c6c8 Mon Sep 17 00:00:00 2001 From: Piotr Podusowski Date: Fri, 10 Jan 2020 10:59:32 +0100 Subject: [PATCH 2/9] workaround for possibly infinite unwind loop --- nwind/src/unwind_context.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/nwind/src/unwind_context.rs b/nwind/src/unwind_context.rs index 6131fb5..c7891d3 100644 --- a/nwind/src/unwind_context.rs +++ b/nwind/src/unwind_context.rs @@ -96,6 +96,12 @@ impl< 'a, A: Architecture > UnwindHandle< 'a, A > { self.ctx.nth_frame += 1; + // avoid infinite loops + if self.ctx.nth_frame > 100 { + warn!("infinite loop detected and avoided"); + return false; + } + self.ctx.address = self.ctx.regs.get( A::INSTRUCTION_POINTER_REG ).unwrap(); debug!( "Unwinding #{} -> #{} at: 0x{:016X}", self.ctx.nth_frame - 1, self.ctx.nth_frame, self.ctx.address ); From f20e756f68b3b45641e2c10b00ffb42f37a62927 Mon Sep 17 00:00:00 2001 From: Piotr Date: Fri, 10 Jan 2020 17:23:27 +0100 Subject: [PATCH 3/9] Update nwind/src/unwind_context.rs Co-Authored-By: bjorn3 --- nwind/src/unwind_context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nwind/src/unwind_context.rs b/nwind/src/unwind_context.rs index c7891d3..c6dd7ce 100644 --- a/nwind/src/unwind_context.rs +++ b/nwind/src/unwind_context.rs @@ -97,7 +97,7 @@ impl< 'a, A: Architecture > UnwindHandle< 'a, A > { self.ctx.nth_frame += 1; // avoid infinite loops - if self.ctx.nth_frame > 100 { + if self.ctx.nth_frame > 1000 { warn!("infinite loop detected and avoided"); return false; } From c6c6f28c6e89aac6b4f59b59fe5dd887117e5715 Mon Sep 17 00:00:00 2001 From: Piotr Date: Fri, 10 Jan 2020 17:23:45 +0100 Subject: [PATCH 4/9] Update nwind/src/unwind_context.rs Co-Authored-By: bjorn3 --- nwind/src/unwind_context.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nwind/src/unwind_context.rs b/nwind/src/unwind_context.rs index c6dd7ce..bd050bd 100644 --- a/nwind/src/unwind_context.rs +++ b/nwind/src/unwind_context.rs @@ -98,7 +98,7 @@ impl< 'a, A: Architecture > UnwindHandle< 'a, A > { // avoid infinite loops if self.ctx.nth_frame > 1000 { - warn!("infinite loop detected and avoided"); + warn!("possible infinite loop detected and avoided"); return false; } From 5e07279e3d4c4b2a557bfbb9b1b0b5207a5308b7 Mon Sep 17 00:00:00 2001 From: Piotr Date: Sat, 11 Jan 2020 18:49:00 +0100 Subject: [PATCH 5/9] Update src/args.rs Co-Authored-By: bjorn3 --- src/args.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/args.rs b/src/args.rs index de85f19..89c8b79 100644 --- a/src/args.rs +++ b/src/args.rs @@ -199,7 +199,7 @@ pub struct RecordArgs { #[structopt(long)] /// Do not stop processes before gathering its info - pub dont_stop_processes: bool + pub dont_stop_processes: bool, } #[derive(StructOpt, Debug)] From 9d39e02533f47e575d0d38f09fac6a524ed8ff72 Mon Sep 17 00:00:00 2001 From: Piotr Date: Sat, 11 Jan 2020 18:49:09 +0100 Subject: [PATCH 6/9] Update src/perf_group.rs Co-Authored-By: bjorn3 --- src/perf_group.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/perf_group.rs b/src/perf_group.rs index 9057878..b88793f 100644 --- a/src/perf_group.rs +++ b/src/perf_group.rs @@ -103,7 +103,7 @@ pub struct PerfGroup { event_source: EventSource, initial_events: Vec< Event< 'static > >, stopped_processes: Vec< StoppedProcess >, - stop_processes: bool + stop_processes: bool, } fn poll_events< 'a, I >( poll_fds: &mut Vec< libc::pollfd >, iter: I ) where I: IntoIterator< Item = &'a Member >, ::IntoIter: Clone { From 9a87266a9c57f642243a6bfd63337059af2a0bb9 Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 17 Jan 2020 16:44:24 +0100 Subject: [PATCH 7/9] Fix style --- src/perf_group.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/perf_group.rs b/src/perf_group.rs index b88793f..5cfa0d3 100644 --- a/src/perf_group.rs +++ b/src/perf_group.rs @@ -174,7 +174,7 @@ impl PerfGroup { event_source, initial_events: Vec::new(), stopped_processes: Vec::new(), - stop_processes: stop_processes + stop_processes }; group From fb72c215cddbd98b623269dd24d9a098be2814db Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 17 Jan 2020 16:54:24 +0100 Subject: [PATCH 8/9] `dont_stop_processes` -> `do_not_send_sigstop` (1/2) --- src/args.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/args.rs b/src/args.rs index 89c8b79..74c9337 100644 --- a/src/args.rs +++ b/src/args.rs @@ -198,8 +198,8 @@ pub struct RecordArgs { pub profiler_args: GenericProfilerArgs, #[structopt(long)] - /// Do not stop processes before gathering its info - pub dont_stop_processes: bool, + /// Do not send SIGSTOP before hooking into the process + pub do_not_send_sigstop: bool, } #[derive(StructOpt, Debug)] From 54a77dd32ce2918483ca0a012be0e542f459bee6 Mon Sep 17 00:00:00 2001 From: Koute Date: Fri, 17 Jan 2020 16:54:30 +0100 Subject: [PATCH 9/9] `dont_stop_processes` -> `do_not_send_sigstop` (2/2) --- src/cmd_record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cmd_record.rs b/src/cmd_record.rs index e9ca9d8..c6d9cee 100644 --- a/src/cmd_record.rs +++ b/src/cmd_record.rs @@ -59,7 +59,7 @@ pub fn main( args: args::RecordArgs ) -> Result< (), Box< dyn Error > > { }); info!( "Opening perf events for process with PID {}...", controller.pid() ); - let mut perf = match PerfGroup::open( controller.pid(), args.frequency, args.stack_size, args.event_source, !args.dont_stop_processes ) { + let mut perf = match PerfGroup::open( controller.pid(), args.frequency, args.stack_size, args.event_source, !args.do_not_send_sigstop ) { Ok( perf ) => perf, Err( error ) => { error!( "Failed to start profiling: {}", error );