Skip to content

Commit 50c5ea2

Browse files
committed
Fix failure to process ETW events if CSwitch events happen after P-End
1 parent 60cfb7a commit 50c5ea2

File tree

1 file changed

+91
-13
lines changed

1 file changed

+91
-13
lines changed

collector/src/etw_parser.rs

Lines changed: 91 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -213,31 +213,32 @@ fn parse_events(r: &mut dyn BufRead, headers: Vec<EventHeader>) -> anyhow::Resul
213213
// Not the rustc process we're looking for
214214
(false, None) => { },
215215
(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+
216226
// read the parent process column and see if it is one of the sub_processes we're monitoring
217227
let parent_pid: u64 = columns[pstart_parent_pid].trim().parse().expect("couldn't parse parent pid");
218228

219229
// if it is, then add this to the set of watched processes
220230
if currently_watched_processes.contains(&parent_pid) {
221-
let pid = extract_pid(process_name);
222231
currently_watched_processes.insert(pid);
223232
all_watched_processes.insert(pid);
224233
}
225234
}
226235
}
227236
}
228237
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).
241242
}
242243
PMC => {
243244
last_pmc = Some(Pmc {
@@ -524,6 +525,83 @@ FirstReliableCSwitchEventTimeStamp, 6016
524525
Ok(())
525526
}
526527

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+
527605
#[test]
528606
fn process_events() -> anyhow::Result<()> {
529607
let events = EventData {

0 commit comments

Comments
 (0)