fix(client): 单实例锁改用 TCP loopback socket

文件锁在 Windows 上行为不一致,改用绑定本地端口(54317)作为互斥锁,
进程退出时 OS 自动释放,Windows/macOS 均可靠生效。

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-15 12:09:34 +08:00
parent 0779bf57e3
commit a8c684ad0c
+11 -9
View File
@@ -1,11 +1,13 @@
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:path_provider/path_provider.dart';
// Keep the RAF open so the OS lock stays alive for the lifetime of the process.
// ignore: unused_element
RandomAccessFile? _raf;
// Keep the server socket alive for the lifetime of the process.
// The OS releases the port automatically when the process exits.
ServerSocket? _server;
// Port unique to this app; chosen from the private range 4915265535.
const _kLockPort = 54317;
/// Returns true if this process successfully acquired the single-instance lock.
/// Returns false if another instance is already running.
@@ -15,11 +17,11 @@ Future<bool> acquire() async {
if (!Platform.isWindows && !Platform.isMacOS) return true;
try {
final dir = await getApplicationSupportDirectory();
final lockFile = File('${dir.path}/jiu.lock');
final raf = await lockFile.open(mode: FileMode.write);
await raf.lock(FileLock.exclusive);
_raf = raf;
_server = await ServerSocket.bind(
InternetAddress.loopbackIPv4,
_kLockPort,
shared: false,
);
return true;
} catch (_) {
return false;