@@ -51,7 +51,7 @@ use std::borrow;
5151/// As sync::condvar, a mechanism for unlock-and-descheduling and signaling.
5252pub struct Condvar < ' a > {
5353 priv is_mutex : bool ,
54- priv failed : & ' a mut bool ,
54+ priv failed : & ' a bool ,
5555 priv cond : & ' a sync:: Condvar < ' a >
5656}
5757
@@ -226,7 +226,7 @@ impl<T:Send> MutexArc<T> {
226226 // not already unsafe. See borrow_rwlock, far below.
227227 ( & ( * state) . lock ) . lock ( || {
228228 check_poison ( true , ( * state) . failed ) ;
229- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
229+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
230230 blk ( & mut ( * state) . data )
231231 } )
232232 }
@@ -239,10 +239,10 @@ impl<T:Send> MutexArc<T> {
239239 let state = self . x . get ( ) ;
240240 ( & ( * state) . lock ) . lock_cond ( |cond| {
241241 check_poison ( true , ( * state) . failed ) ;
242- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
242+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
243243 blk ( & mut ( * state) . data ,
244244 & Condvar { is_mutex : true ,
245- failed : & mut ( * state) . failed ,
245+ failed : & ( * state) . failed ,
246246 cond : cond } )
247247 } )
248248 }
@@ -311,24 +311,28 @@ fn check_poison(is_mutex: bool, failed: bool) {
311311
312312#[ doc( hidden) ]
313313struct PoisonOnFail {
314- failed : * mut bool ,
314+ flag : * mut bool ,
315+ failed : bool ,
315316}
316317
317318impl Drop for PoisonOnFail {
318319 fn drop ( & mut self ) {
319320 unsafe {
320321 /* assert!(!*self.failed);
321322 -- might be false in case of cond.wait() */
322- if task:: failing ( ) {
323- * self . failed = true ;
323+ if ! self . failed && task:: failing ( ) {
324+ * self . flag = true ;
324325 }
325326 }
326327 }
327328}
328329
329- fn PoisonOnFail < ' r > ( failed : & ' r mut bool ) -> PoisonOnFail {
330- PoisonOnFail {
331- failed : failed
330+ impl PoisonOnFail {
331+ fn new < ' a > ( flag : & ' a mut bool ) -> PoisonOnFail {
332+ PoisonOnFail {
333+ flag : flag,
334+ failed : task:: failing ( )
335+ }
332336 }
333337}
334338
@@ -392,7 +396,7 @@ impl<T:Freeze + Send> RWArc<T> {
392396 let state = self . x . get ( ) ;
393397 ( * borrow_rwlock ( state) ) . write ( || {
394398 check_poison ( false , ( * state) . failed ) ;
395- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
399+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
396400 blk ( & mut ( * state) . data )
397401 } )
398402 }
@@ -407,10 +411,10 @@ impl<T:Freeze + Send> RWArc<T> {
407411 let state = self . x . get ( ) ;
408412 ( * borrow_rwlock ( state) ) . write_cond ( |cond| {
409413 check_poison ( false , ( * state) . failed ) ;
410- let _z = PoisonOnFail ( & mut ( * state) . failed ) ;
414+ let _z = PoisonOnFail :: new ( & mut ( * state) . failed ) ;
411415 blk ( & mut ( * state) . data ,
412416 & Condvar { is_mutex : false ,
413- failed : & mut ( * state) . failed ,
417+ failed : & ( * state) . failed ,
414418 cond : cond} )
415419 } )
416420 }
@@ -463,7 +467,7 @@ impl<T:Freeze + Send> RWArc<T> {
463467 blk ( RWWriteMode {
464468 data : & mut ( * state) . data ,
465469 token : write_mode,
466- poison : PoisonOnFail ( & mut ( * state) . failed )
470+ poison : PoisonOnFail :: new ( & mut ( * state) . failed )
467471 } )
468472 } )
469473 }
@@ -563,7 +567,7 @@ impl<'a, T:Freeze + Send> RWWriteMode<'a, T> {
563567 unsafe {
564568 let cvar = Condvar {
565569 is_mutex : false ,
566- failed : & mut * poison. failed ,
570+ failed : & * poison. flag ,
567571 cond : cond
568572 } ;
569573 blk ( data, & cvar)
@@ -714,6 +718,25 @@ mod tests {
714718 }
715719 }
716720
721+ #[ test]
722+ fn test_mutex_arc_access_in_unwind ( ) {
723+ let arc = MutexArc :: new ( 1 i) ;
724+ let arc2 = arc. clone ( ) ;
725+ task:: try :: < ( ) > ( proc ( ) {
726+ struct Unwinder {
727+ i : MutexArc < int >
728+ }
729+ impl Drop for Unwinder {
730+ fn drop ( & mut self ) {
731+ self . i . access ( |num| * num += 1 ) ;
732+ }
733+ }
734+ let _u = Unwinder { i : arc2 } ;
735+ fail ! ( ) ;
736+ } ) ;
737+ assert_eq ! ( 2 , arc. access( |n| * n) ) ;
738+ }
739+
717740 #[ test] #[ should_fail]
718741 fn test_rw_arc_poison_wr ( ) {
719742 let arc = RWArc :: new ( 1 ) ;
@@ -840,6 +863,26 @@ mod tests {
840863 assert_eq ! ( * num, 10 ) ;
841864 } )
842865 }
866+
867+ #[ test]
868+ fn test_rw_arc_access_in_unwind ( ) {
869+ let arc = RWArc :: new ( 1 i) ;
870+ let arc2 = arc. clone ( ) ;
871+ task:: try :: < ( ) > ( proc ( ) {
872+ struct Unwinder {
873+ i : RWArc < int >
874+ }
875+ impl Drop for Unwinder {
876+ fn drop ( & mut self ) {
877+ self . i . write ( |num| * num += 1 ) ;
878+ }
879+ }
880+ let _u = Unwinder { i : arc2 } ;
881+ fail ! ( ) ;
882+ } ) ;
883+ assert_eq ! ( 2 , arc. read( |n| * n) ) ;
884+ }
885+
843886 #[ test]
844887 fn test_rw_downgrade ( ) {
845888 // (1) A downgrader gets in write mode and does cond.wait.
0 commit comments