From bbb9bccda4d053f5605a6e5330468886cd1e4d9f Mon Sep 17 00:00:00 2001 From: yusufipk Date: Sun, 16 Aug 2026 10:28:52 +0300 Subject: [PATCH] Stop answering before the replacement starts, on a restart execv leaves nothing behind to answer, so this never came up on Linux or a Mac. A Windows restart is two processes for a moment: the new one looks for an instance to hand its command to, and if it finds the old one still listening it takes itself for the second copy and exits, leaving nothing running at all. The server is closed before the replacement is started rather than after. Not reproduced, because it is a race and it lost: found by reading the order of the two calls, and worth a restart or twenty on a real machine. --- dikte.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/dikte.py b/dikte.py index 7ce82a2..d777206 100755 --- a/dikte.py +++ b/dikte.py @@ -88,6 +88,9 @@ class Dikte: self.meeting_base = "" self.meeting_message = "" self.settings_window = None + # The single-instance server, handed over once run_app has opened it, so + # that a restart can stop answering before the replacement starts. + self.server = None self._quitting = False # A request that asked to be told how its run ended waits in here until # the run gets there, keyed by which of the three it was waiting on. @@ -901,6 +904,13 @@ class Dikte: if self.settings_window is not None: self.settings_window.close() self.shutdown() + # Stop answering before the replacement is started, not just afterwards. + # execv leaves nothing behind to answer, but a Windows restart is two + # processes for a moment, and a new one that reached a server still + # listening would take itself for the second copy, hand its command over + # and exit, leaving nothing running at all. + if self.server is not None: + self.server.close() QLocalServer.removeServer(SERVER_NAME) if sys.platform == "win32": # execv on Windows mangles arguments with spaces and leaves the two @@ -1066,6 +1076,7 @@ def run_app(args): QLocalServer.removeServer(SERVER_NAME) if not server.listen(SERVER_NAME): print(f"dikte: could not open the IPC socket: {server.errorString()}") + dikte.server = server def on_connection(): conn = server.nextPendingConnection()