Skip to content

[Bug] Linux AppImage 3.14.4: chrome_crashpad_handler & zcode zygote crash with SIGBUS at app exit — squashfs unmounted before child processes exit #926

Open

Description

@gradia64

中文摘要 (TL;DR)

  • Linux AppImage 版退出时,AppImage 的 FUSE squashfs 挂载在子进程退出之前被卸载,仍在存活的 chrome_crashpad_handler 与 zcode --type=zygote 访问已失效的文件映射页 → SIGBUS (BUS_ADRERR)。
  • KDE/DrKonqi 每次受影响的关闭都会弹出崩溃对话框;且 ~/.zcode/v2/crash/ 始终为空 —— 因为崩溃上报器本身就是受害者,这些退出不会产生任何官方崩溃报告。
  • 长时间会话后关闭更易复现(子进程退出变慢,race 更容易输)。主进程本身退出干净(exitCode 0),无数据丢失。
  • 建议修复:打包改用 extract-and-run 语义,或在卸载挂载前先终止并等待 zygote 与 crashpad_handler 退出。

Environment

  • ZCode 3.14.4 (Linux AppImage, Electron 41.0.3, prod=Electron ver=41.0.3 per crashpad annotations)
  • Debian forky/sid, kernel 7.2.9+deb14-amd64, KDE Plasma, systemd-coredump + DrKonqi
  • fuse3 3.18.3-1; /tmp is tmpfs; AppImage mounts at /tmp/user/1000/.mount_ZCodeXXXX

Steps to reproduce

  1. Run the ZCode AppImage. More reliable after a long session (observed after ~2 h, ~1 GB RSS + ~300 MB swap — slow child teardown loses the race more often).
  2. Close the last window (normal quit, no confirmation prompt on Linux).
  3. ~7–8 s into teardown, the kernel delivers SIGBUS to two lingering child processes.

Actual behavior

  • chrome_crashpad_handler → SIGBUS (small core)
  • zcode --type=zygote → SIGBUS, si_code: BUS_ADRERR (1.8 MB core)
  • DrKonqi shows two crash dialogs on every affected close — chronic: 4+ occurrences over 3 consecutive days
  • ZCode's own crash database (~/.zcode/v2/crash/live) stays empty for these events — the crash reporter is itself the crashing process, so nothing is reported server-side

Expected behavior

Clean exit with no child crashes and no crash dialogs.

Evidence

Journal timeline of one occurrence (timestamps from journalctl --user):

11:51:07.886  [desktop-command] execute closeWindow windowId=1
11:51:08.237  [stability] perf_app_exit reported { scene: 'app_quit', exitCode: 0 }   <- main exits cleanly
11:51:11      agents terminated (SIGKILL, terminationKind: 'expected')
11:51:15      systemd scope torn down; AppImage mount deactivated
11:51:15      systemd-coredump: Process 27427 (chrome_crashpad) dumped core          <- SIGBUS
11:51:16      systemd-coredump: Process 27232 (zcode --type=zygote) dumped core      <- SIGBUS

coredumpctl list (chronic pattern, all at app exit):

Sat 2026-10-03 11:53:21  SIGBUS  /chrome_crashpad_handler
Sun 2026-10-04 17:59:38  SIGBUS  /chrome_crashpad_handler
Sun 2026-10-04 21:32:23  SIGBUS  /chrome_crashpad_handler
Mon 2026-10-05 11:51:15  SIGBUS  /tmp/user/1000/.mount_ZCodeZ9jmAB/chrome_crashpad_handler
Mon 2026-10-05 11:51:16  SIGBUS  /tmp/user/1000/.mount_ZCodeZ9jmAB/zcode   (--type=zygote)

GDB on one of the cores confirms the mechanism (the missing-symbol warning is itself the proof — the mapping target no longer exists):

warning: Can't open file /tmp/user/1000/.mount_ZCodeZ9jmAB/chrome_crashpad_handler
         during file-backed mapping note processing
Program terminated with signal SIGBUS, Bus error.

si_code: BUS_ADRERR = access to a page of a memory-mapped file whose backing store is gone.

Root cause analysis

All AppImage binaries (zcode, chrome_crashpad_handler, bundled libs) execute and mmap from the FUSE squashfs mount. At quit, the AppImage runtime unmounts the mount while two kinds of children are still alive:

  • the Chromium zygote, which lingers while renderers shut down;
  • the crashpad handler, which by design must outlive the browser process to catch its crashes.

The first touch of a non-resident page backed by the unmounted filesystem raises SIGBUS. It is a race: short sessions usually finish child teardown before the unmount (no crash); long sessions with memory/swap pressure lose it.

Suggested fixes

Any of:

  1. Package with --appimage-extract-and-run semantics (no runtime FUSE mount), or
  2. Before unmounting: identify zcode --type=zygote and chrome_crashpad_handler children, SIGTERM → wait → SIGKILL, then unmount, or
  3. Lazy-unmount and keep the mount referenced until all processes using it have exited.

Workaround for affected users

Extract once and run from disk (removes the FUSE mount from the equation):

./ZCode-*.AppImage --appimage-extract
./squashfs-root/AppRun

or wrap launches with --appimage-extract-and-run.

Related but distinct: #911 (macOS crashpad handler crashing — same victim process, different platform, signal and root cause).

Activity

  1. github-actions commented on Oct 5, 2026

    @github-actions

    👋 感谢你的反馈,我们已经收到。

    • 维护者看到后会尽快回复你。
    • 状态保持为 status: 待评估,你可以随时补充信息。
    • 信息不全时我们会打上 needs: 更多信息 标签并 @ 你。

    👋 Thanks — we've received your issue.

    • A maintainer will get back to you as soon as we can.
    • Status stays at status: 待评估 (Triage); feel free to add context.
    • If we need more details, we'll add needs: 更多信息 and ping you.
  2. gradia64 commented on Oct 6, 2026

    @gradia64
    Author

    Additional data point from the reporter: session length / memory pressure correlates with crash probability, which further supports the unmount-race diagnosis.

    Same machine, same version (3.14.4 AppImage), same exit path (close last window → normal quit):

    crashing session (2026-10-05) clean sessions (2026-10-06)
    Session duration 2h 06m 50s 54 min / ~1 min
    Memory pressure ~1.0 GB RSS + ~319 MB swap peak low (short sessions)
    Teardown duration (closeWindow → app exit) ~8 s ~1 s
    Result SIGBUS on chrome_crashpad_handler and zcode --type=zygote all children exit before unmount, zero core dumps

    Empirical rule observed over several days: short sessions (< ~1 h, low memory) always exit cleanly; long sessions (≥ ~2 h) with memory/swap pressure lose the race and crash on exit. The longer teardown of a large, swapped-out child tree gives the FUSE unmount a window to arrive first — exactly the timing-dependent failure described in the original report.

    Happy to collect journalctl teardown timings across more exit cycles if useful for triage.

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions