Repository navigation
Desktop app lows: old tray on upgrade, restart waiter, cmd remover, uninstall put-back - #7
Merged
Merged
Conversation
An upgrade left the old tray process running on its old lock (an earlier version kept it loose in the data folder), so the new window started a second tray: two icons until logout. The app gets `--close`, which tells the window and the tray to quit, in the new folder and at the old loose names, waits for them to let go of their locks and prints which ran. install.sh runs it before the copy and starts the new tray at the end, or the installed one from the EXIT trap when the install fails. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
The waiter that starts the agent again after a timeout ran under nohup in the login session, so logind's KillUserProcesses ended it with the session, and every install that gave up queued another. Where the user has systemd it is now a unit of its own (systemd-run --user, a fixed name): it outlives the session, and a second install finds it waiting and adds none. Elsewhere it stays under nohup. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
The fallback remover (where PowerShell can't run) piped tasklist into find, so a tasklist that couldn't run read as "the setup has ended" and the folder was removed too early, then left. tasklist now writes to a file in the temporary folder first, and a failure means wait and ask again. find and ping are named by their full paths (cmd looks in its working folder first), and the removal is retried every second for half a minute, not once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
An uninstall that failed after the stop (a shortcut or a file that couldn't go) left the agent stopped and its start at login removed. While the agent's program is still there, its Run values are now put back and, if it ran, it is started again, so the computer keeps syncing until the uninstall is run again; the error says so. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
An uninstall that failed on a held file after deleting some files left a half-removed folder: the agent couldn't be put back, or was put back over missing files. The folder's files are now moved aside first, into "Craft Cloud.removing-<pid>" next to it: the whole folder in one move, or one file at a time when this setup runs from it, moved back if one can't move. A file held open fails the move as a whole, so then nothing is touched and the agent is put back and started again. Only after the move is anything deleted; what can't go yet (an exe still running) goes once the setup has ended. The put-back now needs all three exes in place, says when a Run value couldn't be restored, and says nothing about start at login when none was removed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
…wait In the cmd fallback a ping that failed after find had matched (the setup still running) fell through to the removal. The wait now ends in ver, which always succeeds. The test with a tasklist that can't run now checks that each round waited (a broken line would end at once and pass) and cleans up its temporary file. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
…riables - Without a systemd unit for the agent, the waiter ran the agent in the foreground, inside its own transient unit: the unit stayed active for the agent's whole life, so a later install that gave up took it for a waiter and nothing restarted the agent. The waiter now starts the agent outside itself (a unit of its own, else detached) and ends. - A transient unit doesn't get the installer's environment, so the restarted agent could use another data folder. CRAFT_CLOUD_AGENT_DIR and the XDG folder variables that are set are passed with --setenv, to the waiter and to the agent's unit. - The wait checks the process name as well as the pid, so a pid reused by another program doesn't hold the (now exclusive) waiter for a day. - The comment no longer claims the waiter outlives logout: only while the user's systemd runs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
…on Ctrl-C Run over ssh or without a session bus, the tray closed for the upgrade couldn't register again and the icon was gone. It is now restarted only where the session bus is reachable; elsewhere the script says how to get it back. INT, TERM and HUP end the script through exit, so dash runs the EXIT trap and the agent and tray are started again. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
…he next run - Uninstalling from inside the folder moves the files aside one by one; when one can't move, those moved go back. A file that can't go back is now named in the message instead of being dropped silently. - A folder an earlier run left aside (<folder>.removing-<pid>, its setup no longer running) is finished by the next run: an install first moves back whatever the program folder lacks and then installs over it; an uninstall deletes it. - Once the files are moved aside, failing to delete them now and failing to schedule the delete for later no longer fails the uninstall: the next run removes the leftover. - Each cmd remover has a temporary file of its own: two may run at once. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
Inside the waiter's unit, a nohup fallback for a failed systemd-run would be killed with the unit as the waiter ends. There it now says in the journal that the agent couldn't be started again; nohup stays the fallback only outside systemd. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
Run over ssh, install.sh finished but never returned: the tray it starts kept the session's output open. Under bash (Arch's sh), a background `[ -x … ] && nohup … &` list's subshell keeps the script's streams while the program runs; dash execs it instead, which hid the bug here. Every background start now goes through detach: stdin, stdout and stderr on /dev/null, in a session of its own where setsid is there. The waiter's own fallback does the same. A test runs install.sh under sh and bash with its output a pipe and checks the pipe ends while the tray runs on. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
The app writes its tray Run value for whichever copy last ran, so a development build run once (from a cargo target folder) started at every login after the install. The setup only moved the agent's value, and only from the older hand-made install. Now, on every install, an agent value that starts another copy is taken over by the new agent (read back as before), and a tray value is pointed at this install's app. A value that isn't there stays away: start at login was turned off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz
Owner
Author
|
Tried on the two test machines:
Not tried: uninstalling from Apps & features. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The low findings left from the re-review of #6.
What changed
Old tray on upgrade (L3):
craft-cloud --closetells the running window and tray to quit, waits for them to release their locks, and prints which ones were running. It checks both the new folder and the old loose file names.install.shruns it before copying and starts the new tray at the end.Restart waiter (L5): where the user has systemd, the waiter runs under
systemd-run --userwith a fixed unit name. It survives logind'sKillUserProcesses, and a second install that gives up finds the first waiter and doesn't add another. Without systemd it still runs undernohup.cmdremover fallback (N1–N3):tasklistwrites to a temp file first, so atasklistthat can't run means "wait", not "the setup has ended".findandpingare called by full path.Uninstall failing after the stop (N5): if the agent's program is still there, its Run values are put back and, if it was running, it is started again. The error message says so.
Fix round from this PR's review:
CRAFT_CLOUD_AGENT_DIRand the XDG folder variables that are set reach the units through--setenv.Craft Cloud.removing-<pid>) before anything is deleted. The whole folder moves in one step, or file by file with roll-back when the setup runs from inside it. If a file held open blocks the move, nothing is touched, the Run values are put back and the agent is started again. On Windows a running exe can be moved; what can't be deleted yet goes once the setup has ended.cmdremover (L1, L4): onlyfinddecides, so a failingpingno longer counts as "ended". The test now checks that each round waited.Second review round:
Craft Cloud.removing-<pid>folder left behind (its setup no longer running). An install moves back what the folder lacks and then installs over it; an uninstall deletes it.cmdremovers: each has its own temp file.nohupprocess the unit would kill.After the real-machine install:
ssh … ./install.shnever returned. Under bash (Arch'ssh), a backgrounda && b &list keeps the script's streams open whilebruns. Every background start now goes throughdetach: stdin, stdout and stderr on/dev/null, andsetsidwhere it's available. A test runsinstall.shunder bothshandbashwith its output as a pipe.Testing
Linux:
cargo xtask cipasses.New
install.shtests:nohupfallback withoutsystemd-run.Stand-ins for
systemd-runandsystemctlkeep the tests from touching the machine's real systemd.Windows: clippy
--all-targets -D warningsand the tests for the desktop, setup and xtask crates pass. Thecmdremover now also has a test with atasklistthat can't run: the folder stays.New unit tests cover
--close(a tray in the new folder and an old-version window at the old names) and the uninstall that fails after the stop.Left
The
cmdremover's temp file stays in TEMP if it gives up after an hour. If TEMP isn't writable, the remover waits the hour and removes nothing.close_running_tells_the_window_and_the_tray_new_and_oldtakes about 6 s: its fake listeners never release their locks.N4 (needs a decision):
clipboard-winships no licence file, soLICENSES.txtgives it the BSL-1.0 text fromerror-code, which has the same author and licence. That is a deliberate exception to "no file means plain MIT/Apache or fail". Please accept it or rule otherwise.Without systemd, the
nohupwaiter still dies with the session underKillUserProcesses. Systems without systemd don't have that setting.A final uninstall message left open for over an hour still leaves the program folder behind (L7).
🤖 Generated with Claude Code
https://claude.ai/code/session_01RC1oqfy9kZznj94RjMojyz