1 use crate::runtime::tests::loom_oneshot as oneshot;
2 use crate::runtime::Builder;
3 use crate::task::LocalSet;
4 
5 use std::task::Poll;
6 
7 /// Waking a runtime will attempt to push a task into a queue of notifications
8 /// in the runtime, however the tasks in such a queue usually have a reference
9 /// to the runtime itself. This means that if they are not properly removed at
10 /// runtime shutdown, this will cause a memory leak.
11 ///
12 /// This test verifies that waking something during shutdown of a LocalSet does
13 /// not result in tasks lingering in the queue once shutdown is complete. This
14 /// is verified using loom's leak finder.
15 #[test]
16 fn wake_during_shutdown() {
17     loom::model(|| {
18         let rt = Builder::new_current_thread().build().unwrap();
19         let ls = LocalSet::new();
20 
21         let (send, recv) = oneshot::channel();
22 
23         ls.spawn_local(async move {
24             let mut send = Some(send);
25 
26             let () = futures::future::poll_fn(|cx| {
27                 if let Some(send) = send.take() {
28                     send.send(cx.waker().clone());
29                 }
30 
31                 Poll::Pending
32             })
33             .await;
34         });
35 
36         let handle = loom::thread::spawn(move || {
37             let waker = recv.recv();
38             waker.wake();
39         });
40 
41         ls.block_on(&rt, crate::task::yield_now());
42 
43         drop(ls);
44         handle.join().unwrap();
45         drop(rt);
46     });
47 }
48