Commit 07a48bc2 authored by Max Lv's avatar Max Lv

Refine the local socket closing logic

parent f870093c
...@@ -70,4 +70,5 @@ public class JniHelper { ...@@ -70,4 +70,5 @@ public class JniHelper {
private static native Object getExitValueMutex(Process process); private static native Object getExitValueMutex(Process process);
public static native int sendFd(int fd, String path); public static native int sendFd(int fd, String path);
public static native void close(int fd); public static native void close(int fd);
public static native void unlink(String path);
} }
...@@ -72,6 +72,12 @@ JNIEXPORT void JNICALL Java_com_github_shadowsocks_JniHelper_close(JNIEnv *env, ...@@ -72,6 +72,12 @@ JNIEXPORT void JNICALL Java_com_github_shadowsocks_JniHelper_close(JNIEnv *env,
close(fd); 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 JNIEXPORT jint JNICALL
Java_com_github_shadowsocks_JniHelper_sendFd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) { Java_com_github_shadowsocks_JniHelper_sendFd(JNIEnv *env, jobject thiz, jint tun_fd, jstring path) {
int fd; int fd;
......
...@@ -25,6 +25,7 @@ import android.net.LocalSocket ...@@ -25,6 +25,7 @@ import android.net.LocalSocket
import android.net.LocalSocketAddress import android.net.LocalSocketAddress
import android.util.Log import android.util.Log
import com.github.shadowsocks.App.Companion.app import com.github.shadowsocks.App.Companion.app
import com.github.shadowsocks.JniHelper
import java.io.File import java.io.File
import java.io.IOException import java.io.IOException
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
...@@ -35,26 +36,30 @@ abstract class LocalSocketListener(private val tag: String) : Thread() { ...@@ -35,26 +36,30 @@ abstract class LocalSocketListener(private val tag: String) : Thread() {
} }
protected abstract val socketFile: File protected abstract val socketFile: File
private val serverSocket = AtomicReference<LocalServerSocket?>() private val localSocket = AtomicReference<LocalSocket?>()
/** /**
* Inherited class do not need to close input/output streams as they will be closed automatically. * Inherited class do not need to close input/output streams as they will be closed automatically.
*/ */
protected abstract fun accept(socket: LocalSocket) protected abstract fun accept(socket: LocalSocket)
override fun run() { override fun run() {
socketFile.delete()
try { JniHelper.unlink(socketFile.absolutePath)
val localSocket = LocalSocket() Thread.sleep(1000) // trick to close the previous local socket safely
localSocket.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
serverSocket.set(LocalServerSocket(localSocket.fileDescriptor)) val serverSocket: LocalServerSocket? = try {
val ls = LocalSocket()
localSocket.set(ls)
ls.bind(LocalSocketAddress(socketFile.absolutePath, LocalSocketAddress.Namespace.FILESYSTEM))
LocalServerSocket(ls.fileDescriptor)
} catch (e: IOException) { } catch (e: IOException) {
Log.e(tag, "unable to bind", e) Log.e(tag, "unable to bind", e)
return null
} }
while (true) { while (true) {
val serverSocket = serverSocket.get() ?: return
try { try {
val socket = serverSocket.accept() val socket = serverSocket?.accept() ?: break
try { try {
accept(socket) accept(socket)
...@@ -73,13 +78,22 @@ abstract class LocalSocketListener(private val tag: String) : Thread() { ...@@ -73,13 +78,22 @@ abstract class LocalSocketListener(private val tag: String) : Thread() {
} catch (e: IOException) { } catch (e: IOException) {
Log.e(tag, "Error when accept socket", e) Log.e(tag, "Error when accept socket", e)
app.track(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() { fun stopThread() {
val old = serverSocket.getAndSet(null) ?: return val old = localSocket.getAndSet(null) ?: return
try { try {
old.close() old.close()
} catch (_: Exception) { } // ignore } catch (_: Exception) { } // ignore
......
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