diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-09-13 20:19:29 +0000 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-09-15 15:51:05 +0000 |
| commit | 144f605291fde938c85df9b24ca125eb43e30d8b (patch) | |
| tree | d5b682f04abea63299a81b10a76d6c2b04a876ad | |
| parent | ed527997886dad36671518b3bc888657e4a2b565 (diff) | |
| download | mullvadvpn-144f605291fde938c85df9b24ca125eb43e30d8b.tar.xz mullvadvpn-144f605291fde938c85df9b24ca125eb43e30d8b.zip | |
Retry to create tunnel on bad file descriptor
| -rw-r--r-- | mullvad-jni/src/vpn_service_tun_provider.rs | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/mullvad-jni/src/vpn_service_tun_provider.rs b/mullvad-jni/src/vpn_service_tun_provider.rs index bcc52c53bf..3e15ee7e2e 100644 --- a/mullvad-jni/src/vpn_service_tun_provider.rs +++ b/mullvad-jni/src/vpn_service_tun_provider.rs @@ -14,6 +14,8 @@ use std::{ use talpid_core::tunnel::tun_provider::{Tun, TunConfig, TunProvider}; use talpid_types::BoxedError; +const MAX_PREPARE_TUN_ATTEMPTS: usize = 4; + /// Errors that occur while setting up VpnService tunnel. #[derive(Debug, err_derive::Error)] #[error(display = "Failed to set up the VpnService")] @@ -92,13 +94,35 @@ impl VpnServiceTunProvider { }) } - fn duplicate_tun(tun: &File) -> Result<RawFd, Error> { + fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> { + for _ in 0..MAX_PREPARE_TUN_ATTEMPTS { + let tun = self.prepare_tun(config.clone())?; + + match Self::duplicate_tun(tun) { + Ok(fd) => return Ok(fd), + Err(error) => match error.raw_os_error() { + Some(libc::EBADF) => { + self.active_tun = None; + + log::warn!("VpnService returned a bad file descriptor, retrying"); + } + _ => return Err(Error::DuplicateTunFd(error)), + }, + } + } + + Err(Error::DuplicateTunFd(io::Error::from_raw_os_error( + libc::EBADF, + ))) + } + + fn duplicate_tun(tun: &File) -> Result<RawFd, io::Error> { let tun_fd = unsafe { libc::dup(tun.as_raw_fd()) }; if tun_fd >= 0 { Ok(tun_fd) } else { - Err(Error::DuplicateTunFd(io::Error::last_os_error())) + Err(io::Error::last_os_error()) } } @@ -150,8 +174,7 @@ impl VpnServiceTunProvider { impl TunProvider for VpnServiceTunProvider { fn get_tun(&mut self, config: TunConfig) -> Result<Box<dyn Tun>, BoxedError> { - let tun = self.prepare_tun(config).map_err(BoxedError::new)?; - let tun_fd = Self::duplicate_tun(tun).map_err(BoxedError::new)?; + let tun_fd = self.get_tun_fd(config).map_err(BoxedError::new)?; let jvm = unsafe { JavaVM::from_raw(self.jvm.get_java_vm_pointer()) } .map_err(|cause| BoxedError::new(Error::CloneJavaVm(cause)))?; |
