Repository navigation
fix(desktop): name the plugin host exit code in a crash report - #756
Closed
zhangqingkun976 wants to merge 1 commit into
Closed
zhangqingkun976 wants to merge 1 commit into
zhangqingkun976 wants to merge 1 commit into
Conversation
A report could only ever say `plugin host process exited: <id>`: the runtime already had the process's exit code but kept it in the audit record, so the sentence a user can paste carried no diagnosis at all (issue vastsa#747 was exactly that line, with no logs). - The exit code now reaches the load error, the `failed` service state, the `plugin.crash` audit record and the `plugin` log channel. On Windows a hard fault (0xC0000005 and friends, which Electron delivers as a negative signed int) and a plugin's own `process.exit(1)` are different bugs; the code is printed with its unsigned hex form so both readings agree. - The plugin's newest output line rides with it. The runtime keeps the last three stdout/stderr lines per plugin (each bounded at 400 characters) and quotes the newest in the load error and the audit record, because a plugin that died on a thrown error usually printed the reason first. Every line still lands in the audit thread as `plugin.stdio`. - Nothing new is persisted and no permission, API or protocol surface changes. The fixture in `plugin-services.test.mjs` now writes a line to stderr before exiting, and asserts the exit code on the service state and both the code and the stderr line on the crash audit record.
This was referenced Sep 21, 2026
Owner
|
该 PR 的原始提交已由修复版 #766(包含行缓冲、退出 flush、统一 Windows 退出码和回归测试)合入 main,关闭此 PR 以避免重复合并旧实现。 |
This was referenced Sep 21, 2026
Open
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.
Fixes #747 — or rather, makes the next report of it fixable.
The issue contains one sentence, three times:
plugin host process exited: io.github.muzimu217.usage-dashboard. That is all the reporter could say, because the exit code the runtime already had never left the audit record. On Windows,3221225477(a0xC0000005access violation, i.e. native code in the plugin or its sidecar) and1(the plugin's ownprocess.exitor an uncaught throw) are completely different investigations, and this one field is what separates them.What changes
plugin host process exited: <id>plugin host process exited: <id> (exit code 7; last output: error: fixture service worker died)failedservice stateplugin host process exitedplugin host process exited (exit code 7)plugin.crashaudit recordexitCodeexitCode, plusmessage= the newest output linepluginlog channeldata: { exitCode }data: { exitCode, lastOutput? }The exit code is printed together with its unsigned hex form when it is in the range a Windows process reports for a hard fault, because Electron hands it over as a signed int (
-1073741819and0xC0000005are the same value). Nothing is interpreted for the reader.The plugin's last words
The runtime keeps the last three stdout/stderr lines per plugin host process (each bounded at 400 characters) and quotes the newest one in the crash report. A plugin that dies on a thrown error has usually printed the reason first, and that line is the difference between "the plugin is broken" and "the plugin is broken because X". Every line still reaches the audit thread as
plugin.stdio— this only makes sure the last one survives into the error the user can paste.Scope
No new persistence, no permission, manifest, API or protocol change; the plugin process is already piped through
onLog, so nothing new is spawned or buffered. The bounded tail lives on the loaded-plugin record and dies with it.Validation
apps/desktop/test/plugin-services.test.mjs— the die-once fixture now writesfixture service worker diedto stderr beforeprocess.exit(7), and the test assertsexit code 7on the service state plus the code and the stderr line on the crash audit record; the fake spawner in the test now implementsonLoglike the real one does. 16/16 pass.node --test apps/desktop/test/plugin-*.test.mjs— 337/338; the one failure (the project's other folders are not an escape hatch) is pre-existing and fails identically on pristinemain.pnpm --filter @pi-desktop/desktop typecheck0;pnpm lintclean;node scripts/check-architecture.mjspassed;pnpm docs:check(78 EN/zh pairs, 495 pages) exit 0.E2E gate: NOT RUN. The scenario is written (
E2E-PLUGIN-crash-report-names-the-exit-code, both locales, with its traceability rows) but no desktop E2E suite was executed — it needs a packaged candidate and a plugin that faults on demand. Alternative validation: the runtime-level test above forks a real host process, kills it and checks the same four surfaces the scenario names. Remaining risk: the plugin page's own error text is read by no driver, so the rendered string is verified only through the contract test.Docs
07-plugins/05-plugin-lifecycle.md§3.1 (crash report) and §8 (audit fields),08-meta/decisions-log.mdD607, and the E2E scenario above — all mirrored todocs/zh-CN/….D607 is numbered after the D604–D606 proposed in my open #721 and #748; I will renumber if those land first.