@@ -401,8 +401,13 @@ impl<'cfg> JobQueue<'cfg> {
401
401
. take ( )
402
402
. map ( move |srv| srv. start ( move |msg| messages. push ( Message :: FixDiagnostic ( msg) ) ) ) ;
403
403
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" )
406
411
}
407
412
}
408
413
@@ -615,13 +620,18 @@ impl<'cfg> DrainState<'cfg> {
615
620
events
616
621
}
617
622
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.
618
628
fn drain_the_queue (
619
629
mut self ,
620
630
cx : & mut Context < ' _ , ' _ > ,
621
631
plan : & mut BuildPlan ,
622
632
scope : & Scope < ' _ > ,
623
633
jobserver_helper : & HelperThread ,
624
- ) -> CargoResult < ( ) > {
634
+ ) -> Option < anyhow :: Error > {
625
635
trace ! ( "queue: {:#?}" , self . queue) ;
626
636
627
637
// Iteratively execute the entire dependency graph. Each turn of the
@@ -635,8 +645,9 @@ impl<'cfg> DrainState<'cfg> {
635
645
// successful and otherwise wait for pending work to finish if it failed
636
646
// and then immediately return.
637
647
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.
640
651
loop {
641
652
if error. is_none ( ) {
642
653
if let Err ( e) = self . spawn_work_if_possible ( cx, jobserver_helper, scope) {
@@ -690,7 +701,7 @@ impl<'cfg> DrainState<'cfg> {
690
701
if error. is_some ( ) {
691
702
crate :: display_error ( & e, & mut cx. bcx . config . shell ( ) ) ;
692
703
} else {
693
- return Err ( e) ;
704
+ return Some ( e) ;
694
705
}
695
706
}
696
707
if cx. bcx . build_config . emit_json ( ) {
@@ -702,13 +713,13 @@ impl<'cfg> DrainState<'cfg> {
702
713
if error. is_some ( ) {
703
714
crate :: display_error ( & e. into ( ) , & mut cx. bcx . config . shell ( ) ) ;
704
715
} else {
705
- return Err ( e. into ( ) ) ;
716
+ return Some ( e. into ( ) ) ;
706
717
}
707
718
}
708
719
}
709
720
710
721
if let Some ( e) = error {
711
- Err ( e)
722
+ Some ( e)
712
723
} else if self . queue . is_empty ( ) && self . pending_queue . is_empty ( ) {
713
724
let message = format ! (
714
725
"{} [{}] target(s) in {}" ,
@@ -718,10 +729,10 @@ impl<'cfg> DrainState<'cfg> {
718
729
// It doesn't really matter if this fails.
719
730
drop ( cx. bcx . config . shell ( ) . status ( "Finished" , message) ) ;
720
731
}
721
- Ok ( ( ) )
732
+ None
722
733
} else {
723
734
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" ) )
725
736
}
726
737
}
727
738
0 commit comments