Fix socket accept loop not restarted after Sparkle update relaunch
After a Sparkle auto-update relaunches cmux, the control socket stops accepting connections because start() early-returns when isRunning is true, without checking if the accept loop thread is actually alive. - Add acceptLoopAlive flag to track accept loop thread liveness - Fix start() early-return to also check acceptLoopAlive, so a dead thread triggers full socket re-creation - Break acceptLoop() after 50 consecutive accept() failures with 10ms backoff instead of tight-spinning forever - Clean up socket in applicationWillTerminate and updaterWillRelaunchApplication for clean teardown before relaunch
This commit is contained in:
parent
50fce9476c
commit
9af7df0dac
3 changed files with 21 additions and 3 deletions
|
|
@ -424,6 +424,7 @@ final class AppDelegate: NSObject, NSApplicationDelegate, UNUserNotificationCent
|
|||
}
|
||||
|
||||
func applicationWillTerminate(_ notification: Notification) {
|
||||
TerminalController.shared.stop()
|
||||
BrowserHistoryStore.shared.flushPendingSaves()
|
||||
PostHogAnalytics.shared.flush()
|
||||
notificationStore?.clearAll()
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ class TerminalController {
|
|||
private nonisolated(unsafe) var socketPath = "/tmp/cmux.sock"
|
||||
private nonisolated(unsafe) var serverSocket: Int32 = -1
|
||||
private nonisolated(unsafe) var isRunning = false
|
||||
private nonisolated(unsafe) var acceptLoopAlive = false
|
||||
private var clientHandlers: [Int32: Thread] = [:]
|
||||
private var tabManager: TabManager?
|
||||
private var accessMode: SocketControlMode = .full
|
||||
|
|
@ -77,7 +78,7 @@ class TerminalController {
|
|||
self.accessMode = accessMode
|
||||
|
||||
if isRunning {
|
||||
if self.socketPath == socketPath {
|
||||
if self.socketPath == socketPath && acceptLoopAlive {
|
||||
self.accessMode = accessMode
|
||||
return
|
||||
}
|
||||
|
|
@ -143,7 +144,14 @@ class TerminalController {
|
|||
unlink(socketPath)
|
||||
}
|
||||
|
||||
private func acceptLoop() {
|
||||
private nonisolated func acceptLoop() {
|
||||
acceptLoopAlive = true
|
||||
defer {
|
||||
acceptLoopAlive = false
|
||||
isRunning = false
|
||||
}
|
||||
|
||||
var consecutiveFailures = 0
|
||||
while isRunning {
|
||||
var clientAddr = sockaddr_un()
|
||||
var clientAddrLen = socklen_t(MemoryLayout<sockaddr_un>.size)
|
||||
|
|
@ -156,11 +164,19 @@ class TerminalController {
|
|||
|
||||
guard clientSocket >= 0 else {
|
||||
if isRunning {
|
||||
print("TerminalController: Accept failed")
|
||||
consecutiveFailures += 1
|
||||
print("TerminalController: Accept failed (\(consecutiveFailures) consecutive)")
|
||||
if consecutiveFailures >= 50 {
|
||||
print("TerminalController: Too many consecutive accept failures, exiting accept loop")
|
||||
break
|
||||
}
|
||||
usleep(10_000) // 10ms backoff
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
consecutiveFailures = 0
|
||||
|
||||
// Handle client in new thread
|
||||
Thread.detachNewThread { [weak self] in
|
||||
self?.handleClient(clientSocket)
|
||||
|
|
|
|||
|
|
@ -87,6 +87,7 @@ extension UpdateDriver: SPUUpdaterDelegate {
|
|||
}
|
||||
|
||||
func updaterWillRelaunchApplication(_ updater: SPUUpdater) {
|
||||
TerminalController.shared.stop()
|
||||
NSApp.invalidateRestorableState()
|
||||
for window in NSApp.windows {
|
||||
window.invalidateRestorableState()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue