diff options
author | Émile Grégoire <eg@emilegregoire.ca> | 2020-07-28 23:43:19 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-07-28 20:43:19 -0700 |
commit | 646fbae76535e397ef79dbcaacb945d4c829f666 (patch) | |
tree | 49c00b3825463cae83eef0e1b65ee3d8266980c3 /tokio/src/park | |
parent | 1562bb314482215eb7517e6b8b8bdecbacf10e79 (diff) |
rt: fix potential leak during runtime shutdown (#2649)
JoinHandle of threads created by the pool are now tracked and properly joined at
shutdown. If the thread does not return within the timeout, then it's not joined and
left to the OS for cleanup.
Also, break a cycle between wakers held by the timer and the runtime.
Fixes #2641, #2535
Diffstat (limited to 'tokio/src/park')
-rw-r--r-- | tokio/src/park/either.rs | 7 | ||||
-rw-r--r-- | tokio/src/park/mod.rs | 3 | ||||
-rw-r--r-- | tokio/src/park/thread.rs | 12 |
3 files changed, 22 insertions, 0 deletions
diff --git a/tokio/src/park/either.rs b/tokio/src/park/either.rs index 67f1e172..c66d1213 100644 --- a/tokio/src/park/either.rs +++ b/tokio/src/park/either.rs @@ -36,6 +36,13 @@ where Either::B(b) => b.park_timeout(duration).map_err(Either::B), } } + + fn shutdown(&mut self) { + match self { + Either::A(a) => a.shutdown(), + Either::B(b) => b.shutdown(), + } + } } impl<A, B> Unpark for Either<A, B> diff --git a/tokio/src/park/mod.rs b/tokio/src/park/mod.rs index 04d3051d..2cfef8c2 100644 --- a/tokio/src/park/mod.rs +++ b/tokio/src/park/mod.rs @@ -88,6 +88,9 @@ pub(crate) trait Park { /// an implementation detail. Refer to the documentation for the specific /// `Park` implementation fn park_timeout(&mut self, duration: Duration) -> Result<(), Self::Error>; + + /// Release all resources holded by the parker for proper leak-free shutdown + fn shutdown(&mut self); } /// Unblock a thread blocked by the associated `Park` instance. diff --git a/tokio/src/park/thread.rs b/tokio/src/park/thread.rs index 2e2397c7..44174d35 100644 --- a/tokio/src/park/thread.rs +++ b/tokio/src/park/thread.rs @@ -65,6 +65,10 @@ impl Park for ParkThread { self.inner.park_timeout(duration); Ok(()) } + + fn shutdown(&mut self) { + self.inner.shutdown(); + } } // ==== impl Inner ==== @@ -188,6 +192,10 @@ impl Inner { self.condvar.notify_one() } + + fn shutdown(&self) { + self.condvar.notify_all(); + } } impl Default for ParkThread { @@ -259,6 +267,10 @@ cfg_block_on! { self.with_current(|park_thread| park_thread.inner.park_timeout(duration))?; Ok(()) } + + fn shutdown(&mut self) { + let _ = self.with_current(|park_thread| park_thread.inner.shutdown()); + } } |