11use crate :: runtime:: { self , Runtime } ;
22
33use std:: sync:: Arc ;
4+ use std:: time:: Duration ;
45
56#[ test]
67fn blocking_shutdown ( ) {
@@ -75,7 +76,6 @@ fn spawn_mandatory_blocking_should_run_even_when_shutting_down_from_other_thread
7576
7677#[ test]
7778fn spawn_blocking_when_paused ( ) {
78- use std:: time:: Duration ;
7979 loom:: model ( || {
8080 let rt = crate :: runtime:: Builder :: new_current_thread ( )
8181 . enable_time ( )
@@ -94,6 +94,44 @@ fn spawn_blocking_when_paused() {
9494 } ) ;
9595}
9696
97+ #[ test]
98+ /// See <https://github.com/tokio-rs/tokio/pull/7922>
99+ fn spawn_blocking_then_shutdown ( ) {
100+ loom:: model ( || {
101+ let rt = crate :: runtime:: Builder :: new_current_thread ( )
102+ . max_blocking_threads ( 1 )
103+ . thread_keep_alive ( Duration :: from_secs ( 7200 ) ) // don't let the thread exit on its own
104+ . build ( )
105+ . unwrap ( ) ;
106+ let rt_hdl = rt. handle ( ) . clone ( ) ;
107+
108+ // Currently, there is no live blocking thread,
109+ // so `spawn_blocking` will spawn a new blocking thread.
110+ let jh0 = rt_hdl. spawn_blocking ( || { } ) ;
111+ loom:: future:: block_on ( jh0) . unwrap ( ) ;
112+
113+ // Now, there is a idle blocking threads park on the condvar,
114+ // so the following `spawn_blocking` will decrease the `num_idle_threads`
115+ // and then notify one of the idle threads to run the task.
116+
117+ // this will decrease the `num_idle_threads`
118+ // and then notify one of the idle threads to run the task.
119+ let jh3 = rt_hdl. spawn_blocking ( || { } ) ;
120+
121+ // shutdown the runtime, which also shutdown the blocking pool
122+ drop ( rt) ;
123+
124+ // loom will emulate two parrel operations:
125+ //
126+ // 1. the blocking thread is woken up on the condvar
127+ // 2. the main thread is waiting for the blocking thread to finish the task
128+ //
129+ // So, if the `num_idle_threads` is not counted correctly,
130+ // it will trigger the assertions inside the `Inner::run` function.
131+ let _ = loom:: future:: block_on ( jh3) ;
132+ } ) ;
133+ }
134+
97135fn mk_runtime ( num_threads : usize ) -> Runtime {
98136 runtime:: Builder :: new_multi_thread ( )
99137 . worker_threads ( num_threads)
0 commit comments