11// ignore-windows: Concurrency on Windows is not supported yet.
2+
3+ //! Cause a panic in one thread while another thread is unwinding. This checks
4+ //! that separate threads have their own panicking state.
5+
26use std:: sync:: { Arc , Condvar , Mutex } ;
37use std:: thread:: { spawn, JoinHandle } ;
48
@@ -12,11 +16,12 @@ impl BlockOnDrop {
1216
1317impl Drop for BlockOnDrop {
1418 fn drop ( & mut self ) {
19+ eprintln ! ( "Thread 2 blocking on thread 1" ) ;
1520 let _ = self . 0 . take ( ) . unwrap ( ) . join ( ) ;
21+ eprintln ! ( "Thread 1 has exited" ) ;
1622 }
1723}
1824
19- /// Cause a panic in one thread while another thread is unwinding.
2025fn main ( ) {
2126 let t1_started_pair = Arc :: new ( ( Mutex :: new ( false ) , Condvar :: new ( ) ) ) ;
2227 let t2_started_pair = Arc :: new ( ( Mutex :: new ( false ) , Condvar :: new ( ) ) ) ;
@@ -28,6 +33,7 @@ fn main() {
2833 let t1_started_pair = t1_started_pair. clone ( ) ;
2934 let t1_continue_mutex = t1_continue_mutex. clone ( ) ;
3035 spawn ( move || {
36+ eprintln ! ( "Thread 1 starting, will block on mutex" ) ;
3137 let ( mutex, condvar) = & * t1_started_pair;
3238 * mutex. lock ( ) . unwrap ( ) = true ;
3339 condvar. notify_one ( ) ;
@@ -36,6 +42,16 @@ fn main() {
3642 panic ! ( "panic in thread 1" ) ;
3743 } )
3844 } ;
45+
46+ // Wait for thread 1 to signal it has started.
47+ let ( t1_started_mutex, t1_started_condvar) = & * t1_started_pair;
48+ let mut t1_started_guard = t1_started_mutex. lock ( ) . unwrap ( ) ;
49+ while !* t1_started_guard {
50+ t1_started_guard = t1_started_condvar. wait ( t1_started_guard) . unwrap ( ) ;
51+ }
52+ eprintln ! ( "Thread 1 reported it has started" ) ;
53+ // Thread 1 should now be blocked waiting on t1_continue_mutex.
54+
3955 let t2 = {
4056 let t2_started_pair = t2_started_pair. clone ( ) ;
4157 let block_on_drop = BlockOnDrop :: new ( t1) ;
@@ -50,24 +66,18 @@ fn main() {
5066 } )
5167 } ;
5268
53- // Wait for thread 1 to signal it has started.
54- let ( t1_started_mutex, t1_started_condvar) = & * t1_started_pair;
55- let mut t1_started_guard = t1_started_mutex. lock ( ) . unwrap ( ) ;
56- while !* t1_started_guard {
57- t1_started_guard = t1_started_condvar. wait ( t1_started_guard) . unwrap ( ) ;
58- }
59- // Thread 1 should now be blocked waiting on t1_continue_mutex.
60-
6169 // Wait for thread 2 to signal it has started.
6270 let ( t2_started_mutex, t2_started_condvar) = & * t2_started_pair;
6371 let mut t2_started_guard = t2_started_mutex. lock ( ) . unwrap ( ) ;
6472 while !* t2_started_guard {
6573 t2_started_guard = t2_started_condvar. wait ( t2_started_guard) . unwrap ( ) ;
6674 }
75+ eprintln ! ( "Thread 2 reported it has started" ) ;
6776 // Thread 2 should now have already panicked and be in the middle of
6877 // unwinding. It should now be blocked on joining thread 1.
6978
7079 // Unlock t1_continue_mutex, and allow thread 1 to proceed.
80+ eprintln ! ( "Unlocking mutex" ) ;
7181 drop ( t1_continue_guard) ;
7282 // Thread 1 will panic the next time it is scheduled. This will test the
7383 // behavior of interest to this test, whether Miri properly handles
@@ -77,4 +87,5 @@ fn main() {
7787 // already be blocked on joining thread 1, so thread 1 will be scheduled
7888 // to run next, as it is the only ready thread.
7989 assert ! ( t2. join( ) . is_err( ) ) ;
90+ eprintln ! ( "Thread 2 has exited" ) ;
8091}
0 commit comments