@@ -2,10 +2,12 @@ use std::cell::Cell;
2
2
use std:: collections:: { HashMap , HashSet } ;
3
3
use std:: io;
4
4
use std:: marker;
5
+ use std:: mem;
5
6
use std:: sync:: mpsc:: { channel, Receiver , Sender } ;
6
7
use std:: sync:: Arc ;
7
8
8
9
use crossbeam_utils:: thread:: Scope ;
10
+ use failure:: format_err;
9
11
use jobserver:: { Acquired , HelperThread } ;
10
12
use log:: { debug, info, trace} ;
11
13
@@ -490,7 +492,13 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
490
492
rmeta_required : Cell :: new ( rmeta_required) ,
491
493
_marker : marker:: PhantomData ,
492
494
} ;
493
- let res = job. run ( & state) ;
495
+
496
+ let mut sender = FinishOnDrop {
497
+ tx : & my_tx,
498
+ id,
499
+ result : Err ( format_err ! ( "worker panicked" ) ) ,
500
+ } ;
501
+ sender. result = job. run ( & state) ;
494
502
495
503
// If the `rmeta_required` wasn't consumed but it was set
496
504
// previously, then we either have:
@@ -504,13 +512,28 @@ impl<'a, 'cfg> JobQueue<'a, 'cfg> {
504
512
// we'll just naturally abort the compilation operation but for 1
505
513
// we need to make sure that the metadata is flagged as produced so
506
514
// send a synthetic message here.
507
- if state. rmeta_required . get ( ) && res . is_ok ( ) {
515
+ if state. rmeta_required . get ( ) && sender . result . is_ok ( ) {
508
516
my_tx
509
517
. send ( Message :: Finish ( id, Artifact :: Metadata , Ok ( ( ) ) ) )
510
518
. unwrap ( ) ;
511
519
}
512
520
513
- my_tx. send ( Message :: Finish ( id, Artifact :: All , res) ) . unwrap ( ) ;
521
+ // Use a helper struct with a `Drop` implementation to guarantee
522
+ // that a `Finish` message is sent even if our job panics. We
523
+ // shouldn't panic unless there's a bug in Cargo, so we just need
524
+ // to make sure nothing hangs by accident.
525
+ struct FinishOnDrop < ' a > {
526
+ tx : & ' a Sender < Message > ,
527
+ id : u32 ,
528
+ result : CargoResult < ( ) > ,
529
+ }
530
+
531
+ impl Drop for FinishOnDrop < ' _ > {
532
+ fn drop ( & mut self ) {
533
+ let msg = mem:: replace ( & mut self . result , Ok ( ( ) ) ) ;
534
+ drop ( self . tx . send ( Message :: Finish ( self . id , Artifact :: All , msg) ) ) ;
535
+ }
536
+ }
514
537
} ;
515
538
516
539
if !cx. bcx . build_config . build_plan {
0 commit comments