Skip to content

feat(v3): debug package + user-goroutine panic handling#5173

Draft
leaanthony wants to merge 8 commits intomasterfrom
debug-package
Draft

feat(v3): debug package + user-goroutine panic handling#5173
leaanthony wants to merge 8 commits intomasterfrom
debug-package

Conversation

@leaanthony
Copy link
Copy Markdown
Member

Summary

Introduces a Windows-first diagnostic/crash-dump package alongside guidance
and an example for handling panics in user-spawned goroutines.

New: v3/pkg/debug

A small, stateless API for capturing crash diagnostics at runtime. Two
entry points:

  • debug.Dump(...) — writes a Windows minidump of the current process via
    Dbghelp.MiniDumpWriteDump. Uses GetCurrentProcess() so no
    elevation / SeDebugPrivilege is required
    — runs under a standard user
    token. Returns the absolute path of the written file. On non-Windows
    platforms it returns a clean unimplemented error so callers can degrade
    gracefully. Options: WithPath, WithFullMemory.
  • debug.Report(...) — collects system info, build info, runtime
    process/memory/module state, and a diagnostics pass from
    pkg/doctor-ng. Returns a *CrashReport. Minidump is opt-in via
    WithDump / WithDumpPath / WithDumpFullMemory.

Both entry points are designed to be safe to call from PanicHandler:
they stream the minidump directly to a file handle (no Go-side buffering
of megabytes), and Report returns a partial report even when the
minidump step fails.

Default dump location is os.TempDir() — on Windows,
%LOCALAPPDATA%\Temp\wails-crash-<pid>-<unix>.dmp. Writable by the
current user, not elevated, not world-readable.

New: v3/examples/user-panic-handling

Demonstrates funnelling panics from user-spawned goroutines through
the same PanicHandler wails uses for bound methods. Ships a
recoverAndReport() helper that user code defers at the top of every
goroutine it owns. Without it, goroutine panics crash the whole process —
wails can only inject deferred recovers into code paths it owns.

Docs

  • New guide: guides/debugging-crashes.mdx — full coverage of the
    debug package. Quick reference, CrashReport shape, PanicHandler
    integration, manual debugging use cases (hang detection, support
    bundles, anomaly reports), minidump flag rationale, non-Windows
    behaviour, and security notes.
  • Updated: guides/panic-handling.mdx — new "Handling Panics in Your
    Own Goroutines" section with the recoverAndReport pattern, and a
    "Capturing Diagnostics on Panic" section cross-linking into the new
    debug guide.

Security notes

  • No elevation. No SeDebugPrivilege. No OpenProcess on remote PIDs.
    Deliberately scoped to the calling process.
  • Minidumps contain everything in process memory — tokens, keys, user
    data. The docs call this out so consumers handle dumps with the same
    care as raw memory images.

Test plan

  • go build ./v3/pkg/debug/... on linux, windows, darwin (verified locally)
  • go vet ./v3/pkg/debug/... clean on all three platforms
  • go test ./v3/pkg/debug/... passes on linux
  • Cross-platform test covers: Report populates fields, default
    DumpPath empty without WithDump, Dump returns error on
    non-Windows, option composition
  • Run dump_windows_test.go on a real Windows host — verifies
    MDMP magic bytes, default path under TempDir, Report(WithDumpPath)
    writes + records path
  • Open a produced .dmp in WinDbg to sanity-check thread/handle/module
    coverage with the default flag set

Out of scope (follow-ups)

  • Wiring debug.Report into PanicHandler by default — intentionally
    opt-in. Could ship a helper debug.CrashHandler(userHandler) later.
  • macOS/Linux postmortem equivalents (core dumps via GOTRACEBACK=crash,
    CrashReporter, rr, etc.) — out of scope for a Windows-first package.

🤖 Generated with Claude Code

Wails Documentation Agent and others added 6 commits April 19, 2026 11:52
Demonstrates funnelling panics from user-spawned goroutines through the same
PanicHandler wails uses for bound methods and internal runtime callbacks.
Ships a recoverAndReport() helper for deferral inside user goroutines, since
wails cannot inject deferred recovers into code it does not own.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The existing guide noted that user-spawned goroutines fall outside wails'
automatic recovery but didn't show how to route them through the registered
PanicHandler. Added a "Handling Panics in Your Own Goroutines" section with
the recoverAndReport pattern, a caution on stack-trace fidelity, and a link
to the new runnable example.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The guide referenced v3/examples/panic-handling just above the new section
and then added a second reference to v3/examples/user-panic-handling,
making it unclear which one to run. Moved the references into a single
list inside the "Handling Panics in Your Own Goroutines" section with a
one-line description of what each example demonstrates.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…tform build

