mirror of
https://github.com/ghostty-org/ghostty.git
synced 2026-07-31 04:39:01 +00:00
macOS: free surface synchronously in deinit on main thread (#13364)
Since the renderer thread now emits scrollbar events on almost every frame, there's always a `.scrollbar` message for the dying surface in the app mailbox. The OS runtime seems to schedule `appTick` and `ghostty_surface_free` differently across macOS pre-26, 26 and 27. On macOS 26.x, `ghostty_app_free` happens after `App.scrollbar(_:target:v:)`, leaving `surface.userdata` pointing at a freed `SurfaceView`. When `deinit` runs on the main thread, free the surface synchronously instead of detaching to a task. This fixes both crashes mentioned in https://github.com/ghostty-org/ghostty/pull/9512 and https://github.com/ghostty-org/ghostty/issues/13359. ### AI Disclosure I used Claude to analyze the backtrace, but the code is written and tested by myself.
This commit is contained in:
@@ -24,6 +24,13 @@ extension Ghostty {
|
||||
}
|
||||
|
||||
deinit {
|
||||
guard !Thread.isMainThread else {
|
||||
// The surface remains registered with the app and holds unretained
|
||||
// userdata until it is freed. When already on the main thread, free
|
||||
// it synchronously so teardown completes before we disappear.
|
||||
ghostty_surface_free(surface)
|
||||
return
|
||||
}
|
||||
// deinit is not guaranteed to happen on the main actor and our API
|
||||
// calls into libghostty must happen there so we capture the surface
|
||||
// value so we don't capture `self` and then we detach it in a task.
|
||||
|
||||
Reference in New Issue
Block a user