fix(desktop): keep AppImage mounted while t3 shuts down#24421

open4
main
fix/issue-24416
opened17d agobyJJulius Marminge
View on GitHubTwo-way sync enabledPR last imported 3h ago

Problem

Sending SIGTERM to the Linux AppImage t3 serve process group also stops its AppImage mounter. The filesystem disappears while the server is shutting down, causing SIGBUS. SIGHUP has the same exposure.

Change

Start the mounter in a separate session so group signals reach the server without unmounting its executable. Catch HUP alongside the existing INT/TERM traps so launcher cleanup stops the mounter after the server exits. Add signal-order regression tests, gated on setsid availability.

Scope and approval

Fixes https://github.com/pingdotgg/t3code/issues/24416

Triaged bug via the automated issue flow. GitCafe: https://git.cafe/pingdotgg/t3code/issues/24416

This focused fix changes only the Linux AppImage launcher lifecycle and its tests.

Verification

  • Red: both TERM/HUP shutdown-order tests fail against the base renderer (expected 'unmounted' to be 'mounted').
  • Green: vp test run apps/desktop/src/app/DesktopCliShim.test.ts passes all 6 tests, including after integrating current main. The two new cases skip when setsid is unavailable.
  • Scoped launcher/test lint and desktop typecheck pass. Both independent reviewers report no blocking findings after the test portability correction.
  • Real runtime: Ubuntu 24.04 x86_64, dash, util-linux setsid, FUSE, isolated temporary state, core dumps disabled. Launcher source at 0e05de5f8d is byte-identical to the final head after merging unrelated main changes. The packaged runtime is the released 0.1.2 AppImage; a full head desktop artifact was not rebuilt.
Runtime proofBeforeAfter
Group SIGTERM, genuine FUSE mount9/9 attempts print Bus error9/9 without Bus error; server, mounter, mount and launcher workspace removed
Group SIGHUPShutdown-order regression failsNo Bus error; server and mount removed
Foreground terminal Ctrl-CExisting behaviorPass; cleanup verified
Mounted normal completionExisting behavior--version exits 0; cleanup verified
Mount failure / unavailable setsidExisting extraction fallbackBoth real extraction paths exit 0; workspace removed

Before transcript, after transcript, and complete evidence index. The index includes red/green output, PID/session and FUSE-map observations, cleanup results, and uploaded reproduction drivers. No visual surface changes; the visual fixture matrix is empty. Final proof audit found the proof sufficient, with the limitations below.

Limits: the released runtime leaves a startup Claude probe after SIGHUP; the driver records and stops it, so full provider-descendant cleanup is not claimed. SIGKILL bypasses launcher cleanup and can leave the isolated mounter alive. GUI, other platforms, SSH/service-manager variants and a rebuilt head desktop were not runtime-tested; their launcher branches are unchanged.

Models and harnesses: Claude Opus 5.5 through Claude Code (implementation/tests); GPT-6.1 Sol through Codex (issue lead, review and proof), orchestrated by T3 Code.

Fixes pingdotgg/t3code#24416

Checks

22 successful · 7 skipped
All checks passed
c3e066d

Added 4 commits

  • test(desktop): skip the AppImage mount signal tests where setsid is missing0e05de5
  • fix(desktop): the AppImage t3 launcher stays mounted until the server exits after a group signalbfe5cc6
  • Merge main into fix/issue-24416c3e066d
  • test(desktop): reproduce issue 24416, group SIGTERM/SIGHUP unmounts the AppImage before the server exitse789952

[GPT-6.1 Sol][Codex] on behalf of shivam.

Stopping the parallel issue-watch investigation now that Julius owns this fix. Source inspection on main confirmed that the generated launcher starts --appimage-mount in the server's process group and traps INT/TERM without HUP, matching the reported shutdown race. I had not started runtime testing, so I have no independent reproduction or test result to add. No code changes or competing PR were made.

Synced from GitHub

Approvability

Verdict: Approved at c3e066d

Macroscope's review found this PR approvable — This is a narrowly scoped AppImage shutdown bug fix that isolates the mounter from process-group signals and adds TERM/HUP regression coverage. Existing direct, Windows, and extraction-fallback paths remain unchanged, with no product-default or static-analysis configuration changes.

You can add or adjust custom eligibility rules. Learn more.

Synced from GitHub

Review in Change Stack →

No actionable comments were generated in the recent review.

Walkthrough

The AppImage launcher starts its mounter in a separate session and handles HUP alongside INT and TERM. A new test checks that process-group signals do not unmount the AppImage before the server exits.

Changes: AppImage signal lifecycle

