@@ -91,8 +91,8 @@ use super::FileLock;
9191use crate :: CargoResult ;
9292use crate :: GlobalContext ;
9393use anyhow:: Context as _;
94- use std:: cell:: RefCell ;
9594use std:: io;
95+ use std:: sync:: Mutex ;
9696
9797/// The style of lock to acquire.
9898#[ derive( Copy , Clone , Debug , PartialEq ) ]
@@ -435,7 +435,11 @@ pub struct CacheLock<'lock> {
435435impl Drop for CacheLock < ' _ > {
436436 fn drop ( & mut self ) {
437437 use CacheLockMode :: * ;
438- let mut state = self . locker . state . borrow_mut ( ) ;
438+ let mut state = match self . locker . state . lock ( ) {
439+ Ok ( result) => result,
440+ // we should release the cache even if a thread panicked while holding a lock
441+ Err ( poison) => poison. into_inner ( ) ,
442+ } ;
439443 match self . mode {
440444 Shared => {
441445 state. mutate_lock . decrement ( ) ;
@@ -472,24 +476,25 @@ pub struct CacheLocker {
472476 ///
473477 /// [`CacheLocker`] uses interior mutability because it is stuffed inside
474478 /// [`GlobalContext`], which does not allow mutation.
475- state : RefCell < CacheState > ,
479+ state : Mutex < CacheState > ,
476480}
477481
478482impl CacheLocker {
479483 /// Creates a new `CacheLocker`.
480484 pub fn new ( ) -> CacheLocker {
481485 CacheLocker {
482- state : RefCell :: new ( CacheState {
486+ state : CacheState {
483487 cache_lock : RecursiveLock :: new ( CACHE_LOCK_NAME ) ,
484488 mutate_lock : RecursiveLock :: new ( MUTATE_NAME ) ,
485- } ) ,
489+ }
490+ . into ( ) ,
486491 }
487492 }
488493
489494 /// Acquires a lock with the given mode, possibly blocking if another
490495 /// cargo is holding the lock.
491496 pub fn lock ( & self , gctx : & GlobalContext , mode : CacheLockMode ) -> CargoResult < CacheLock < ' _ > > {
492- let mut state = self . state . borrow_mut ( ) ;
497+ let mut state = self . state . lock ( ) . unwrap ( ) ;
493498 let _ = state. lock ( gctx, mode, Blocking ) ?;
494499 Ok ( CacheLock { mode, locker : self } )
495500 }
@@ -501,7 +506,7 @@ impl CacheLocker {
501506 gctx : & GlobalContext ,
502507 mode : CacheLockMode ,
503508 ) -> CargoResult < Option < CacheLock < ' _ > > > {
504- let mut state = self . state . borrow_mut ( ) ;
509+ let mut state = self . state . lock ( ) . unwrap ( ) ;
505510 if state. lock ( gctx, mode, NonBlocking ) ? == LockAcquired {
506511 Ok ( Some ( CacheLock { mode, locker : self } ) )
507512 } else {
@@ -519,7 +524,7 @@ impl CacheLocker {
519524 /// `DownloadExclusive` will return true if a `MutateExclusive` lock is
520525 /// held since they overlap.
521526 pub fn is_locked ( & self , mode : CacheLockMode ) -> bool {
522- let state = self . state . borrow ( ) ;
527+ let state = self . state . lock ( ) . unwrap ( ) ;
523528 match (
524529 mode,
525530 state. cache_lock . count ,
0 commit comments