From b9511eedbe27f1b201ba94a336fe645b1315cb22 Mon Sep 17 00:00:00 2001 From: Mygod Date: Sat, 24 Feb 2018 00:54:40 -0800 Subject: [PATCH] Prevent blocking on errorStream --- .../main/java/be/mygod/vpnhotspot/Utils.kt | 20 +++++++++++--- .../vpnhotspot/net/IpNeighbourMonitor.kt | 27 ++++++++----------- 2 files changed, 27 insertions(+), 20 deletions(-) diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt index fefca583..fa9cd819 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/Utils.kt @@ -43,6 +43,17 @@ fun NetworkInterface.formatAddresses() = })) .joinToString("\n") +/** + * Wrapper for kotlin.concurrent.thread that silences uncaught exceptions. + */ +fun thread(name: String? = null, start: Boolean = true, isDaemon: Boolean = false, + contextClassLoader: ClassLoader? = null, priority: Int = -1, block: () -> Unit): Thread { + val thread = kotlin.concurrent.thread(false, isDaemon, contextClassLoader, name, priority, block) + thread.setUncaughtExceptionHandler { _, _ -> app.toast(R.string.noisy_su_failure) } + if (start) thread.start() + return thread +} + private const val NOISYSU_TAG = "NoisySU" private const val NOISYSU_SUFFIX = "SUCCESS\n" fun loggerSuStream(command: String): InputStream? { @@ -55,11 +66,12 @@ fun loggerSuStream(command: String): InputStream? { e.printStackTrace() return null } - try { + thread("LoggerSU-error") { val err = process.errorStream.bufferedReader().readText() - if (err.isNotBlank()) Log.e(NOISYSU_TAG, err) - } catch (e: IOException) { - e.printStackTrace() + if (err.isNotBlank()) { + Log.e(NOISYSU_TAG, err) + app.toast(R.string.noisy_su_failure) + } } return process.inputStream } diff --git a/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbourMonitor.kt b/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbourMonitor.kt index 65061fc3..81f6f20b 100644 --- a/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbourMonitor.kt +++ b/mobile/src/main/java/be/mygod/vpnhotspot/net/IpNeighbourMonitor.kt @@ -5,6 +5,7 @@ import android.util.Log import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.debugLog +import be.mygod.vpnhotspot.thread import java.io.InterruptedIOException class IpNeighbourMonitor private constructor() { @@ -32,17 +33,6 @@ class IpNeighbourMonitor private constructor() { val process = monitor.monitor if (process != null) thread(TAG + "-killer") { process.destroy() } } - - /** - * Wrapper for kotlin.concurrent.thread that silences uncaught exceptions. - */ - private fun thread(name: String? = null, start: Boolean = true, isDaemon: Boolean = false, - contextClassLoader: ClassLoader? = null, priority: Int = -1, block: () -> Unit): Thread { - val thread = kotlin.concurrent.thread(false, isDaemon, contextClassLoader, name, priority, block) - thread.setUncaughtExceptionHandler { _, _ -> app.toast(R.string.noisy_su_failure) } - if (start) thread.start() - return thread - } } interface Callback { @@ -56,13 +46,13 @@ class IpNeighbourMonitor private constructor() { private var monitor: Process? = null init { - thread(name = TAG + "-input") { + thread(TAG + "-input") { // monitor may get rejected by SELinux val monitor = ProcessBuilder("sh", "-c", "ip monitor neigh || su -c ip monitor neigh") .redirectErrorStream(true) .start() this.monitor = monitor - thread(name = TAG + "-error") { + thread(TAG + "-error") { try { monitor.errorStream.bufferedReader().forEachLine { Log.e(TAG, it) } } catch (ignore: InterruptedIOException) { } @@ -84,13 +74,18 @@ class IpNeighbourMonitor private constructor() { } } - fun flush() = thread(name = TAG + "-flush") { + fun flush() = thread(TAG + "-flush") { val process = ProcessBuilder("ip", "neigh") .redirectErrorStream(true) .start() process.waitFor() - val err = process.errorStream.bufferedReader().readText() - if (err.isNotBlank()) Log.e(TAG, err) + thread(TAG + "-flush-error") { + val err = process.errorStream.bufferedReader().readText() + if (err.isNotBlank()) { + Log.e(TAG, err) + app.toast(R.string.noisy_su_failure) + } + } process.inputStream.bufferedReader().useLines { synchronized(neighbours) { neighbours.clear()