From 07a48bc20bec32ab427ce67c04ada9a0ddf8550b Mon Sep 17 00:00:00 2001 From: Max Lv Date: Wed, 6 Dec 2017 02:42:59 -0800 Subject: [PATCH] Refine the local socket closing logic --- .../com/github/shadowsocks/JniHelper.java | 1 + core/src/main/jni/jni-helper.cpp | 6 ++++ .../shadowsocks/bg/LocalSocketListener.kt | 36 +++++++++++++------ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/core/src/main/java/com/github/shadowsocks/JniHelper.java b/core/src/main/java/com/github/shadowsocks/JniHelper.java index 2cc41a34..14a8e914 100755 --- a/core/src/main/java/com/github/shadowsocks/JniHelper.java +++ b/core/src/main/java/com/github/shadowsocks/JniHelper.java @@ -70,4 +70,5 @@ public class JniHelper { private static native Object getExitValueMutex(Process process); public static native int sendFd(int fd, String path); public static native void close(int fd); + public static native void unlink(String path); } diff --git a/core/src/main/jni/jni-helper.cpp b/core/src/main/jni/jni-helper.cpp index 6c56cb52..9730879a 100644 --- a/core/src/main/jni/jni-helper.cpp +++ b/core/src/main/jni/jni-helper.cpp @@ -72,6 +72,12 @@ JNIEXPORT void JNICALL Java_com_github_shadowsocks_JniHelper_close(JNIEnv *env, close(fd); } +JNIEXPORT void JNICALL Java_com_github_shadowsocks_JniHelper_unlink(JNIEnv *env, jobject thiz, jstring path) { + const char *sock_str = env->GetStringUTFChars(path, 0); + unlink(sock_str); + env->ReleaseStringUTFChars(path, sock_str); +} + JNIEXPORT jint JNICALL Java_com_github_shadowsocks_JniHelper_sendFd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) { int fd; diff --git a/mobile/src/main/java/com/github/shadowsocks/bg/LocalSocketListener.kt b/mobile/src/main/java/com/github/shadowsocks/bg/LocalSocketListener.kt index d3afb592..753d2065 100644 --- a/mobile/src/main/java/com/github/shadowsocks/bg/LocalSocketListener.kt +++ b/mobile/src/main/java/com/github/shadowsocks/bg/LocalSocketListener.kt @@ -25,6 +25,7 @@ import android.net.LocalSocket import android.net.LocalSocketAddress import android.util.Log import com.github.shadowsocks.App.Companion.app +import com.github.shadowsocks.JniHelper import java.io.File import java.io.IOException import java.util.concurrent.atomic.AtomicReference @@ -35,26 +36,30 @@ abstract class LocalSocketListener(private val tag: String) : Thread() { } protected abstract val socketFile: File - private val serverSocket = AtomicReference() + private val localSocket = AtomicReference() /** * Inherited class do not need to close input/output streams as they will be closed automatically. */ protected abstract fun accept(socket: LocalSocket) override fun run() { - socketFile.delete() - try { - val localSocket = LocalSocket() - localSocket.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM)) - serverSocket.set(LocalServerSocket(localSocket.fileDescriptor)) + + JniHelper.unlink(socketFile.absolutePath) + Thread.sleep(1000) // trick to close the previous local socket safely + + val serverSocket: LocalServerSocket? = try { + val ls = LocalSocket() + localSocket.set(ls) + ls.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM)) + LocalServerSocket(ls.fileDescriptor) } catch (e: IOException) { Log.e(tag, "unable to bind", e) - return + null } + while (true) { - val serverSocket = serverSocket.get() ?: return try { - val socket = serverSocket.accept() + val socket = serverSocket?.accept() ?: break try { accept(socket) @@ -73,13 +78,22 @@ abstract class LocalSocketListener(private val tag: String) : Thread() { } catch (e: IOException) { Log.e(tag, "Error when accept socket", e) app.track(e) - return + break } } + + try { + serverSocket?.close() + } catch (e: IOException) { + Log.e(tag, "Error when closing socket", e) + app.track(e) + } + + Log.d(tag, "thread exit") } fun stopThread() { - val old = serverSocket.getAndSet(null) ?: return + val old = localSocket.getAndSet(null) ?: return try { old.close() } catch (_: Exception) { } // ignore