Skip to content

Commit 5e561ae

Browse files
committed
Ensure drain_the_queue does not attempt to return a Result.
1 parent 0a5960b commit 5e561ae

File tree

1 file changed

+21
-10
lines changed

1 file changed

+21
-10
lines changed

src/cargo/core/compiler/job_queue.rs

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,13 @@ impl<'cfg> JobQueue<'cfg> {
401401
.take()
402402
.map(move |srv| srv.start(move |msg| messages.push(Message::FixDiagnostic(msg))));
403403

404-
crossbeam_utils::thread::scope(move |scope| state.drain_the_queue(cx, plan, scope, &helper))
405-
.expect("child threads shouldn't panic")
404+
crossbeam_utils::thread::scope(move |scope| {
405+
match state.drain_the_queue(cx, plan, scope, &helper) {
406+
Some(err) => Err(err),
407+
None => Ok(()),
408+
}
409+
})
410+
.expect("child threads shouldn't panic")
406411
}
407412
}
408413

@@ -615,13 +620,18 @@ impl<'cfg> DrainState<'cfg> {
615620
events
616621
}
617622

623+
/// This is the "main" loop, where Cargo does all work to run the
624+
/// compiler.
625+
///
626+
/// This returns an Option to prevent the use of `?` on `Result` types
627+
/// because it is important for the loop to carefully handle errors.
618628
fn drain_the_queue(
619629
mut self,
620630
cx: &mut Context<'_, '_>,
621631
plan: &mut BuildPlan,
622632
scope: &Scope<'_>,
623633
jobserver_helper: &HelperThread,
624-
) -> CargoResult<()> {
634+
) -> Option<anyhow::Error> {
625635
trace!("queue: {:#?}", self.queue);
626636

627637
// Iteratively execute the entire dependency graph. Each turn of the
@@ -635,8 +645,9 @@ impl<'cfg> DrainState<'cfg> {
635645
// successful and otherwise wait for pending work to finish if it failed
636646
// and then immediately return.
637647
let mut error = None;
638-
// CAUTION! From here on out, do not use `?`. Every error must be handled
639-
// in such a way that the loop is still allowed to drain event messages.
648+
// CAUTION! Do not use `?` or break out of the loop early. Every error
649+
// must be handled in such a way that the loop is still allowed to
650+
// drain event messages.
640651
loop {
641652
if error.is_none() {
642653
if let Err(e) = self.spawn_work_if_possible(cx, jobserver_helper, scope) {
@@ -690,7 +701,7 @@ impl<'cfg> DrainState<'cfg> {
690701
if error.is_some() {
691702
crate::display_error(&e, &mut cx.bcx.config.shell());
692703
} else {
693-
return Err(e);
704+
return Some(e);
694705
}
695706
}
696707
if cx.bcx.build_config.emit_json() {
@@ -702,13 +713,13 @@ impl<'cfg> DrainState<'cfg> {
702713
if error.is_some() {
703714
crate::display_error(&e.into(), &mut cx.bcx.config.shell());
704715
} else {
705-
return Err(e.into());
716+
return Some(e.into());
706717
}
707718
}
708719
}
709720

710721
if let Some(e) = error {
711-
Err(e)
722+
Some(e)
712723
} else if self.queue.is_empty() && self.pending_queue.is_empty() {
713724
let message = format!(
714725
"{} [{}] target(s) in {}",
@@ -718,10 +729,10 @@ impl<'cfg> DrainState<'cfg> {
718729
// It doesn't really matter if this fails.
719730
drop(cx.bcx.config.shell().status("Finished", message));
720731
}
721-
Ok(())
732+
None
722733
} else {
723734
debug!("queue: {:#?}", self.queue);
724-
Err(internal("finished with jobs still left in the queue"))
735+
Some(internal("finished with jobs still left in the queue"))
725736
}
726737
}
727738

0 commit comments

Comments
 (0)