Summary
On macOS, screenpipe-app crashes with SIGSEGV inside onnxruntime when the auto-updater triggers tauri::AppHandle::restart() while the audio manager is still loading the speaker-recognition ONNX model. Looks like a race between process teardown (C++ static destructors in onnxruntime firing from exit) and the screenpipe-server worker thread still initializing the speaker embedding session.
Environment
- screenpipe version: 2.4.258
- OS: macOS 26.5 (Apple Silicon, arm64)
- Install: signed release build from the
.app bundle
What happened
- App had been running ~1h 20min.
- Auto-update kicked in (
screenpipe_app::updates::UpdatesManager::check_for_updates → tauri::AppHandle::restart → std::process::exit).
- While the main thread was exiting and running
__cxa_finalize_ranges (C++ static destructors), the screenpipe-server worker thread was still inside AudioManager::new, calling get_or_download_model_with_retries → speaker::create_session → ORT CreateSession → InferenceSession::Initialize.
- The onnxruntime graph planner tried to look up a type in the global
DataTypeRegistry that had already been (or was being) torn down by the exiting main thread, dereferenced a near-null pointer, and segfaulted.
Crash signature
Exception Type: EXC_BAD_ACCESS (SIGSEGV)
Exception Subtype: KERN_INVALID_ADDRESS at 0x00000000000002c8
Triggered by Thread: screenpipe-server
Faulting thread (trimmed):
0 onnxruntime std::__1::__hash_table<... DataTypeImpl ...>::find(...) + 128
1 onnxruntime onnxruntime::DataTypeImpl::TypeFromProto(onnx::TypeProto const&) + 64
2 onnxruntime onnxruntime::PlannerImpl::GetElementSize(...) + 24
3 onnxruntime onnxruntime::PlannerImpl::SameSize(...) + 84
4 onnxruntime onnxruntime::PlannerImpl::FindReusableTensor(...) + 348
5 onnxruntime onnxruntime::PlannerImpl::ComputeSingleStreamReusePlan(...) + 1112
6 onnxruntime onnxruntime::PlannerImpl::ComputeReusePlan() + 380
7 onnxruntime onnxruntime::PlannerImpl::CreatePlan(...) + 416
8 onnxruntime onnxruntime::SequentialPlanner::CreatePlan(...) + 340
9 onnxruntime onnxruntime::SessionState::FinalizeSessionStateImpl(...) + 796
10 onnxruntime onnxruntime::SessionState::FinalizeSessionState(...) + 1256
11 onnxruntime onnxruntime::InferenceSession::Initialize() + 5884
12 onnxruntime InitializeSession(...) + 1964
13 onnxruntime OrtApis::CreateSession(...) + 88
14 ort SessionBuilder::commit_from_file_inner + 616
15 screenpipe_audio::speaker::create_session + 1152
16 screenpipe_audio::speaker::models::get_or_download_model_with_retries (closure)
17 screenpipe_audio::audio_manager::manager::AudioManager::new (closure)
18 screenpipe_app::server_core::ServerCore::start (closure)
Meanwhile, main thread (thread 0) was exiting via the updater:
0 onnxruntime ~OptionalType() / static dtor
1 libsystem_c __cxa_finalize_ranges + 416
2 libsystem_c exit + 44
3 std::sys::pal::unix::os::exit
4 std::process::exit
5 tauri::process::restart + 2960
And another tokio worker was sleeping inside tauri::AppHandle::restart (called from UpdatesManager::check_for_updates), confirming the restart-during-init scenario.
Root cause (suspected)
tauri::AppHandle::restart() calls std::process::exit, which runs C++ static destructors in onnxruntime. The global DataTypeRegistry (singleton accessed via DataTypeImpl::TypeFromProto) gets destroyed, but the audio-manager worker is mid-CreateSession and dereferences the now-invalid registry.
Suggested fix directions
- Make audio-manager / speaker-model init cancellation-aware, so that on a restart signal
AudioManager::new can be aborted before calling into ORT CreateSession.
- Have
UpdatesManager wait for ServerCore::start to reach a stable state (or signal it to cancel) before invoking AppHandle::restart.
- At minimum, gate the restart on a "startup complete" flag so it can't fire during initial model load.
Reproduction
Not deterministic, but: launch a fresh install (so models need downloading / first-time session init), let it sit until the updater finds a new version. The narrower the window between app start and update-check firing, the more likely you hit this.
Impact
App dies hard mid-update; on next launch it has to redo the speaker-model session init from scratch. No data loss observed.
Summary
On macOS, screenpipe-app crashes with
SIGSEGVinside onnxruntime when the auto-updater triggerstauri::AppHandle::restart()while the audio manager is still loading the speaker-recognition ONNX model. Looks like a race between process teardown (C++ static destructors in onnxruntime firing fromexit) and thescreenpipe-serverworker thread still initializing the speaker embedding session.Environment
.appbundleWhat happened
screenpipe_app::updates::UpdatesManager::check_for_updates→tauri::AppHandle::restart→std::process::exit).__cxa_finalize_ranges(C++ static destructors), thescreenpipe-serverworker thread was still insideAudioManager::new, callingget_or_download_model_with_retries→speaker::create_session→ ORTCreateSession→InferenceSession::Initialize.DataTypeRegistrythat had already been (or was being) torn down by the exiting main thread, dereferenced a near-null pointer, and segfaulted.Crash signature
Faulting thread (trimmed):
Meanwhile, main thread (thread 0) was exiting via the updater:
And another tokio worker was sleeping inside
tauri::AppHandle::restart(called fromUpdatesManager::check_for_updates), confirming the restart-during-init scenario.Root cause (suspected)
tauri::AppHandle::restart()callsstd::process::exit, which runs C++ static destructors in onnxruntime. The globalDataTypeRegistry(singleton accessed viaDataTypeImpl::TypeFromProto) gets destroyed, but the audio-manager worker is mid-CreateSessionand dereferences the now-invalid registry.Suggested fix directions
AudioManager::newcan be aborted before calling into ORTCreateSession.UpdatesManagerwait forServerCore::startto reach a stable state (or signal it to cancel) before invokingAppHandle::restart.Reproduction
Not deterministic, but: launch a fresh install (so models need downloading / first-time session init), let it sit until the updater finds a new version. The narrower the window between app start and update-check firing, the more likely you hit this.
Impact
App dies hard mid-update; on next launch it has to redo the speaker-model session init from scratch. No data loss observed.