collect_windows.go: writeCoreDump now writes a real minidump of the current
process via Dbghelp.MiniDumpWriteDump, using the GetCurrentProcess pseudo-
handle so no SeDebugPrivilege or OpenProcess is required — runs under a
standard user token. Default path uses os.TempDir() with a wails-crash-<pid>-
<unix>.dmp filename. Flags combine MiniDumpNormal, WithThreadInfo,
WithHandleData, and WithUnloadedModules — rich postmortem content without
writing the full address space.

Signature change: writeCoreDump(path string) (string, error). Returns the
absolute dump path so callers can attach it to reports without reading
megabytes back into Go memory.

collect_unix.go: fix compile errors (double init in if-stmt, MemorySummary
composite literal using non-existent HeapAlloc/HeapObjects fields,
runtime.MemStats field name TotalPause → PauseTotalNs, LastGC narrowing to
uint32). Unix writeCoreDump matches the new signature and returns an
unimplemented error.

debug.go + types.go: add `doctor` import alias for pkg/doctor-ng
(package is doctorng; code references as doctor.*).

Verified: go build ./pkg/debug/... on linux, windows, and darwin all green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…bug guide

Replace the old Collector / Run() façade with two top-level, stateless
entry points and functional options:

  - debug.Dump(...) writes a minidump of the current process.
    Options: WithPath, WithFullMemory.
    Windows only; returns an error on other platforms.

  - debug.Report(...) collects system, build, process/memory/module,
    and diagnostic info. Opt-in minidump via WithDump, WithDumpPath,
    or WithDumpFullMemory. Returns a *CrashReport with a DumpPath
    field populated only when a dump was requested.

Neither entry point is invoked automatically by wails — PanicHandler
integration is opt-in so crash reporting can be gated on user consent
or PII redaction.

Tests:
  - debug_test.go covers Report population, default DumpPath empty,
    non-Windows Dump returns an error, option composition.
  - dump_windows_test.go (//go:build windows) verifies Dump produces
    a file with the MDMP magic bytes, default path lands under TempDir,
    and Report(WithDumpPath) records the dump path.

Docs:
  - docs/src/content/docs/guides/debugging-crashes.mdx — full guide
    covering quick reference, CrashReport fields, PanicHandler
    integration, manual debugging use cases, minidump flag rationale,
    non-Windows behaviour, and security notes.
  - docs/src/content/docs/guides/panic-handling.mdx — cross-link into
    the new guide from the PanicHandler section.

Build verified on linux, windows, darwin. go test ./pkg/debug/... green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 19, 2026

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: e16b89b4-3dc6-4c15-a16d-2cee5c2e0958

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch debug-package

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Wails Documentation Agent added 2 commits April 21, 2026 19:13
- Fix MemorySummary.TotalVirtual: use OS-level memory APIs instead of
  incorrect TotalAlloc+Mallocs (psapi GetProcessMemoryInfo on Windows,
  /proc/self/status VmSize on Linux)
- Implement loadModules on Windows using CreateToolhelp32Snapshot
  (Module32First/Next) for proper module enumeration
- Implement collectThreadInfo on Windows using CreateToolhelp32Snapshot
  (Thread32First/Next) for thread counting
- Remove dead ThreadInfo.WaitChan chan field, replace with WaitReason
  string that properly serializes to JSON
- Add process handle counting via GetProcessHandleCount on Windows
- Add comprehensive tests for memory, modules, threads, and JSON
  round-trip on both platforms
- Split collect_unix.go build tag from '!windows' to 'linux' since
  /proc only exists on Linux, not macOS
- Add collect_darwin.go with Go runtime fallbacks for macOS
- Remove omitempty from ThreadInfo.WaitReason so the field always
  appears in JSON serialization
- Fix tests to account for platform differences:
  - Module enumeration only tested on Linux and Windows
  - Thread count only asserted on Linux and Windows
  - MemoryBytes only asserted on Linux
  - All platforms still test MemorySummary non-zero (via Go runtime)
@leaanthony leaanthony changed the base branch from v3-alpha to master April 29, 2026 13:08
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