fix(desktop): exit cleanly on fatal setup errors instead of SIGABRT

Setup errors inside tao's `did_finish_launching` FFI callback propagate
as `Err` to Tauri's `panic!("Failed to setup app: {e}")`. Because Rust
cannot unwind across an `extern "C"` boundary, this escalates to
`panic_cannot_unwind` → SIGABRT. macOS treats SIGABRT as a crash and
auto-relaunches the app, producing a 6-crash pile-up before giving up.
This is a known upstream issue (tao#1171, still open).

Convert the two fatal `?` operators in the setup closure (identity
resolution and keys mutex access) to explicit `eprintln! +
process::exit(1)`. A clean exit produces no crash report and macOS does
not auto-relaunch, breaking the crash-loop.
This commit is contained in:
Will Pfleger
2026-07-14 19:28:47 -04:00
parent af190c93e1
commit 1ffd2b1d78

View File

@@ -423,8 +423,10 @@ pub fn run() {
// that will be lost on restart, as that silently breaks channel
// memberships, DMs, and relay identity.
let state = app_handle.state::<AppState>();
resolve_persisted_identity(&app_handle, &state)
.map_err(|e| -> Box<dyn std::error::Error> { e.into() })?;
if let Err(e) = resolve_persisted_identity(&app_handle, &state) {
eprintln!("buzz-desktop: fatal: identity resolution failed: {e}");
std::process::exit(1);
}
// When the identity is in recovery mode (lost = keyring empty after
// migration, or keyring-locked = keyring unreachable but marker
@@ -441,11 +443,13 @@ pub fn run() {
// Snapshot owner keys after identity resolution; the best-effort
// event reconcile itself runs off the synchronous setup path below.
let owner_keys = state
.keys
.lock()
.map(|k| k.clone())
.map_err(|e| -> Box<dyn std::error::Error> { e.to_string().into() })?;
let owner_keys = match state.keys.lock() {
Ok(k) => k.clone(),
Err(e) => {
eprintln!("buzz-desktop: fatal: identity keys poisoned: {e}");
std::process::exit(1);
}
};
// Backfill the pinned persona snapshot for any pre-existing agent
// that predates the record-authoritative-spawn cutover (persona_id