Skip to content

Commit cdeef1f

Browse files
Merge pull request #2016 from lqd/self-profile-issue
Handle measureme panics, and don't crash the collector on self-profile data errors
2 parents 8830c4d + 2cdeaa1 commit cdeef1f

File tree

1 file changed

+36
-7
lines changed
  • collector/src/compile/execute

1 file changed

+36
-7
lines changed

collector/src/compile/execute/mod.rs

+36-7
Original file line numberDiff line numberDiff line change
@@ -574,7 +574,21 @@ fn process_stat_output(
574574
return Err(DeserializeStatError::NoOutput(output));
575575
}
576576
let (profile, files) = match (self_profile_dir, self_profile_crate) {
577-
(Some(dir), Some(krate)) => parse_self_profile(dir, krate)?,
577+
(Some(dir), Some(krate)) => {
578+
// FIXME: errors reading the self-profile data should be recorded as benchmark failures
579+
// and made more visible in the UI. Until then, we only log errors and continue with the
580+
// run, as if we had no self-profile data.
581+
// The self-profile page already supports missing data, but it's unclear exactly how the
582+
// rest of the site handles this situation.
583+
// In any case it's better than crashing the collector and looping indefinitely trying
584+
// to to complete a run -- which happens if we propagate `parse_self_profile`'s errors
585+
// up to the caller.
586+
if let Ok(self_profile_data) = parse_self_profile(dir, krate) {
587+
self_profile_data
588+
} else {
589+
(None, None)
590+
}
591+
}
578592
_ => (None, None),
579593
};
580594
Ok((stats, profile, files))
@@ -636,12 +650,27 @@ fn parse_self_profile(
636650
let (profile, files) = if let Some(profile_path) = full_path {
637651
// measureme 0.8+ uses a single file
638652
let data = fs::read(&profile_path)?;
639-
let results = analyzeme::ProfilingData::from_paged_buffer(data, None)
640-
.map_err(|error| {
641-
eprintln!("Cannot read self-profile data: {error:?}");
642-
std::io::Error::new(ErrorKind::InvalidData, error)
643-
})?
644-
.perform_analysis();
653+
654+
// HACK: `decodeme` can unexpectedly panic on invalid data produced by rustc. We catch this
655+
// here until it's fixed and emits a proper error.
656+
let res =
657+
std::panic::catch_unwind(|| analyzeme::ProfilingData::from_paged_buffer(data, None));
658+
let results = match res {
659+
Ok(Ok(profiling_data)) => profiling_data.perform_analysis(),
660+
Ok(Err(error)) => {
661+
// A "regular" error in measureme.
662+
log::error!("Cannot read self-profile data: {error:?}");
663+
return Err(std::io::Error::new(ErrorKind::InvalidData, error));
664+
}
665+
Err(error) => {
666+
// An unexpected panic in measureme: it sometimes happens when encountering some
667+
// cases of invalid mm_profdata files.
668+
let error = format!("Unexpected measureme error with self-profile data: {error:?}");
669+
log::error!("{error}");
670+
return Err(std::io::Error::new(ErrorKind::InvalidData, error));
671+
}
672+
};
673+
645674
let profile = SelfProfile {
646675
artifact_sizes: results.artifact_sizes,
647676
};

0 commit comments

Comments
 (0)