Bundled KDE Connect: close the races the second review found

- The need-packages retry only runs if no start() has taken over, so two
  agents can't end up running for one session.
- Each copy goes to its own incoming folder; the agent removes its own once
  connected (and any a cancelled start left over an hour ago), so a stopped
  start can't delete files another is copying or still needs.
- A missing package folder means need-packages, not an error.
- Tests keep fake agents running, so they check ready and which agent owns
  the session, plus a bounded retry and the tidy rule.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
saphidandClaude Opus 5.5 committed 2026-09-28 21:28:10 +10:00
1 parent 75b2478a55
commit 6765fbcb20
3 files changed
+84 -31

No files matched your search

+16 -7
View File
@@ -166,7 +166,7 @@ def ensure_daemon(folder, packages):
"""
system = SYSTEM_DAEMON.exists()
if not system and not installed(packages) and not (listening() and our_daemons()):
if not folder:
if not folder or not Path(folder).is_dir():
raise NeedPackages()
install(folder, packages)
if listening():
@@ -346,6 +346,20 @@ def main():
stop_daemon()
def tidy_incoming(folder):
"""Remove this start's copy of the packages, and any a cancelled start left over an hour ago."""
incoming = BASE / "incoming"
if folder.startswith(str(incoming) + "/"):
shutil.rmtree(folder, ignore_errors=True)
try:
for old in incoming.iterdir():
if time.time() - old.stat().st_mtime > 3600:
shutil.rmtree(old, ignore_errors=True)
incoming.rmdir()
except OSError:
pass # none, or another start's copy is still there
class daemon_lock:
"""Installing, starting and restarting KDE Connect happen one agent at a time."""
@@ -361,12 +375,6 @@ def run(client, name, folder, packages):
try:
with daemon_lock():
ensure_daemon(folder, packages)
if folder.startswith(str(BASE / "incoming") + "/"):
shutil.rmtree(folder, ignore_errors=True) # unpacked; the copy isn't needed again
try:
(BASE / "incoming").rmdir()
except OSError:
pass # another device's copy is still there
device, cert, key = identity(client)
say("pairing")
seen = our_daemons()
@@ -390,6 +398,7 @@ def run(client, name, folder, packages):
except (OSError, RuntimeError, subprocess.SubprocessError) as e:
say("error", message=str(e))
return 1
tidy_incoming(folder) # unpacked or not needed: the copy has done its job
say("ready", keyboard=link.keyboard is not False)
stdin, pending = sys.stdin.fileno(), b""
sel = selectors.DefaultSelector()