Attempt to fix segfault in window drop (#10690)

By default NSWindow's release themselves when closed, which doesn't
interact well with rust's lifetime system.

Disable that behaviour, and explicitly release the NSWindow when the
window handle is dropped.

Release Notes:

- Fixed a (rare) panic when closing a window.
This commit is contained in:
Conrad Irwin 2024-04-17 15:29:10 -06:00 committed by GitHub
parent b9e0269991
commit 41c8f2caa6
No known key found for this signature in database
GPG key ID: B5690EEEBB952194

View file

@ -337,7 +337,6 @@ struct MacWindowState {
handle: AnyWindowHandle, handle: AnyWindowHandle,
executor: ForegroundExecutor, executor: ForegroundExecutor,
native_window: id, native_window: id,
native_window_was_closed: bool,
native_view: NonNull<Object>, native_view: NonNull<Object>,
display_link: Option<DisplayLink>, display_link: Option<DisplayLink>,
renderer: renderer::Renderer, renderer: renderer::Renderer,
@ -605,6 +604,10 @@ impl MacWindow {
registerForDraggedTypes: registerForDraggedTypes:
NSArray::arrayWithObject(nil, NSFilenamesPboardType) NSArray::arrayWithObject(nil, NSFilenamesPboardType)
]; ];
let () = msg_send![
native_window,
setReleasedWhenClosed: NO
];
let native_view: id = msg_send![VIEW_CLASS, alloc]; let native_view: id = msg_send![VIEW_CLASS, alloc];
let native_view = NSView::init(native_view); let native_view = NSView::init(native_view);
@ -622,7 +625,6 @@ impl MacWindow {
handle, handle,
executor, executor,
native_window, native_window,
native_window_was_closed: false,
native_view: NonNull::new_unchecked(native_view), native_view: NonNull::new_unchecked(native_view),
display_link: None, display_link: None,
renderer: renderer::new_renderer( renderer: renderer::new_renderer(
@ -770,20 +772,18 @@ impl Drop for MacWindow {
this.renderer.destroy(); this.renderer.destroy();
let window = this.native_window; let window = this.native_window;
this.display_link.take(); this.display_link.take();
if !this.native_window_was_closed {
unsafe { unsafe {
this.native_window.setDelegate_(nil); this.native_window.setDelegate_(nil);
} }
this.executor this.executor
.spawn(async move { .spawn(async move {
unsafe { unsafe {
window.close(); window.close();
window.autorelease();
} }
}) })
.detach(); .detach();
} }
}
} }
impl PlatformWindow for MacWindow { impl PlatformWindow for MacWindow {
@ -1592,7 +1592,6 @@ extern "C" fn close_window(this: &Object, _: Sel) {
let close_callback = { let close_callback = {
let window_state = get_window_state(this); let window_state = get_window_state(this);
let mut lock = window_state.as_ref().lock(); let mut lock = window_state.as_ref().lock();
lock.native_window_was_closed = true;
lock.close_callback.take() lock.close_callback.take()
}; };