summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-09-15 21:47:30 -0300
committerJanito Vaqueiro Ferreira Filho <janito@mullvad.net>2019-09-15 21:47:30 -0300
commit6719fc6d5f6a634781fe07d8bd7b8731c8d26e35 (patch)
tree3a16e0b2e812fc258b3c8cedb4cf80d3206aa09f
parented527997886dad36671518b3bc888657e4a2b565 (diff)
parente81403b62dc38918a5fd89086ed81fbd07fbb41e (diff)
downloadmullvadvpn-6719fc6d5f6a634781fe07d8bd7b8731c8d26e35.tar.xz
mullvadvpn-6719fc6d5f6a634781fe07d8bd7b8731c8d26e35.zip
Merge branch 'handle-bad-file-descriptor'
-rw-r--r--mullvad-jni/src/vpn_service_tun_provider.rs35
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)))?;