Skip to content

fix(desktop): avoid temporary icon copies on Linux launches - #22305

Closed
only21mil wants to merge 3 commits into
pingdotgg:mainfrom
only21mil:r9/rl-19589
Closed

only21mil wants to merge 3 commits into
pingdotgg:mainfrom
only21mil:r9/rl-19589

Conversation

@only21mil

@only21mil only21mil commented Oct 20, 2026 •

Copy link
Copy Markdown
Contributor

Re-lands #19589, which was merged and then reverted in #22222 with the other desktop fixes from the takeover batch. The revert comment on #19589 asked for a fresh PR from the original commit, run on a real build that already has user state. This branch is git cherry-pick -x of the #19589 squash commit (115e405) onto current main. It applied cleanly with no edits.

Problem

Every packaged Linux launch copies prod-resources/icon.png out of app.asar with copyFile. Electron serves that copy by extracting the ASAR entry to a temporary file, and it never deletes it. Each launch leaves one .org.chromium.Chromium.* file the size of the icon (549,578 bytes) in $TMPDIR. That includes launches the single-instance lock rejects, which is the case reported in #17737.

Change

Both icon installers (DesktopPreReadyPlatform.ts before ready, DesktopLinuxUrlHandler.ts after ready) now read the bundled icon bytes, compare them with the installed icon, and write it with writeFile only when it is missing or different. Reading a file from the ASAR doesn't extract it. Icon errors still don't block desktop registration. The code is the #19589 commit as merged, unchanged.

Scope and approval

Verification

Real build with existing user state, Linux x64 (Fedora 44):

  1. Built unsigned AppImages for main (774c6c1) and for this branch with node scripts/build-desktop-artifact.ts --platform linux --target AppImage --arch x64. The main bundle's main.cjs has the copyFileSync of prod-resources/icon.png; the branch bundle doesn't.
  2. Ran each one under Xvfb with env -i, a throwaway HOME and its own TMPDIR, so every app path (~/.t3, ~/.config, ~/.local/share) was isolated.
  3. Launches 1-3 used the main AppImage. Launch 1 went through first-run setup. Launch 2 added a local git project (demo-app), created a thread by sending a message, and changed two settings (Working section on, Hide whitespace changes off). A stub claude CLI that only answers --version made a provider selectable, so the thread's turn fails by design.
  4. Launches 4-7 used the branch AppImage on that same profile. Before launch 6, I replaced the installed icon with 17 stale bytes.
  5. Then, one at a time on the same profile, each build ran as a primary instance plus two second-instance launches.

Each main exit left one more icon-sized temp file:

TMPDIR after main launches 1-3

The branch left none, and launch 6 restored the stale icon to the bundled bytes:

TMPDIR after branch launches 4-7

Second-instance launches, the #17737 case. Exit code 130 is how the app exits when the single-instance lock refuses a launch, on both builds:

Second-instance launches on main and on the branch

In launches 3 through 6, the project, the thread with its message and both settings read back unchanged from the UI and from ~/.t3/userdata. Launch 7 rechecked the settings. None of the 9 app logs has an icon warning.

Main, launch 3:

Main launch 3 with the project and thread

Branch, launch 5, same profile:

Branch launch 5 with the same project and thread

The setting as changed on main in launch 2, then still set on the branch in launch 7:

Main launch 2 settings

Branch launch 7 settings

Focused tests: 6 of 23 fail with main's production code, and all 23 pass on the branch. The screenshots below predate main's test purge (#22557), when the same two files held 32 tests and 7 failed.

Focused tests with main production code

Focused tests on the branch

Also run on the branch: tsc-rs --noEmit in apps/desktop (a planted type error fails it), plus vp fmt --check and vp lint --report-unused-disable-directives on the four changed files.

Not checked:

The production fix is the #19589 squash commit, unchanged. So are its tests, except where merging main's test purge (#22557) trimmed DesktopPreReadyPlatform.test.ts: the pre-ready icon-read fallback test checks the written files, the other two icon tests check the installed icon bytes instead of asserting mock calls, and the repeated-launch test also checks that the icon is written once. They were written with Claude Opus 5.5 and revised in the maintainer takeover, with GPT-6.1 Sol on the implementation and GPT-6 Astra on the tests. Re-land, packaged-build verification, PR description and images by Claude Opus 5.5 in T3 Code Nightly.

🤖 Generated with Claude Opus 5.5 in T3 Code Nightly

Loading
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S 10-29 changed lines (additions + deletions). vouch:unvouched Author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants