crashlog.rs

crates/veilvoice-gui/src/crashlog.rs

veilvoice-gui · 447 lines · read the source here · or on GitHub

Make a failure that produces no output produce some.

The problem this exists for

veilvoice-gui is built with windows_subsystem = "windows", so it has no console, and the workspace builds with panic = "abort", so a panic does not unwind into anything that could report it. Put together, every way this application can fail on Windows produces exactly nothing: no message, no dialog, no log. The window appears or it does not.

That is not hypothetical. A release shipped and the report was "it flashes a command prompt, loads in an unusable state, and crashes" -- which is all a user can report, because the program tells them nothing. The console flash turned out to be subprocesses (see no_window in crate::reduced_motion), and the crash could not be diagnosed at all from what was observable.

What this does about it

Two failures are caught and written to a file beside the preferences:

  • A panic, through a hook. The hook runs before abort even under panic = "abort", so there is a window in which to write.
  • A startup failure from eframe, which is a returned Err rather than a panic and is otherwise printed to a stderr nobody can see.

The second is the one worth expecting. This application renders through glow, which is OpenGL, and creating a GL context depends on the graphics driver. In a virtual machine, over a remote desktop session, or on a laptop whose hybrid graphics hand the process the wrong adapter, that call fails -- and the honest answer to "why did nothing happen?" needs to survive the process exiting.

What it deliberately does not do

It does not report anything anywhere. The file is written next to the preferences, on the user's own disk, and stays there until they delete it or the application clears it. A privacy tool that phones home about its own crashes would be exactly the thing this project spends its documentation refusing to be, and there is no network code in the dependency graph to do it with even if that changed.

It records no user content. A panic message, a source location, the version and a timestamp. Not the file being processed, not a path the user chose, not a passphrase -- nothing that is theirs.

In plain words

Makes sure that if VeilVoice falls over, it leaves something behind saying so.

A windowed program on Windows has nowhere to print to. Without this, a failure at startup produces a window that never appears and no message anywhere, and the only thing anybody can report is "it crashed", which is exactly the report that arrived once.

So the reason is written to a file, and the file is shown to you next time the application opens. It stays on your machine and is never sent anywhere.

WHAT THIS FILE CONTAINS

447 lines defining 9 functions (6 public), 0 types and 0 constants. Everything below is read out of the source, so it cannot disagree with the code.

What happens when it runs. These are the ways in: public, and nothing else in this file calls them, so they are what an outside caller reaches first.

  • install line 195 · Install the panic hook.
    reaches default_path, previous, write, advice, stamp, missing_library
  • record_startup_failure line 218 · Record a startup failure that eframe returned rather than panicked.
    reaches default_path, write, advice, stamp, missing_library
  • clear line 232 · Forget a previous report.
    reaches default_path

WHAT CALLS WHAT

default_path line 64 stamp line 74 write line 87 advice line 149 missing_library line 179 install line 195 record_startup_failure line 218 previous line 225 clear line 232 entry: a way in: public, and nothing in this file calls it api: public, and also used inside this file helper: private to this file dashed: a call that goes back up, or across a wrapped rank The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The functions this file defines, and the calls between them. An edge means the callee's name appears, called, inside the caller's body. This is a syntactic reading, not a type-resolved one.

The same graph as Mermaid source
%%{init: {"theme":"base","themeVariables":{"background":"#1a1b26","primaryColor":"#1f2335","primaryTextColor":"#c0caf5","primaryBorderColor":"#7aa2f7","secondaryColor":"#16161e","tertiaryColor":"#16161e","lineColor":"#737aa2","textColor":"#c0caf5","mainBkg":"#1f2335","nodeBorder":"#7aa2f7","clusterBkg":"#16161e","clusterBorder":"#2f3549","fontFamily":"ui-monospace, SFMono-Regular, Consolas, monospace","fontSize":"14px"}}}%%
flowchart TD
    n_default_path["default_path<br/>line 64"]
    n_stamp["stamp<br/>line 74"]
    n_write["write<br/>line 87"]
    n_advice["advice<br/>line 149"]
    n_missing_library["missing_library<br/>line 179"]
    n_install(["install<br/>line 195"])
    n_record_startup_failure(["record_startup_failure<br/>line 218"])
    n_previous["previous<br/>line 225"]
    n_clear(["clear<br/>line 232"])
    n_advice --> n_missing_library
    n_clear --> n_default_path
    n_install --> n_default_path
    n_install --> n_previous
    n_install --> n_write
    n_previous --> n_default_path
    n_record_startup_failure --> n_default_path
    n_record_startup_failure --> n_write
    n_write --> n_advice
    n_write --> n_stamp
    click n_default_path href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L64" "open the source"
    click n_stamp href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L74" "open the source"
    click n_write href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L87" "open the source"
    click n_advice href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L149" "open the source"
    click n_missing_library href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L179" "open the source"
    click n_install href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L195" "open the source"
    click n_record_startup_failure href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L218" "open the source"
    click n_previous href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L225" "open the source"
    click n_clear href "https://github.com/tilas01/veilvoice/blob/main/crates/veilvoice-gui/src/crashlog.rs#L232" "open the source"
    classDef entry fill:#1f2335,stroke:#7aa2f7,color:#c0caf5
    class n_install,n_record_startup_failure,n_clear entry
    classDef api fill:#1f2335,stroke:#7dcfff,color:#c0caf5
    class n_default_path,n_write,n_previous api
    classDef helper fill:#1f2335,stroke:#bb9af7,color:#c0caf5
    class n_stamp,n_advice,n_missing_library helper

This site loads no third-party script, so it cannot run Mermaid; the diagram above is the same nodes and edges drawn by the generator instead. GitHub renders the source below directly.

ITEMS

ItemLineDocumentation
default_path pub fn64The file a failure is written to, beside the preferences.
stamp fn74Seconds since the Unix epoch, or 0 if the clock is unreadable.
write pub fn87Write one failure report.
advice fn149The paragraph that tries to be useful about this failure.
missing_library fn179The name of the shared library a panic message says could not be loaded.
install pub fn195Install the panic hook.
record_startup_failure pub fn218Record a startup failure that eframe returned rather than panicked.
previous pub fn225Read a previous report, if one is there, so the interface can mention it.
clear pub fn232Forget a previous report.