Layer / File(s)Summary
Mounter isolation and signal handling
apps/desktop/src/app/DesktopCliShim.ts
The launcher starts the mount process with setsid and handles HUP, INT, and TERM.
Shutdown and unmount-order test
apps/desktop/src/app/DesktopCliShim.test.ts
The fixtures report mount events and hold the server during shutdown. The test sends SIGTERM or SIGHUP to the process group and checks that unmount follows server exit.

Estimated code review effort: 2 (Simple) | ~10 minutes

Change: Bug fix · Severity of issue fixed: Medium

Suggested labels: bugfix, size:XS

Suggested reviewers: maria-rcks

Merge Risk: External image Minimal · up to c3e06

The AppImage shutdown change is ready to merge after normal checks; no concrete blocking issue was identified.

Pre-merge checks: Passed 4

Check nameStatusExplanation
Title checkPassedThe title "fix(desktop): keep AppImage mounted while t3 shuts down" matches the main change. The PR starts the AppImage mounter in a separate session and traps HUP, so the mount stays up while the ser…
Linked Issues checkPassedIssue #24416 is the only active directly linked target. Its coding requirements are: (1) start the AppImage mounter in its own session so group SIGTERM/SIGHUP does not unmount it under the server; (2)…
Out of Scope Changes checkPassedThe whole-PR diff against merge base d0e621e9 touches two files: apps/desktop/src/app/DesktopCliShim.ts (+6/-3) and apps/desktop/src/app/DesktopCliShim.test.ts (+80/-3). Both files implement the AppIm…
Description checkPassedThe description covers all required sections. It explains the shutdown race and fix, links the triaged issue, defines the focused scope, and reports tests, runtime results, and limitations.
Full details: Title check

Explanation

The title "fix(desktop): keep AppImage mounted while t3 shuts down" matches the main change. The PR starts the AppImage mounter in a separate session and traps HUP, so the mount stays up while the server stops. The title is specific and follows conventional commit style.

Full details: Linked Issues check

Explanation

Issue #24416 is the only active directly linked target. Its coding requirements are: (1) start the AppImage mounter in its own session so group SIGTERM/SIGHUP does not unmount it under the server; (2) trap HUP so the EXIT cleanup still unmounts after the server exits; (3) keep the INT/TERM behavior. The change in apps/desktop/src/app/DesktopCliShim.ts meets (1) with setsid "$app" --appimage-mount and meets (2) and (3) with trap 'exit 130' INT TERM HUP. The EXIT trap still kills the mounter and removes the work directory. The test diff in apps/desktop/src/app/DesktopCliShim.test.ts adds SIGTERM and SIGHUP group-signal cases. Each case checks that the mounter reports mounted while the server stops and reports unmounted only after the server exits. The cases skip when setsid is absent. The PR runtime evidence (Ubuntu 24.04, 9/9 group SIGTERM runs without Bus error) is author-reported and was not independently rerun. The source and test diffs support the requirements. Non-coding runtime checks in the PR description were not assessed as requirements. The SIGKILL trade-off from the issue is documented and is not a requirement failure.

Full details: Out of Scope Changes check

Explanation

The whole-PR diff against merge base d0e621e9 touches two files: apps/desktop/src/app/DesktopCliShim.ts (+6/-3) and apps/desktop/src/app/DesktopCliShim.test.ts (+80/-3). Both files implement the AppImage launcher lifecycle in issue #24416. The source edits are the setsid wrap, the HUP trap, and the explanatory comments. The test edits are the fake AppImage fixture extension (custom app script, fd 3 event reporting, HUP/INT unmount trap), the SLOW_SERVER fixture, the hasSetsid gate, and the two signal-order cases. The change set contains no unrelated behavior changes. The PR description states that no visual surfaces or other modules changed. Remaining uncertainty: this review did not rerun the tests or the packaged runtime. That uncertainty affects verification only, not scope.

Finishing Touches

Generate docstrings

  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)

  • Commit to this branch
  • Create a new PR
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
External image Recent review info

External image Run configuration

External image Commits

Reviewing files that changed from the base of the PR and between a46f80ee28d9b498bb8b407c8b60bd4e93bbe2e3 and c3e066d39d392f83fd1a390d5dc5da6d42da358a.

External image Files selected for processing: 2

  • apps/desktop/src/app/DesktopCliShim.test.ts
  • apps/desktop/src/app/DesktopCliShim.ts

Included review availability: This review used your included allowance. Your plan provides up to 10 included reviews per hour; 0 remain after this review.

The automated pipeline stopped on this pull request and will not merge it:

someone else pushed to fix/issue-24416 (head is now c3e066d39d); the pipeline does not build on commits it did not review

It stays open for a person to finish or close.