fix(electron): potential app crash on quit (#12480)

<!-- This is an auto-generated comment: release notes by coderabbit.ai -->

## Summary by CodeRabbit

- **Bug Fixes**
	- Improved stability during shutdown by preventing potential crashes when removing audio property listeners on macOS.
	- Suppressed unnecessary error logs related to device listener removal during system shutdown.
	- Enhanced handling of internal subscriptions to avoid redundant operations and improve reliability when loading or destroying views.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
pengx17
2025-05-27 03:43:27 +00:00
parent bfe743b68b
commit ed8e50bca6
3 changed files with 47 additions and 19 deletions

View File

@@ -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),
);
}
});
}
}
}

View File

@@ -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
}
}
}