diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-09-15 21:47:30 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2019-09-15 21:47:30 -0300 |
| commit | 6719fc6d5f6a634781fe07d8bd7b8731c8d26e35 (patch) | |
| tree | 3a16e0b2e812fc258b3c8cedb4cf80d3206aa09f | |
| parent | ed527997886dad36671518b3bc888657e4a2b565 (diff) | |
| parent | e81403b62dc38918a5fd89086ed81fbd07fbb41e (diff) | |
| download | mullvadvpn-6719fc6d5f6a634781fe07d8bd7b8731c8d26e35.tar.xz mullvadvpn-6719fc6d5f6a634781fe07d8bd7b8731c8d26e35.zip | |
Merge branch 'handle-bad-file-descriptor'
| -rw-r--r-- | mullvad-jni/src/vpn_service_tun_provider.rs | 35 |
1 files changed, 31 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..49740f5e9f 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,39 @@ impl VpnServiceTunProvider { }) } - fn duplicate_tun(tun: &File) -> Result<RawFd, Error> { + fn get_tun_fd(&mut self, config: TunConfig) -> Result<RawFd, Error> { + for retry in 1..=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 ({}/{})", + retry, + MAX_PREPARE_TUN_ATTEMPTS + ); + } + _ => 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 +178,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)))?; |
