std/crash

Crash reports. When a program crashes outside Cuarzo's own errors, in a C library or the system, the handler writes a report: what happened (the signal on Linux and macOS, the exception on Windows), the build information, the Cuarzo functions that were running, as a runtime error shows them, and the native trace; on Windows a minidump goes beside it, for a debugger. The program then ends as it would have. The next time it starts, it can offer to send the reports.

import "std/crash"
import "std/prompt"

str dir = crash_reports_dir("notes")
install_crash_reporter(dir, "Notes")
for report in pending_crash_reports(dir) do
    if confirm("Notes crashed: " + report.summary() + ". Send the report?", false) then
        send_crash_report(report, "https://example.com/crashes")?
    end
    dismiss_crash_report(report)
end
Function Result
install_crash_reporter(dir, app, version) reports crashes from now on to dir, made if needed, with app, version (build_version() unless given), the commit and time it was built, and the system
crash_reports_dir(app) crashes in the application's folder of the user's data
pending_crash_reports(dir) the reports not yet dismissed, oldest first: each a CrashReport with its path, text, and dump, the minidump's path or "", and summary() and time()
send_crash_report(r, url), crash_report_json(r) the report as JSON, the minidump in base64, sent with POST; an ERROR of kind "http" when it is not taken
dismiss_crash_report(r) deletes the report and its minidump
crash_for_test(kind) crashes, to try the reporter: "segv", "abort", "overflow", or "fpe"

The handler writes without allocating, as a signal handler must, and on a stack of its own, so a stack that ran out is reported too. The native trace comes from backtrace on glibc and macOS (none with musl) and from CaptureStackBackTrace on Windows, as module and offset.