Prevent blocking on errorStream

This commit is contained in:
Mygod
2018-02-24 00:54:40 -08:00
parent ee5197cadc
commit b9511eedbe
2 changed files with 27 additions and 20 deletions

View File

@@ -43,6 +43,17 @@ fun NetworkInterface.formatAddresses() =
})) }))
.joinToString("\n") .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_TAG = "NoisySU"
private const val NOISYSU_SUFFIX = "SUCCESS\n" private const val NOISYSU_SUFFIX = "SUCCESS\n"
fun loggerSuStream(command: String): InputStream? { fun loggerSuStream(command: String): InputStream? {
@@ -55,11 +66,12 @@ fun loggerSuStream(command: String): InputStream? {
e.printStackTrace() e.printStackTrace()
return null return null
} }
try { thread("LoggerSU-error") {
val err = process.errorStream.bufferedReader().readText() val err = process.errorStream.bufferedReader().readText()
if (err.isNotBlank()) Log.e(NOISYSU_TAG, err) if (err.isNotBlank()) {
} catch (e: IOException) { Log.e(NOISYSU_TAG, err)
e.printStackTrace() app.toast(R.string.noisy_su_failure)
}
} }
return process.inputStream return process.inputStream
} }

View File

@@ -5,6 +5,7 @@ import android.util.Log
import be.mygod.vpnhotspot.App.Companion.app import be.mygod.vpnhotspot.App.Companion.app
import be.mygod.vpnhotspot.R import be.mygod.vpnhotspot.R
import be.mygod.vpnhotspot.debugLog import be.mygod.vpnhotspot.debugLog
import be.mygod.vpnhotspot.thread
import java.io.InterruptedIOException import java.io.InterruptedIOException
class IpNeighbourMonitor private constructor() { class IpNeighbourMonitor private constructor() {
@@ -32,17 +33,6 @@ class IpNeighbourMonitor private constructor() {
val process = monitor.monitor val process = monitor.monitor
if (process != null) thread(TAG + "-killer") { process.destroy() } 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 { interface Callback {
@@ -56,13 +46,13 @@ class IpNeighbourMonitor private constructor() {
private var monitor: Process? = null private var monitor: Process? = null
init { init {
thread(name = TAG + "-input") { thread(TAG + "-input") {
// monitor may get rejected by SELinux // monitor may get rejected by SELinux
val monitor = ProcessBuilder("sh", "-c", "ip monitor neigh || su -c ip monitor neigh") val monitor = ProcessBuilder("sh", "-c", "ip monitor neigh || su -c ip monitor neigh")
.redirectErrorStream(true) .redirectErrorStream(true)
.start() .start()
this.monitor = monitor this.monitor = monitor
thread(name = TAG + "-error") { thread(TAG + "-error") {
try { try {
monitor.errorStream.bufferedReader().forEachLine { Log.e(TAG, it) } monitor.errorStream.bufferedReader().forEachLine { Log.e(TAG, it) }
} catch (ignore: InterruptedIOException) { } } 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") val process = ProcessBuilder("ip", "neigh")
.redirectErrorStream(true) .redirectErrorStream(true)
.start() .start()
process.waitFor() process.waitFor()
thread(TAG + "-flush-error") {
val err = process.errorStream.bufferedReader().readText() val err = process.errorStream.bufferedReader().readText()
if (err.isNotBlank()) Log.e(TAG, err) if (err.isNotBlank()) {
Log.e(TAG, err)
app.toast(R.string.noisy_su_failure)
}
}
process.inputStream.bufferedReader().useLines { process.inputStream.bufferedReader().useLines {
synchronized(neighbours) { synchronized(neighbours) {
neighbours.clear() neighbours.clear()