@@ -77,6 +77,7 @@ use crate::core::compiler::future_incompat::{
7777use crate :: core:: resolver:: ResolveBehavior ;
7878use crate :: core:: { PackageId , Shell , TargetKind } ;
7979use crate :: util:: diagnostic_server:: { self , DiagnosticPrinter } ;
80+ use crate :: util:: errors:: AlreadyPrintedError ;
8081use crate :: util:: machine_message:: { self , Message as _} ;
8182use crate :: util:: CargoResult ;
8283use crate :: util:: { self , internal, profile} ;
@@ -169,6 +170,10 @@ struct DrainState<'cfg> {
169170 per_package_future_incompat_reports : Vec < FutureIncompatReportPackage > ,
170171}
171172
173+ pub struct ErrorsDuringDrain {
174+ pub count : usize ,
175+ }
176+
172177#[ derive( Debug , Copy , Clone , PartialEq , Eq , Hash , PartialOrd , Ord ) ]
173178pub struct JobId ( pub u32 ) ;
174179
@@ -786,14 +791,14 @@ impl<'cfg> DrainState<'cfg> {
786791 // After a job has finished we update our internal state if it was
787792 // successful and otherwise wait for pending work to finish if it failed
788793 // and then immediately return.
789- let mut error = None ;
794+ let mut errors = ErrorsDuringDrain { count : 0 } ;
790795 // CAUTION! Do not use `?` or break out of the loop early. Every error
791796 // must be handled in such a way that the loop is still allowed to
792797 // drain event messages.
793798 loop {
794- if error . is_none ( ) {
799+ if errors . count == 0 {
795800 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) ;
797802 }
798803 }
799804
@@ -804,7 +809,7 @@ impl<'cfg> DrainState<'cfg> {
804809 }
805810
806811 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) ;
808813 }
809814
810815 // And finally, before we block waiting for the next event, drop any
@@ -814,7 +819,7 @@ impl<'cfg> DrainState<'cfg> {
814819 // to the jobserver itself.
815820 for event in self . wait_for_events ( ) {
816821 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) ;
818823 }
819824 }
820825 }
@@ -839,30 +844,24 @@ impl<'cfg> DrainState<'cfg> {
839844 }
840845
841846 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) ;
848849 }
849850 if cx. bcx . build_config . emit_json ( ) {
850851 let mut shell = cx. bcx . config . shell ( ) ;
851852 let msg = machine_message:: BuildFinished {
852- success : error . is_none ( ) ,
853+ success : errors . count == 0 ,
853854 }
854855 . to_json_string ( ) ;
855856 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 ( ) ) ;
861858 }
862859 }
863860
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) ) )
866865 } else if self . queue . is_empty ( ) && self . pending_queue . is_empty ( ) {
867866 let message = format ! (
868867 "{} [{}] target(s) in {}" ,
@@ -887,19 +886,14 @@ impl<'cfg> DrainState<'cfg> {
887886 fn handle_error (
888887 & self ,
889888 shell : & mut Shell ,
890- err_state : & mut Option < anyhow :: Error > ,
889+ err_state : & mut ErrorsDuringDrain ,
891890 new_err : anyhow:: Error ,
892891 ) {
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 {
898894 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) ;
902895 }
896+ err_state. count += 1 ;
903897 }
904898
905899 // 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.
12161210 Ok ( ( ) )
12171211 }
12181212}
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