@@ -77,6 +77,7 @@ use crate::core::compiler::future_incompat::{
77
77
use crate :: core:: resolver:: ResolveBehavior ;
78
78
use crate :: core:: { PackageId , Shell , TargetKind } ;
79
79
use crate :: util:: diagnostic_server:: { self , DiagnosticPrinter } ;
80
+ use crate :: util:: errors:: AlreadyPrintedError ;
80
81
use crate :: util:: machine_message:: { self , Message as _} ;
81
82
use crate :: util:: CargoResult ;
82
83
use crate :: util:: { self , internal, profile} ;
@@ -169,6 +170,10 @@ struct DrainState<'cfg> {
169
170
per_package_future_incompat_reports : Vec < FutureIncompatReportPackage > ,
170
171
}
171
172
173
+ pub struct ErrorsDuringDrain {
174
+ pub count : usize ,
175
+ }
176
+
172
177
#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
173
178
pub struct JobId ( pub u32 ) ;
174
179
@@ -786,14 +791,14 @@ impl<'cfg> DrainState<'cfg> {
786
791
// After a job has finished we update our internal state if it was
787
792
// successful and otherwise wait for pending work to finish if it failed
788
793
// and then immediately return.
789
- let mut error = None ;
794
+ let mut errors = ErrorsDuringDrain { count : 0 } ;
790
795
// CAUTION! Do not use `?` or break out of the loop early. Every error
791
796
// must be handled in such a way that the loop is still allowed to
792
797
// drain event messages.
793
798
loop {
794
- if error . is_none ( ) {
799
+ if errors . count == 0 {
795
800
if let Err ( e) = self . spawn_work_if_possible ( cx, jobserver_helper, scope) {
796
- self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut error , e) ;
801
+ self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut errors , e) ;
797
802
}
798
803
}
799
804
@@ -804,7 +809,7 @@ impl<'cfg> DrainState<'cfg> {
804
809
}
805
810
806
811
if let Err ( e) = self . grant_rustc_token_requests ( ) {
807
- self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut error , e) ;
812
+ self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut errors , e) ;
808
813
}
809
814
810
815
// And finally, before we block waiting for the next event, drop any
@@ -814,7 +819,7 @@ impl<'cfg> DrainState<'cfg> {
814
819
// to the jobserver itself.
815
820
for event in self . wait_for_events ( ) {
816
821
if let Err ( event_err) = self . handle_event ( cx, jobserver_helper, plan, event) {
817
- self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut error , event_err) ;
822
+ self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut errors , event_err) ;
818
823
}
819
824
}
820
825
}
@@ -839,30 +844,24 @@ impl<'cfg> DrainState<'cfg> {
839
844
}
840
845
841
846
let time_elapsed = util:: elapsed ( cx. bcx . config . creation_time ( ) . elapsed ( ) ) ;
842
- if let Err ( e) = self . timings . finished ( cx, & error) {
843
- if error. is_some ( ) {
844
- crate :: display_error ( & e, & mut cx. bcx . config . shell ( ) ) ;
845
- } else {
846
- return Some ( e) ;
847
- }
847
+ if let Err ( e) = self . timings . finished ( cx, & errors. to_error ( ) ) {
848
+ self . handle_error ( & mut cx. bcx . config . shell ( ) , & mut errors, e) ;
848
849
}
849
850
if cx. bcx . build_config . emit_json ( ) {
850
851
let mut shell = cx. bcx . config . shell ( ) ;
851
852
let msg = machine_message:: BuildFinished {
852
- success : error . is_none ( ) ,
853
+ success : errors . count == 0 ,
853
854
}
854
855
. to_json_string ( ) ;
855
856
if let Err ( e) = writeln ! ( shell. out( ) , "{}" , msg) {
856
- if error. is_some ( ) {
857
- crate :: display_error ( & e. into ( ) , & mut shell) ;
858
- } else {
859
- return Some ( e. into ( ) ) ;
860
- }
857
+ self . handle_error ( & mut shell, & mut errors, e. into ( ) ) ;
861
858
}
862
859
}
863
860
864
- if let Some ( e) = error {
865
- Some ( e)
861
+ if let Some ( error) = errors. to_error ( ) {
862
+ // Any errors up to this point have already been printed via the
863
+ // `display_error` inside `handle_error`.
864
+ Some ( anyhow:: Error :: new ( AlreadyPrintedError :: new ( error) ) )
866
865
} else if self . queue . is_empty ( ) && self . pending_queue . is_empty ( ) {
867
866
let message = format ! (
868
867
"{} [{}] target(s) in {}" ,
@@ -887,19 +886,14 @@ impl<'cfg> DrainState<'cfg> {
887
886
fn handle_error (
888
887
& self ,
889
888
shell : & mut Shell ,
890
- err_state : & mut Option < anyhow :: Error > ,
889
+ err_state : & mut ErrorsDuringDrain ,
891
890
new_err : anyhow:: Error ,
892
891
) {
893
- if err_state. is_some ( ) {
894
- // Already encountered one error.
895
- log:: warn!( "{:?}" , new_err) ;
896
- } else if !self . active . is_empty ( ) {
897
- crate :: display_error ( & new_err, shell) ;
892
+ crate :: display_error ( & new_err, shell) ;
893
+ if !self . active . is_empty ( ) && err_state. count == 0 {
898
894
drop ( shell. warn ( "build failed, waiting for other jobs to finish..." ) ) ;
899
- * err_state = Some ( anyhow:: format_err!( "build failed" ) ) ;
900
- } else {
901
- * err_state = Some ( new_err) ;
902
895
}
896
+ err_state. count += 1 ;
903
897
}
904
898
905
899
// This also records CPU usage and marks concurrency; we roughly want to do
@@ -1216,3 +1210,13 @@ feature resolver. Try updating to diesel 1.4.8 to fix this error.
1216
1210
Ok ( ( ) )
1217
1211
}
1218
1212
}
1213
+
1214
+ impl ErrorsDuringDrain {
1215
+ fn to_error ( & self ) -> Option < anyhow:: Error > {
1216
+ match self . count {
1217
+ 0 => None ,
1218
+ 1 => Some ( format_err ! ( "1 job failed" ) ) ,
1219
+ n => Some ( format_err ! ( "{} jobs failed" , n) ) ,
1220
+ }
1221
+ }
1222
+ }
0 commit comments