summaryrefslogtreecommitdiffhomepage
path: root/talpid-core/src
diff options
context:
space:
mode:
authorDavid Lönnhager <david.l@mullvad.net>2023-01-17 15:55:43 +0100
committerDavid Lönnhager <david.l@mullvad.net>2023-01-18 16:43:23 +0100
commitd23a843239cc218d59ab5664f17559fde49bf34f (patch)
tree87cd0c3f2f00d8de0fde634e8da5de4bfe37e42c /talpid-core/src
parent17b5b5689b70cc1d750ddf7853aa2a4350522b63 (diff)
downloadmullvadvpn-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.rs22
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;