fix(diagnostics): make startup crashes self-reporting; cross-env for dev script - #41
Merged
Merged
Conversation
…cript Three users independently root-caused the same startup crash (#36/#37/#38) from OS crash reports, because the app itself recorded nothing: onnxruntime aborted natively inside InferenceSession.create, which gives JS no chance to run a catch block or flush a buffered stream, and crashpad was never started. %APPDATA%\Out Loud didn't even exist afterwards. Add electron/crash-log.ts, an append-only breadcrumb log shared by the main process and the TTS worker. Every write is synchronous, so the last line is on disk before the next statement runs and survives a hard abort — verified against process.abort() (SIGABRT, no unwinding), where the breadcrumb persists. console.log/warn/error are teed into it, so the breadcrumbs the app already emits are captured in packaged builds where stdout goes nowhere. The worker writes to the file directly rather than via its piped stdout: a native abort kills the thread with whatever is still in the pipe, and the lost line is exactly the one identifying where it died. The main process passes the path through workerData; standalone worker use skips logging. Also: - crashReporter.start({uploadToServer: false}) at module load, so native minidumps land locally in crashDumps. Nothing is uploaded anywhere. - Log the ONNX session parameters BEFORE the call that can abort, so a truncated log still names the providers, optimisation level and arch. - child-process-gone / render-process-gone / uncaughtException / unhandledRejection handlers. - Rotate at 2 MB keeping one previous file; all logging is best-effort and wrapped so diagnostics can never break startup. Separately, electron:dev used Unix-only `NODE_ENV=development electron .`, which fails on Windows (also reported in #36). Route it through cross-env. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Follow-up to #39. That PR fixed the crash; this one makes the next one diagnosable.
Why
Three users independently root-caused #36/#37/#38 from OS crash reports, because the app recorded nothing itself. onnxruntime aborted natively inside
InferenceSession.create— no JS error, no catch block, no chance to flush a buffered stream — andcrashReporterwas never started.%APPDATA%\Out Louddidn't exist afterwards, and the Windows event log was empty. From the user's side the app simply vanished ~3s after launch.What
New
electron/crash-log.ts: an append-only breadcrumb log shared by the main process and the TTS worker thread.Every write is synchronous. That's the whole design constraint — the line has to be on disk before the next statement runs, so it survives an abort that never unwinds. Verified against
process.abort()(SIGABRT, no flush): the breadcrumb persists.console.log/warn/errorare teed into it, so the breadcrumbs the app already emits (ONNX session providers: cpu,Model preloaded successfully) get captured in packaged builds, where stdout goes nowhere a user can reach.The worker writes to the file directly rather than through its piped stdout. A native abort kills the thread with whatever is still sitting in the pipe — and the lost line is precisely the one identifying where it died. The main process passes the path via
workerData; driving the worker standalone (as the website's sample generator does) just skips logging.Also:
crashReporter.start({ uploadToServer: false })at module load, so native minidumps land incrashDumps. Local only — nothing is uploaded anywhere. Confirmed the Crashpad database is created on launch.child-process-gone,render-process-gone,uncaughtException,unhandledRejectionhandlers.Had this existed, #36 would have been a one-line paste:
Log location is printed at startup and is
app.getPath("logs")/out-loud.log—%APPDATA%\Out Loud\logs\on Windows,~/Library/Logs/Out Loud/on macOS.Unrelated fix
electron:devused Unix-onlyNODE_ENV=development electron ., which fails on Windows — also reported in #36. Routed throughcross-env(added as a dev dependency).Verification
npm run check(lint, format, knip, typecheck) passes.process.abort()survival test as described above.Note:
knip.config.jsneededelectron/crash-log.tsadded to the entry list — the same treatment the other electron modules already get, since imports resolve to the committed.jsand the.tssource would otherwise read as unused. The config already documents this.🤖 Generated with Claude Code