Commit 3bb74625 authored by Mygod's avatar Mygod

Refine #594, again

parent 8fa2e60c
......@@ -39,67 +39,59 @@
package com.github.shadowsocks
import java.io.{IOException, InputStream, OutputStream}
import java.lang.System.currentTimeMillis
import java.util.concurrent.Semaphore
import android.util.Log
import java.io.IOException
import java.io.InputStream
import java.io.OutputStream
import java.util.concurrent.CountDownLatch
import java.util.concurrent.atomic.AtomicReference
import collection.JavaConversions._
import scala.collection.JavaConversions._
/**
* @author ayanamist@gmail.com
*/
class GuardedProcess (cmd: Seq[String], onRestartCallback: Runnable = null) extends Process {
class GuardedProcess(cmd: Seq[String]) extends Process {
private val TAG = classOf[GuardedProcess].getSimpleName
@volatile private var guardThread: Thread = null
@volatile private var isDestroyed: Boolean = false
@volatile private var process: Process = null
@volatile private var guardThread: Thread = _
@volatile private var isDestroyed: Boolean = _
@volatile private var process: Process = _
def start(): GuardedProcess = {
def start(onRestartCallback: () => Unit = null): GuardedProcess = {
val semaphore = new Semaphore(1)
semaphore.acquire
var ioException: IOException = null
val atomicIoException = new AtomicReference[IOException](null)
val countDownLatch = new CountDownLatch(1)
guardThread = new Thread(() => {
try {
var callback: () => Unit = null
while (!isDestroyed) {
Log.i(TAG, "start process: " + cmd)
val startTime = currentTimeMillis
guardThread = new Thread(new Runnable() {
override def run() {
try {
while (!isDestroyed) {
Log.i(TAG, "start process: " + cmd)
val startTime = java.lang.System.currentTimeMillis
process = new ProcessBuilder(cmd).redirectErrorStream(true).start
process = new ProcessBuilder(cmd).redirectErrorStream(true).start
if (onRestartCallback != null && countDownLatch.getCount <= 0) {
onRestartCallback.run()
}
if (callback == null) callback = onRestartCallback else callback()
countDownLatch.countDown()
process.waitFor
semaphore.release
process.waitFor
if (java.lang.System.currentTimeMillis - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + cmd)
return
}
if (currentTimeMillis - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + cmd)
isDestroyed = true
}
} catch {
case ignored: InterruptedException =>
Log.i(TAG, "thread interrupt, destroy process: " + cmd)
process.destroy()
case e: IOException =>
atomicIoException.compareAndSet(null, e)
} finally {
countDownLatch.countDown()
}
}
} catch {
case ignored: InterruptedException =>
Log.i(TAG, "thread interrupt, destroy process: " + cmd)
process.destroy()
case e: IOException => ioException = e
} finally semaphore.release
}, "GuardThread-" + cmd)
guardThread.start()
countDownLatch.await()
semaphore.acquire
val ioException: IOException = atomicIoException.get
if (ioException != null) {
throw ioException
}
......@@ -111,32 +103,18 @@ class GuardedProcess (cmd: Seq[String], onRestartCallback: Runnable = null) exte
isDestroyed = true
guardThread.interrupt()
process.destroy()
try {
guardThread.join()
}
catch {
try guardThread.join() catch {
case ignored: InterruptedException =>
}
}
def exitValue: Int = {
throw new UnsupportedOperationException
}
def getErrorStream: InputStream = {
throw new UnsupportedOperationException
}
def getInputStream: InputStream = {
throw new UnsupportedOperationException
}
def getOutputStream: OutputStream = {
throw new UnsupportedOperationException
}
def exitValue: Int = throw new UnsupportedOperationException
def getErrorStream: InputStream = throw new UnsupportedOperationException
def getInputStream: InputStream = throw new UnsupportedOperationException
def getOutputStream: OutputStream = throw new UnsupportedOperationException
@throws(classOf[InterruptedException])
def waitFor: Int = {
def waitFor = {
guardThread.join()
0
}
......
......@@ -44,18 +44,16 @@ import java.lang.Process
import java.util.Locale
import android.content._
import android.content.pm.PackageManager.NameNotFoundException
import android.content.pm.{PackageInfo, PackageManager}
import android.net.VpnService
import android.os._
import android.util.Log
import android.widget.Toast
import android.content.pm.PackageManager.NameNotFoundException
import com.github.shadowsocks.aidl.Config
import com.github.shadowsocks.utils._
import org.apache.commons.net.util.SubnetUtils
import scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer
class ShadowsocksVpnService extends VpnService with BaseService {
......@@ -434,11 +432,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (BuildConfig.DEBUG) Log.d(TAG, cmd)
tun2socksProcess = new GuardedProcess(cmd.split(" ").toSeq, new Runnable {
override def run(): Unit = {
sendFd(fd)
}
}).start()
tun2socksProcess = new GuardedProcess(cmd.split(" ").toSeq).start(() => sendFd(fd))
fd
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment