diff options
| author | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-01-13 12:00:24 -0300 |
|---|---|---|
| committer | Janito Vaqueiro Ferreira Filho <janito@mullvad.net> | 2020-01-13 12:00:24 -0300 |
| commit | 8dabfcfc8950e9b249a10cf4ebd964f8685dc5dc (patch) | |
| tree | d5ec667e71457bd2934584db5bbe26b0074d4877 | |
| parent | b73ab60bb5bf94409a0b49f91b355de43c62c06c (diff) | |
| parent | 4ba5fcde44e30f2c59edb9457fdd4aa571a1feb0 (diff) | |
| download | mullvadvpn-8dabfcfc8950e9b249a10cf4ebd964f8685dc5dc.tar.xz mullvadvpn-8dabfcfc8950e9b249a10cf4ebd964f8685dc5dc.zip | |
Merge branch 'restart-service-on-daemon-crash'
| -rw-r--r-- | CHANGELOG.md | 1 | ||||
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt | 5 | ||||
| -rw-r--r-- | android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt | 26 | ||||
| -rw-r--r-- | mullvad-jni/src/lib.rs | 52 |
4 files changed, 71 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 2067af6894..82e677657a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -49,6 +49,7 @@ Line wrap the file at 100 chars. Th #### Android - Fix crash when starting the app right after quitting it. +- Restart background service if it stops responding. ### Security #### Windows diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt index c3b1661907..a175efc5ca 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadDaemon.kt @@ -20,6 +20,7 @@ class MullvadDaemon(val vpnService: MullvadVpnService) { var onKeygenEvent: ((KeygenEvent) -> Unit)? = null var onRelayListChange: ((RelayList) -> Unit)? = null var onTunnelStateChange: ((TunnelState) -> Unit)? = null + var onDaemonStopped: (() -> Unit)? = null init { System.loadLibrary("mullvad_jni") @@ -138,6 +139,10 @@ class MullvadDaemon(val vpnService: MullvadVpnService) { onTunnelStateChange?.invoke(event) } + private fun notifyDaemonStopped() { + onDaemonStopped?.invoke() + } + private fun finalize() { deinitialize() } diff --git a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt index f22094dfe9..6d8747f915 100644 --- a/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt +++ b/android/src/main/kotlin/net/mullvad/mullvadvpn/service/MullvadVpnService.kt @@ -34,8 +34,7 @@ class MullvadVpnService : TalpidVpnService() { override fun onRebind(intent: Intent) { if (isStopping) { - tearDown() - setUp() + restart() isStopping = false } } @@ -46,7 +45,6 @@ class MullvadVpnService : TalpidVpnService() { override fun onDestroy() { tearDown() - daemon.cancel() super.onDestroy() } @@ -72,6 +70,12 @@ class MullvadVpnService : TalpidVpnService() { onSettingsChange.subscribe { settings -> notificationManager.loggedIn = settings?.accountToken != null } + + onDaemonStopped = { + if (!isStopping) { + restart() + } + } } serviceNotifier.notify(ServiceInstance(daemon, connectionProxy, connectivityListener)) @@ -88,20 +92,28 @@ class MullvadVpnService : TalpidVpnService() { private fun stop() { isStopping = true + stopDaemon() + stopSelf() + } - serviceNotifier.notify(null) - + private fun stopDaemon() { if (daemon.isCompleted) { runBlocking { daemon.await().shutdown() } } else { daemon.cancel() } - - stopSelf() } private fun tearDown() { + serviceNotifier.notify(null) + stopDaemon() + connectionProxy.onDestroy() notificationManager.onDestroy() } + + private fun restart() { + tearDown() + setUp() + } } diff --git a/mullvad-jni/src/lib.rs b/mullvad-jni/src/lib.rs index 1a4a3e0da3..e8d8c92321 100644 --- a/mullvad-jni/src/lib.rs +++ b/mullvad-jni/src/lib.rs @@ -12,10 +12,10 @@ use crate::{ }; use jnix::{ jni::{ - objects::{JObject, JString, JValue}, + objects::{GlobalRef, JObject, JString, JValue}, signature::{JavaType, Primitive}, sys::{jboolean, jlong, JNI_FALSE, JNI_TRUE}, - JNIEnv, + JNIEnv, JavaVM, }, IntoJava, JnixEnv, }; @@ -161,10 +161,15 @@ fn spawn_daemon( android_context: AndroidContext, ) -> Result<DaemonCommandSender, Error> { let listener = JniEventListener::spawn(env, this).map_err(Error::SpawnJniEventListener)?; + let daemon_object = env + .new_global_ref(*this) + .map_err(Error::CreateGlobalReference)?; let (tx, rx) = mpsc::channel(); - thread::spawn( - move || match create_daemon(listener, log_dir, android_context) { + thread::spawn(move || { + let jvm = android_context.jvm.clone(); + + match create_daemon(listener, log_dir, android_context) { Ok(daemon) => { let _ = tx.send(Ok(daemon.command_sender())); match daemon.run() { @@ -175,8 +180,10 @@ fn spawn_daemon( Err(error) => { let _ = tx.send(Err(error)); } - }, - ); + } + + notify_daemon_stopped(jvm, daemon_object); + }); rx.recv().unwrap() } @@ -201,6 +208,39 @@ fn create_daemon( Ok(daemon) } +fn notify_daemon_stopped(jvm: Arc<JavaVM>, daemon_object: GlobalRef) { + match jvm.attach_current_thread_as_daemon() { + Ok(env) => { + let env = JnixEnv::from(env); + let class = env.get_class("net/mullvad/mullvadvpn/service/MullvadDaemon"); + let object = daemon_object.as_obj(); + let method_id = env + .get_method_id(&class, "notifyDaemonStopped", "()V") + .expect("Failed to get method ID for MullvadDaemon.notifyDaemonStopped"); + let return_type = JavaType::Primitive(Primitive::Void); + + let result = env.call_method_unchecked(object, method_id, return_type, &[]); + + match result { + Ok(JValue::Void) => {} + Ok(value) => panic!( + "Unexpected return value from MullvadDaemon.notifyDaemonStopped: {:?}", + value + ), + Err(error) => panic!( + "{}", + error + .display_chain_with_msg("Failed to call MullvadDaemon.notifyDaemonStopped") + ), + } + } + Err(error) => log::error!( + "{}", + error.display_chain_with_msg("Failed to notify that the daemon stopped") + ), + } +} + fn set_daemon_interface_address(env: &JnixEnv<'_>, this: &JObject<'_>, address: jlong) { let class = env.get_class("net/mullvad/mullvadvpn/service/MullvadDaemon"); let method_id = env |
