Attempt to fix segfault in window drop (cherry-pick #10690) (#10701)

gcp-cherry-pick-bot[bot] and Conrad Irwin created

Cherry-picked 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.

Co-authored-by: Conrad Irwin <conrad.irwin@gmail.com>

Change summary

crates/gpui/src/platform/mac/window.rs | 29 +++++++++++++--------------
1 file changed, 14 insertions(+), 15 deletions(-)

Detailed changes

crates/gpui/src/platform/mac/window.rs 🔗

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