diff options
| author | David Lönnhager <david.l@mullvad.net> | 2022-07-13 20:20:22 +0200 |
|---|---|---|
| committer | David Lönnhager <david.l@mullvad.net> | 2022-08-10 14:19:23 +0200 |
| commit | d7223f3ae2bfefb267317a8fe7e7c51524f63f94 (patch) | |
| tree | 4f648d2e8633be970528f54ba38e50dd6841cb15 | |
| parent | 97c55dc556ce9fca5039035070f3fb2af77c8801 (diff) | |
| download | mullvadvpn-d7223f3ae2bfefb267317a8fe7e7c51524f63f94.tar.xz mullvadvpn-d7223f3ae2bfefb267317a8fe7e7c51524f63f94.zip | |
Give up if DNS flush takes too long
| -rw-r--r-- | talpid-core/src/dns/windows/dnsapi.rs | 23 |
1 files changed, 22 insertions, 1 deletions
diff --git a/talpid-core/src/dns/windows/dnsapi.rs b/talpid-core/src/dns/windows/dnsapi.rs index 1c6b2c4fbc..4a0cf636e5 100644 --- a/talpid-core/src/dns/windows/dnsapi.rs +++ b/talpid-core/src/dns/windows/dnsapi.rs @@ -1,5 +1,5 @@ use once_cell::sync::OnceCell; -use std::{io, ptr}; +use std::{io, ptr, sync::mpsc, time::Duration}; use winapi::{ shared::minwindef::{BOOL, FALSE}, um::libloaderapi::{FreeLibrary, GetProcAddress, LoadLibraryExW, LOAD_LIBRARY_SEARCH_SYSTEM32}, @@ -8,6 +8,7 @@ use winapi::{ type FlushResolverCacheFn = unsafe extern "stdcall" fn() -> BOOL; static FLUSH_RESOLVER_CACHE: OnceCell<FlushResolverCacheFn> = OnceCell::new(); +static FLUSH_TIMEOUT: Duration = Duration::from_secs(5); /// Errors that can happen when configuring DNS on Windows. #[derive(err_derive::Error, Debug)] @@ -24,9 +25,29 @@ pub enum Error { /// Failed to flush the DNS cache. #[error(display = "Call to flush DNS cache failed")] FlushCache, + + /// Flushing the DNS cache timed out. + #[error(display = "Timeout while flushing DNS cache")] + Timeout, } pub fn flush_resolver_cache() -> Result<(), Error> { + let (tx, rx) = mpsc::channel(); + + std::thread::spawn(move || { + if tx.send(flush_resolver_cache_inner()).is_err() { + log::warn!("Flushing DNS cache completed (delayed)"); + } + }); + + match rx.recv_timeout(FLUSH_TIMEOUT) { + Ok(result) => result, + // TODO: Can this be a cancelled safely? + Err(_timeout_err) => Err(Error::Timeout), + } +} + +fn flush_resolver_cache_inner() -> Result<(), Error> { let flush_cache = FLUSH_RESOLVER_CACHE.get_or_try_init(|| { let handle = unsafe { LoadLibraryExW( |
