Add 60 seconds timeout to RootSession

This commit is contained in:
Mygod
2018-09-07 10:36:01 +08:00
parent f72a3272cc
commit 9bc59ac270

View File

@@ -1,6 +1,8 @@
package be.mygod.vpnhotspot.util package be.mygod.vpnhotspot.util
import android.util.Log import android.util.Log
import androidx.core.os.postDelayed
import be.mygod.vpnhotspot.App.Companion.app
import com.crashlytics.android.Crashlytics import com.crashlytics.android.Crashlytics
import com.topjohnwu.superuser.Shell import com.topjohnwu.superuser.Shell
import java.util.* import java.util.*
@@ -8,27 +10,41 @@ import java.util.concurrent.locks.ReentrantLock
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
import kotlin.concurrent.withLock import kotlin.concurrent.withLock
class RootSession { class RootSession : AutoCloseable {
companion object { companion object {
const val TAG = "RootSession" private const val TAG = "RootSession"
const val INIT_CHECKPOINT = "$TAG initialized successfully" private const val INIT_CHECKPOINT = "$TAG initialized successfully"
private val monitor = ReentrantLock() private val monitor = ReentrantLock()
private fun onUnlock() {
if (monitor.holdCount == 1) instance?.startTimeout()
}
private fun unlock() {
onUnlock()
monitor.unlock()
}
private var instance: RootSession? = null private var instance: RootSession? = null
private fun ensureInstance(): RootSession { private fun ensureInstance(): RootSession {
var instance = instance var instance = instance
if (instance == null) instance = RootSession().also { RootSession.instance = it } if (instance == null || !instance.isAlive) instance = RootSession().also { RootSession.instance = it }
return instance return instance
} }
fun <T> use(operation: (RootSession) -> T) = monitor.withLock { operation(ensureInstance()) } fun <T> use(operation: (RootSession) -> T) = monitor.withLock {
val instance = ensureInstance()
instance.haltTimeout()
operation(instance).also { onUnlock() }
}
fun beginTransaction(): Transaction { fun beginTransaction(): Transaction {
monitor.lock() monitor.lock()
return try { val instance = try {
ensureInstance() ensureInstance()
} catch (e: RuntimeException) { } catch (e: RuntimeException) {
monitor.unlock() unlock()
throw e throw e
}.Transaction() }
instance.haltTimeout()
return instance.Transaction()
} }
} }
@@ -53,6 +69,14 @@ class RootSession {
checkOutput("echo", result, result.out.joinToString("\n").trim() != INIT_CHECKPOINT) checkOutput("echo", result, result.out.joinToString("\n").trim() != INIT_CHECKPOINT)
} }
private val isAlive get() = shell.isAlive
override fun close() {
shell.close()
if (instance == this) instance = null
}
private fun startTimeout() = app.handler.postDelayed(60 * 1000, this) { monitor.withLock { close() } }
private fun haltTimeout() = app.handler.removeCallbacksAndMessages(this)
/** /**
* Don't care about the results, but still sync. * Don't care about the results, but still sync.
*/ */
@@ -91,7 +115,7 @@ class RootSession {
} }
fun execQuiet(command: String) = this@RootSession.execQuiet(command) fun execQuiet(command: String) = this@RootSession.execQuiet(command)
fun commit() = monitor.unlock() fun commit() = unlock()
fun revert() { fun revert() {
if (revertCommands.isEmpty()) return if (revertCommands.isEmpty()) return
@@ -99,9 +123,10 @@ class RootSession {
monitor.lock() monitor.lock()
ensureInstance() ensureInstance()
} }
shell.haltTimeout()
revertCommands.forEach { shell.submit(it) } revertCommands.forEach { shell.submit(it) }
revertCommands.clear() revertCommands.clear()
monitor.unlock() // commit unlock() // commit
} }
} }
} }