Skip to content

feat(logging): record renderer and helper process crashes - #2972

Open
chris-yoshih wants to merge 1 commit into
generalaction:mainfrom
chris-yoshih:yoshih/log-process-crashes
Open

feat(logging): record renderer and helper process crashes#2972
chris-yoshih wants to merge 1 commit into
generalaction:mainfrom
chris-yoshih:yoshih/log-process-crashes

Conversation

@chris-yoshih

Copy link
Copy Markdown

Description

Another suggestion — independent of #2971, either can stand alone.

render-process-gone and child-process-gone have no handlers anywhere in the
repo. When a renderer, GPU, or utility process dies, no main-process code path
runs: the window white-screens or a feature quietly stops working, and
uncaughtException never fires, so registerProcessErrorLogging doesn't see it
either. emdash.log just ends mid-session.

That's the worst case for the failure mode #80's memory watchdog exists for. An
OS-killed renderer is exactly what leaves no trace — the evidence is a platform
crash report (a macOS JetsamEvent, say), outside the app, kept only if the OS
felt like it. This puts the cause in emdash's own log next to the rest of the
session, so reason and exitCode are one grep away.

clean-exit is dropped rather than recorded. Electron reports it for every
helper that terminates normally at shutdown, so logging it would mean a burst of
errors on every ordinary quit. For a renderer death the report also carries the
WebContents URL, which separates the app window from a browser-pane webview —
a page in the in-app browser crashing says nothing about emdash.

Shape. reportRenderProcessGone / reportChildProcessGone are pure
functions returning a message plus fields, or null for a clean exit — no
Electron import, so the filtering and field selection are directly testable.
registerProcessCrashLogging(app, log) is the wiring, typed against a narrowed
ProcessCrashEventSource interface rather than Electron.App so a test can
hand it a stub emitter. Same split as dev-worktree-profile.ts and
reap-dev-profiles.ts. index.ts gains one import and one call, next to the
existing registerProcessErrorLogging.

One thing worth flagging: reading contents.getURL() on a WebContents that is
already tearing down can throw, so it's wrapped and the URL is simply omitted
when unavailable — the crash still gets logged.

Related issues

None filed. It came up while reading #80 — the watchdog catches the run-up to a
memory kill, but if the kill lands anyway there's nothing in the log to confirm
what happened.

Testing

  • oxfmt --check, oxlint, tsgo --noEmit on apps/emdash-desktop — all clean.
  • vitest run --project node — 283 files / 2032 tests pass, including 10 new
    ones: oom / crashed / killed renderer reasons, clean-exit suppressed
    on both events, a missing URL falling back to undefined, child-process type
    and serviceName passthrough, and the registration seam driven by a stub
    emitter (both handlers registered, both firing, clean exits producing no log
    call).
  • Not run: the full workspace pnpm run test across every project. No manual
    crash reproduction — I didn't want to guess at forcing an OOM kill on a real
    session, so the Electron event payloads are taken from the documented shapes
    and exercised through the stub rather than from a live crash. If you'd rather
    see a real one in a log before taking this, that's fair.

Screenshot/Recording (if applicable)

n/a — log output only.

Checklist
  • I kept this PR small and focused
  • I ran a self-review before opening this PR
  • I ran the relevant local checks or explained why not
  • I updated docs when behavior or setup changed — no docs describe log contents
  • I added or updated tests when behavior changed, or explained why not
  • I only added comments where the logic is not obvious
  • I used Conventional Commits for commit messages and the PR title

A renderer, GPU, or utility process that dies takes no main-process code
path with it. The window white-screens or a feature quietly stops
working, `uncaughtException` never fires, and the session log simply
ends. An OS-killed renderer — the shape a memory incident takes — is then
reconstructible only from a platform crash report, if the machine kept
one.

Register `render-process-gone` and `child-process-gone` at the same point
as the existing process error handlers, so the cause lands in emdash.log
next to the rest of the session: the reason (`oom`, `crashed`,
`launch-failed`, …), the exit code, the URL for a renderer, and the
process type and service name for a helper. `clean-exit` is dropped —
every helper reports it at shutdown, so logging it would put a crash line
in every quit.

The reporting decisions are pure functions over the detail payloads, with
the Electron wiring narrowed to a stubbable event-source seam.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@greptile-apps

greptile-apps Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Adds app-wide logging for abnormal Electron renderer and helper-process exits.

  • Records process reason, exit code, renderer URL, and helper metadata through the existing file logger.
  • Suppresses normal clean-exit events and tolerates destroyed WebContents instances.
  • Registers the handlers during main-process startup and adds focused unit and wiring tests.

Confidence Score: 5/5

The PR appears safe to merge, with no concrete correctness or security failures identified in the changed paths.

The new listeners match the intended Electron process-gone event flow, use the initialized non-throwing logger, suppress ordinary teardown events, and retain crash logging when renderer URL lookup fails.

Important Files Changed

Filename Overview
apps/emdash-desktop/src/main/app/process-crash-logging.ts Adds focused process-exit report builders and Electron event registration with clean-exit filtering and safe URL lookup.
apps/emdash-desktop/src/main/app/process-crash-logging.test.ts Covers renderer and helper crash reports, clean-exit suppression, registration wiring, and unavailable renderer URLs.
apps/emdash-desktop/src/main/index.ts Registers process crash logging after file-logger initialization during synchronous main-process setup.

Reviews (1): Last reviewed commit: "feat(logging): record renderer and helpe..." | Re-trigger Greptile

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.

1 participant