@@ -213,31 +213,32 @@ fn parse_events(r: &mut dyn BufRead, headers: Vec<EventHeader>) -> anyhow::Resul
213
213
// Not the rustc process we're looking for
214
214
( false , None ) => { } ,
215
215
( false , Some ( _) ) => {
216
+ let pid = extract_pid ( process_name) ;
217
+
218
+ // If the pid is already in the currently_watched_processes list,
219
+ // then that process has already ended and its pid has been recycled.
220
+ // We need to remove it from the watched processes list.
221
+ if currently_watched_processes. contains ( & pid) {
222
+ log:: debug!( "a re-used PID was detected for pid {}" , pid) ;
223
+ currently_watched_processes. remove ( & pid) ;
224
+ }
225
+
216
226
// read the parent process column and see if it is one of the sub_processes we're monitoring
217
227
let parent_pid: u64 = columns[ pstart_parent_pid] . trim ( ) . parse ( ) . expect ( "couldn't parse parent pid" ) ;
218
228
219
229
// if it is, then add this to the set of watched processes
220
230
if currently_watched_processes. contains ( & parent_pid) {
221
- let pid = extract_pid ( process_name) ;
222
231
currently_watched_processes. insert ( pid) ;
223
232
all_watched_processes. insert ( pid) ;
224
233
}
225
234
}
226
235
}
227
236
}
228
237
PROCESS_END => {
229
- let process_name = columns[ pend_process_name] . trim ( ) ;
230
-
231
- // if this is a watched process that has ended, remove it from the set
232
- let pid = extract_pid ( process_name) ;
233
- currently_watched_processes. remove ( & pid) ;
234
-
235
- // stop processing events after the P-End event for the rustc process
236
- if let Some ( rustc_process) = & rustc_process {
237
- if process_name == rustc_process {
238
- break ;
239
- }
240
- }
238
+ // On process end, don't remove the process from the watched processes list
239
+ // because sometimes C-Switch events come in after the P-End event and we
240
+ // don't want to miss them. (If PID reuse occurs for a watched process, we
241
+ // detect this in PROCESS_START).
241
242
}
242
243
PMC => {
243
244
last_pmc = Some ( Pmc {
@@ -524,6 +525,83 @@ FirstReliableCSwitchEventTimeStamp, 6016
524
525
Ok ( ( ) )
525
526
}
526
527
528
+ #[ test]
529
+ fn parse_events_pmc_cswitch_after_pend ( ) -> anyhow:: Result < ( ) > {
530
+ // Tests that in case the pmc/cswitch event pair comes in after the p-end event, we still include the pair in the results.
531
+
532
+ let headers = vec ! [
533
+ EventHeader {
534
+ name: "P-Start" . into( ) ,
535
+ columns: vec![ "TimeStamp" . into( ) , "Process Name ( PID)" . into( ) , "ParentPID" . into( ) ] ,
536
+ } ,
537
+ EventHeader {
538
+ name: "P-End" . into( ) ,
539
+ columns: vec![ "TimeStamp" . into( ) , "Process Name ( PID)" . into( ) , "ParentPID" . into( ) ]
540
+ } ,
541
+ EventHeader {
542
+ name: "CSwitch" . into( ) ,
543
+ columns: vec![ "TimeStamp" . into( ) , "New Process Name ( PID)" . into( ) , "New TID" . into( ) , "Old Process Name ( PID)" . into( ) , "Old TID" . into( ) , "CPU" . into( ) , "IdealProc" . into( ) ] ,
544
+ } ,
545
+ EventHeader {
546
+ name: "Pmc" . to_string( ) ,
547
+ columns: vec![ "TimeStamp" . into( ) , "ThreadID" . into( ) , "InstructionRetired" . into( ) , "TotalCycles" . into( ) ] ,
548
+ }
549
+ ] ;
550
+
551
+ let mut events = BufReader :: new ( "OS Version: 10.0.19043, Trace Size: 20736KB, Events Lost: 0, Buffers lost: 0, Trace Start: 132675686690347142, Trace Length: 2 sec, PointerSize: 8, Trace Name: pmc_counters_merged.etl
552
+ FirstReliableEventTimeStamp, 0
553
+ FirstReliableCSwitchEventTimeStamp, 6016
554
+ UnknownEvent/Classic, 0, tracelog.exe (8108), 24632, 0, {68fdd900-4a3e-11d1-84f4-0000f80464e3}, 0x50, 0x00, 0x0002, 48
555
+ GroupMasks, 0, 0, 0x00000000
556
+ Pmc, 256444, 0, 43430750, 47757881
557
+ CSwitch, 256444, Idle ( 0), 0, csrss.exe ( 608), 1044, 0, 0, Important, Important
558
+ Pmc, 256448, 22992, 82586058, 89184079
559
+ CSwitch, 256448, powershell.exe (13872), 22992, Idle ( 0), 0, 0, 1, Important, Important
560
+ P-Start, 104743, rustc.exe (10612), 480, 1, 0x0000938192a10300, 0x000000049f5be000, 0x00000000, S-1-12-1-2346571520-1185420729-3708355771-3596251678, \" rustc.exe\" --crate-name regex src\\ lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 -C metadata=3e524b9e4d4e3569 -C extra-filename=-3e524b9e4d4e3569 --out-dir .tmpeAXOco\\ target\\ debug\\ deps -L dependency=deps --extern aho_corasick=.tmp, <none>, <none>
561
+ Pmc, 104811, 0, 1808061, 2972786
562
+ CSwitch, 104811, Idle ( 0), 0, rustc-fake.exe ( 480), 26116, 0, 0, Important, Important
563
+ Pmc, 106082, 15340, 3184489, 3416818
564
+ CSwitch, 106082, rustc.exe (10612), 15340, Idle ( 0), 0, 0, 1, Important, Important
565
+ P-End, 107179, rustc.exe (10612), 480, 1, 0x0000938192a10300, 0x00000000, 0x000000049f5be000, 0x00000000, S-1-12-1-2346571520-1185420729-3708355771-3596251678, \" rustc.exe\" --crate-name regex src\\ lib.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type lib --emit=dep-info,metadata -C embed-bitcode=no -C debuginfo=2 -C metadata=3e524b9e4d4e3569 -C extra-filename=-3e524b9e4d4e3569 --out-dir .tmpeAXOco\\ target\\ debug\\ deps -L dependency=deps --extern aho_corasick=.tmp, <none>, <none>
566
+ Pmc, 1359642, 15340, 4205942, 3779655
567
+ CSwitch, 1359642, Idle ( 0), 15340, rustc.exe (10612), 0, 0, 1, Important, Important" . as_bytes ( ) ) ;
568
+
569
+ let expected = EventData {
570
+ events : vec ! [
571
+ ( Pmc {
572
+ timestamp: 106082 ,
573
+ thread_id: 15340 ,
574
+ instructions_retired: 3184489 ,
575
+ total_cycles: 3416818 ,
576
+ } ,
577
+ CSwitch {
578
+ timestamp: 106082 ,
579
+ new_process_pid: 10612 , // rustc.exe
580
+ old_process_pid: 0 , // Idle
581
+ cpu: 0 ,
582
+ } ) ,
583
+
584
+ ( Pmc {
585
+ timestamp: 1359642 ,
586
+ thread_id: 15340 ,
587
+ instructions_retired: 4205942 ,
588
+ total_cycles: 3779655 ,
589
+ } ,
590
+ CSwitch {
591
+ timestamp: 1359642 ,
592
+ new_process_pid: 0 , // Idle
593
+ old_process_pid: 10612 , // rustc.exe
594
+ cpu: 0 ,
595
+ } )
596
+ ] ,
597
+ watched_processes : [ 10612 ] . iter ( ) . copied ( ) . collect ( ) ,
598
+ } ;
599
+
600
+ assert_eq ! ( expected, super :: parse_events( & mut events, headers) ?) ;
601
+
602
+ Ok ( ( ) )
603
+ }
604
+
527
605
#[ test]
528
606
fn process_events ( ) -> anyhow:: Result < ( ) > {
529
607
let events = EventData {
0 commit comments