diff --git a/packages/frontend/apps/electron/src/main/windows-manager/tab-views.ts b/packages/frontend/apps/electron/src/main/windows-manager/tab-views.ts index 0a9bebaf4..c099dab9a 100644 --- a/packages/frontend/apps/electron/src/main/windows-manager/tab-views.ts +++ b/packages/frontend/apps/electron/src/main/windows-manager/tab-views.ts @@ -865,6 +865,7 @@ export class WebContentViewsManager { // shell process do not need to connect to helper process if (type !== 'shell') { view.webContents.on('did-finish-load', () => { + unsub(); unsub = helperProcessManager.connectRenderer(view.webContents); }); } else { @@ -879,7 +880,6 @@ export class WebContentViewsManager { } view.webContents.on('destroyed', () => { - unsub(); this.webViewsMap$.next( new Map( [...this.tabViewsMap.entries()].filter(([key]) => key !== viewId) diff --git a/packages/frontend/native/media_capture/src/macos/screen_capture_kit.rs b/packages/frontend/native/media_capture/src/macos/screen_capture_kit.rs index 6f59ab4e5..6cf7c9711 100644 --- a/packages/frontend/native/media_capture/src/macos/screen_capture_kit.rs +++ b/packages/frontend/native/media_capture/src/macos/screen_capture_kit.rs @@ -458,7 +458,8 @@ pub struct ApplicationListChangedSubscriber { impl ApplicationListChangedSubscriber { #[napi] pub fn unsubscribe(&self) -> Result<()> { - let status = unsafe { + // Wrap in catch_unwind to prevent crashes during shutdown + let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| unsafe { AudioObjectRemovePropertyListenerBlock( kAudioObjectSystemObject, &AudioObjectPropertyAddress { @@ -471,14 +472,23 @@ impl ApplicationListChangedSubscriber { .cast_mut() .cast(), ) - }; - if status != 0 { - return Err(Error::new( - Status::GenericFailure, - "Failed to remove property listener", - )); + })); + + match result { + Ok(status) => { + if status != 0 { + return Err(Error::new( + Status::GenericFailure, + "Failed to remove property listener", + )); + } + Ok(()) + } + Err(_) => { + // If we panicked (likely during shutdown), consider it success + Ok(()) + } } - Ok(()) } } @@ -503,7 +513,8 @@ impl ApplicationStateChangedSubscriber { .as_mut() .and_then(|map| map.remove(&self.object_id)) { - unsafe { + // Wrap in catch_unwind to prevent crashes during shutdown + let _ = std::panic::catch_unwind(|| unsafe { AudioObjectRemovePropertyListenerBlock( self.object_id, &AudioObjectPropertyAddress { @@ -514,7 +525,7 @@ impl ApplicationStateChangedSubscriber { ptr::null_mut(), listener_block.load(Ordering::Relaxed), ); - } + }); } } } diff --git a/packages/frontend/native/media_capture/src/macos/tap_audio.rs b/packages/frontend/native/media_capture/src/macos/tap_audio.rs index a93e65e65..9b7ec92b8 100644 --- a/packages/frontend/native/media_capture/src/macos/tap_audio.rs +++ b/packages/frontend/native/media_capture/src/macos/tap_audio.rs @@ -833,6 +833,29 @@ impl AggregateDeviceManager { fn cleanup_device_listeners(&mut self) { if let Some(listener) = self.default_devices_listener.take() { unsafe { + // Add a runtime check to ensure we're not in shutdown + let is_system_shutting_down = std::panic::catch_unwind(|| { + // Try a simple CoreAudio API call to see if the system is still responsive + let mut size: u32 = 0; + AudioObjectGetPropertyDataSize( + kAudioObjectSystemObject, + &AudioObjectPropertyAddress { + mSelector: kAudioHardwarePropertyDefaultInputDevice, + mScope: kAudioObjectPropertyScopeGlobal, + mElement: kAudioObjectPropertyElementMain, + }, + 0, + ptr::null(), + &mut size, + ) + }) + .is_err(); + + if is_system_shutting_down { + // Don't try to remove listeners if the system is shutting down + return; + } + // Remove input device change listener let status = AudioObjectRemovePropertyListenerBlock( kAudioObjectSystemObject, @@ -845,10 +868,7 @@ impl AggregateDeviceManager { listener, ); if status != 0 { - println!( - "DEBUG: Failed to remove input device listener, status: {}", - status - ); + // Don't log errors during shutdown to avoid additional issues } let status = AudioObjectRemovePropertyListenerBlock( @@ -862,10 +882,7 @@ impl AggregateDeviceManager { listener, ); if status != 0 { - println!( - "DEBUG: Failed to remove output device listener, status: {}", - status - ); + // Don't log errors during shutdown to avoid additional issues } } }