Commit 3bb74625 authored by Mygod's avatar Mygod

Refine #594, again

parent 8fa2e60c
...@@ -39,67 +39,59 @@ ...@@ -39,67 +39,59 @@
package com.github.shadowsocks 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 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 * @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 private val TAG = classOf[GuardedProcess].getSimpleName
@volatile private var guardThread: Thread = null @volatile private var guardThread: Thread = _
@volatile private var isDestroyed: Boolean = false @volatile private var isDestroyed: Boolean = _
@volatile private var process: Process = null @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) guardThread = new Thread(() => {
val countDownLatch = new CountDownLatch(1) try {
var callback: () => Unit = null
while (!isDestroyed) {
Log.i(TAG, "start process: " + cmd)
val startTime = currentTimeMillis
guardThread = new Thread(new Runnable() { process = new ProcessBuilder(cmd).redirectErrorStream(true).start
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 if (callback == null) callback = onRestartCallback else callback()
if (onRestartCallback != null && countDownLatch.getCount <= 0) {
onRestartCallback.run()
}
countDownLatch.countDown() semaphore.release
process.waitFor process.waitFor
if (java.lang.System.currentTimeMillis - startTime < 1000) { if (currentTimeMillis - startTime < 1000) {
Log.w(TAG, "process exit too fast, stop guard: " + cmd) Log.w(TAG, "process exit too fast, stop guard: " + cmd)
return 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-" + cmd)
guardThread.start() guardThread.start()
countDownLatch.await() semaphore.acquire
val ioException: IOException = atomicIoException.get
if (ioException != null) { if (ioException != null) {
throw ioException throw ioException
} }
...@@ -111,32 +103,18 @@ class GuardedProcess (cmd: Seq[String], onRestartCallback: Runnable = null) exte ...@@ -111,32 +103,18 @@ class GuardedProcess (cmd: Seq[String], onRestartCallback: Runnable = null) exte
isDestroyed = true isDestroyed = true
guardThread.interrupt() guardThread.interrupt()
process.destroy() process.destroy()
try { try guardThread.join() catch {
guardThread.join()
}
catch {
case ignored: InterruptedException => case ignored: InterruptedException =>
} }
} }
def exitValue: Int = { def exitValue: Int = throw new UnsupportedOperationException
throw new UnsupportedOperationException def getErrorStream: InputStream = throw new UnsupportedOperationException
} def getInputStream: InputStream = throw new UnsupportedOperationException
def getOutputStream: OutputStream = throw new UnsupportedOperationException
def getErrorStream: InputStream = {
throw new UnsupportedOperationException
}
def getInputStream: InputStream = {
throw new UnsupportedOperationException
}
def getOutputStream: OutputStream = {
throw new UnsupportedOperationException
}
@throws(classOf[InterruptedException]) @throws(classOf[InterruptedException])
def waitFor: Int = { def waitFor = {
guardThread.join() guardThread.join()
0 0
} }
......
...@@ -44,18 +44,16 @@ import java.lang.Process ...@@ -44,18 +44,16 @@ import java.lang.Process
import java.util.Locale import java.util.Locale
import android.content._ import android.content._
import android.content.pm.PackageManager.NameNotFoundException
import android.content.pm.{PackageInfo, PackageManager} import android.content.pm.{PackageInfo, PackageManager}
import android.net.VpnService import android.net.VpnService
import android.os._ import android.os._
import android.util.Log import android.util.Log
import android.widget.Toast import android.widget.Toast
import android.content.pm.PackageManager.NameNotFoundException
import com.github.shadowsocks.aidl.Config import com.github.shadowsocks.aidl.Config
import com.github.shadowsocks.utils._ import com.github.shadowsocks.utils._
import org.apache.commons.net.util.SubnetUtils import org.apache.commons.net.util.SubnetUtils
import scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
class ShadowsocksVpnService extends VpnService with BaseService { class ShadowsocksVpnService extends VpnService with BaseService {
...@@ -434,11 +432,7 @@ class ShadowsocksVpnService extends VpnService with BaseService { ...@@ -434,11 +432,7 @@ class ShadowsocksVpnService extends VpnService with BaseService {
if (BuildConfig.DEBUG) Log.d(TAG, cmd) if (BuildConfig.DEBUG) Log.d(TAG, cmd)
tun2socksProcess = new GuardedProcess(cmd.split(" ").toSeq, new Runnable { tun2socksProcess = new GuardedProcess(cmd.split(" ").toSeq).start(() => sendFd(fd))
override def run(): Unit = {
sendFd(fd)
}
}).start()
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