diff options
| author | David Lönnhager <david.l@mullvad.net> | 2023-01-17 15:55:43 +0100 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2023-01-18 16:43:23 +0100 |
| commit | d23a843239cc218d59ab5664f17559fde49bf34f (patch) | |
| tree | 87cd0c3f2f00d8de0fde634e8da5de4bfe37e42c /talpid-core/src | |
| parent | 17b5b5689b70cc1d750ddf7853aa2a4350522b63 (diff) | |
| download | mullvadvpn-d23a843239cc218d59ab5664f17559fde49bf34f.tar.xz mullvadvpn-d23a843239cc218d59ab5664f17559fde49bf34f.zip | |
Fix deadlock in set_tunnel_addresses
Diffstat (limited to 'talpid-core/src')
| -rw-r--r-- | talpid-core/src/split_tunnel/windows/mod.rs | 22 |
1 files changed, 18 insertions, 4 deletions
diff --git a/talpid-core/src/split_tunnel/windows/mod.rs b/talpid-core/src/split_tunnel/windows/mod.rs index 83fb4727e7..9e091e8f01 100644 --- a/talpid-core/src/split_tunnel/windows/mod.rs +++ b/talpid-core/src/split_tunnel/windows/mod.rs @@ -15,7 +15,7 @@ use std::{ path::{Path, PathBuf}, sync::{ atomic::{AtomicBool, Ordering}, - mpsc as sync_mpsc, Arc, Mutex, RwLock, Weak, + mpsc as sync_mpsc, Arc, Mutex, MutexGuard, RwLock, Weak, }, time::Duration, }; @@ -639,7 +639,7 @@ impl SplitTunnel { self._route_change_callback = None; let moved_context_mutex = context_mutex.clone(); - let mut context = context_mutex.lock().unwrap(); + let context = context_mutex.lock().unwrap(); let callback = self .runtime .block_on( @@ -653,15 +653,29 @@ impl SplitTunnel { })), ) .map(Some) + // NOTE: This cannot fail if a callback is created. If that assumption is wrong, this + // could deadlock if the dropped callback is invoked (see `init_context`). .map_err(|_| Error::RegisterRouteChangeCallback)?; - context.initialize_internet_addresses()?; - context.register_ips()?; + Self::init_context(context)?; self._route_change_callback = callback; Ok(()) } + fn init_context( + mut context: MutexGuard<'_, SplitTunnelDefaultRouteChangeHandlerContext>, + ) -> Result<(), Error> { + // NOTE: This should remain a separate function. Dropping the context after `callback` + // causes a deadlock if `split_tunnel_default_route_change_handler` is called at the same + // time (i.e. if a route change has occurred), since it waits on the context and + // `CallbackHandle::drop` also waits for `split_tunnel_default_route_change_handler` + // to complete. + + context.initialize_internet_addresses()?; + context.register_ips() + } + /// Instructs the driver to stop redirecting tunnel traffic and INADDR_ANY. pub fn clear_tunnel_addresses(&mut self) -> Result<(), Error> { self._route_change_callback = None; |
