Fix #1870: prevent split crash on Intel Macs caused by stale font pointer
ghostty_surface_quicklook_font returns an unretained CTFont pointer that can become stale on Intel Macs, leading to EXC_BAD_ACCESS (SIGSEGV) when creating a split. This is a follow-up to the same crash pattern fixed in #1496. Add malloc_size validation in cmuxCurrentSurfaceFontSizePoints to detect freed heap allocations before interpreting the pointer as a CTFont. Also add hasLiveSurface guards in inheritedTerminalConfig and rememberTerminalConfigInheritanceSource to skip surfaces whose native state is closing or closed. All callers already handle nil gracefully by falling back to inherited config values.
This commit is contained in:
parent
6ff81579d9
commit
b1b07bf55b
2 changed files with 20 additions and 2 deletions
|
|
@ -2677,6 +2677,15 @@ final class TerminalSurface: Identifiable, ObservableObject {
|
|||
|
||||
private(set) var surface: ghostty_surface_t?
|
||||
private weak var attachedView: GhosttyNSView?
|
||||
|
||||
/// Whether the runtime Ghostty surface exists and has not begun teardown.
|
||||
///
|
||||
/// Use this before passing `surface` to Ghostty C APIs that dereference the
|
||||
/// pointer (e.g. `ghostty_surface_inherited_config`, `ghostty_surface_quicklook_font`).
|
||||
/// A non-nil `surface` alone is not sufficient — the underlying native state may
|
||||
/// already be closing or closed.
|
||||
var hasLiveSurface: Bool { surface != nil && portalLifecycleState == .live }
|
||||
|
||||
/// Whether the terminal surface view is currently attached to a window.
|
||||
///
|
||||
/// Use the hosted view rather than the inner surface view, since the surface can be
|
||||
|
|
|
|||
|
|
@ -26,6 +26,13 @@ func cmuxCurrentSurfaceFontSizePoints(_ surface: ghostty_surface_t) -> Float? {
|
|||
return nil
|
||||
}
|
||||
|
||||
// Validate the font pointer is a live heap allocation before interpreting
|
||||
// it as a CTFont. ghostty_surface_quicklook_font returns an unretained
|
||||
// pointer that can become stale on Intel Macs (#1496, #1870).
|
||||
guard malloc_size(quicklookFont) > 0 else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let ctFont = Unmanaged<CTFont>.fromOpaque(quicklookFont).takeUnretainedValue()
|
||||
let points = Float(CTFontGetSize(ctFont))
|
||||
guard points > 0 else { return nil }
|
||||
|
|
@ -6797,7 +6804,8 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
|
||||
private func rememberTerminalConfigInheritanceSource(_ terminalPanel: TerminalPanel) {
|
||||
lastTerminalConfigInheritancePanelId = terminalPanel.id
|
||||
if let sourceSurface = terminalPanel.surface.surface,
|
||||
if terminalPanel.surface.hasLiveSurface,
|
||||
let sourceSurface = terminalPanel.surface.surface,
|
||||
let runtimePoints = cmuxCurrentSurfaceFontSizePoints(sourceSurface) {
|
||||
let existing = terminalInheritanceFontPointsByPanelId[terminalPanel.id]
|
||||
if existing == nil || abs((existing ?? runtimePoints) - runtimePoints) > 0.05 {
|
||||
|
|
@ -6895,7 +6903,8 @@ final class Workspace: Identifiable, ObservableObject {
|
|||
preferredPanelId: preferredPanelId,
|
||||
inPane: preferredPaneId
|
||||
) {
|
||||
guard let sourceSurface = terminalPanel.surface.surface else { continue }
|
||||
guard terminalPanel.surface.hasLiveSurface,
|
||||
let sourceSurface = terminalPanel.surface.surface else { continue }
|
||||
var config = cmuxInheritedSurfaceConfig(
|
||||
sourceSurface: sourceSurface,
|
||||
context: GHOSTTY_SURFACE_CONTEXT_SPLIT
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue