Skip to content

fix(desktop): quit on SIGTERM when no scripts are running - #45

Merged
Delta1035 merged 1 commit into
mainfrom
Delta1035/linux-sigterm
Oct 7, 2026
Merged

Delta1035 merged 1 commit into
mainfrom
Delta1035/linux-sigterm

Conversation

@Delta1035

Copy link
Copy Markdown
Owner

Closes #39

原因

Electron 在 Linux 上会把 SIGTERM 转成 Browser::Quit()(最小 Electron 程序可正常退出)。问题在 before-quit 处理器:没有运行中的脚本时 core.dispose() 只靠微任务就完成,而回调返回时 Node 会清空微任务,.finally(() => app.quit()) 于是在外层 Quit() 写回结果之前重入。内层把 is_quitting_ 设为 true 并关闭窗口,外层随后用「被阻止」的结果把它覆盖回 false;窗口关完后 Electron 只发 window-all-closed,「关闭到托盘」模式下什么也不做,托盘已销毁,进程挂住。托盘「退出」不受影响(外面有 JS 栈,微任务要等它结束)。

修改

  • app.quit() 推迟到下一轮事件循环(setImmediate)。
  • quit.spec.ts 新增 SIGTERM 用例(Windows 跳过):空闲时正常退出(退出码 0);有运行中的脚本时停止整棵进程树。

验证

  • Linux(Mint 22.2,X11):1.4.0 AppImage 复现(40 秒仍未退出);有修复时 quit.spec.ts 3 个用例通过,约 1 秒退出;去掉修复后空闲用例超时失败。
  • Windows:pnpm check 通过;pnpm e2e 中 project-actions.spec.ts 悬停卡片偶发失败一次(与本改动无关),单独重跑通过。
  • 未验证:真实注销 / 关机场景。

With nothing to stop, core.dispose() settles within the microtasks Node
drains as the before-quit handler returns. On SIGTERM Electron calls
Browser::Quit() from a task with no JS on the stack, so the follow-up
app.quit() re-entered Quit() before the outer call stored its result; the
outer, prevented result then reset is_quitting_. The windows still
closed, Electron saw "all windows closed" without quitting, and DevHub
stayed alive with its tray destroyed, so logout and shutdown had to
SIGKILL it. Defer the follow-up quit to the next event loop turn.

Add Linux/macOS E2E tests for SIGTERM, idle and with a running process
tree; the idle one times out without the fix.

Closes #39
@Delta1035
Delta1035 merged commit 28fb111 into main Oct 7, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux:收到 SIGTERM 不退出

1 participant