Skip to content

fix(Workspace): fix EXC_BAD_ACCESS caused by over-releasing ghostty font - #1496

Merged
lawrencecchen merged 1 commit into
manaflow-ai:mainfrom
s010s:fix-crash-1452
Mar 17, 2026
Merged

lawrencecchen merged 1 commit into
manaflow-ai:mainfrom
s010s:fix-crash-1452

Conversation

@s010s

@s010s s010s commented Mar 16, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1452.

Root Cause Analysis

According to issue #1452, cmux consistently crashes with EXC_BAD_ACCESS (SIGSEGV) on Intel Macs when creating a new tab (Cmd + T) or splitting a pane (Cmd + D).

The issue stems from the cmuxCurrentSurfaceFontSizePoints function:

let ctFont = Unmanaged<CTFont>.fromOpaque(quicklookFont).takeRetainedValue()

The ghostty_surface_quicklook_font() C API returns an unretained inner pointer (Get semantics). Forcing .takeRetainedValue() incorrectly transfers ownership of this pointer to Swift's ARC. When the variable goes out of scope, ARC attempts to release it, causing an over-release of the underlying font object, which leads to a segmentation fault on certain architectures (like Intel).

Fix

Replaced takeRetainedValue() with takeUnretainedValue() to prevent ARC from consuming the memory reference, fixing the over-release crash


Summary by cubic

Prevent EXC_BAD_ACCESS on Intel Macs when creating a tab (Cmd+T) or splitting a pane (Cmd+D) by fixing CoreText font ownership in cmux. Fixes #1452.

  • Bug Fixes
    • Replace .takeRetainedValue() with .takeUnretainedValue() when converting the pointer from ghostty_surface_quicklook_font() to CTFont (Get semantics) to avoid ARC over-release and the crash.

Written for commit b3bac4f. Summary will update on new commits.

Summary by CodeRabbit

No user-facing changes in this release. This update includes internal optimizations to memory management that improve code reliability without affecting application functionality or user experience.

The ghostty_surface_quicklook_font function returns an unretained pointer to a font object. Using takeRetainedValue() transferred non-existent ownership to ARC, leading to an over-release and an eventual EXC_BAD_ACCESS (SIGSEGV) crash when creating new surfaces (like cmd+t or cmd+d) on certain systems such as Intel Macs.

Replaced takeRetainedValue() with takeUnretainedValue() to correctly manage memory.
@vercel

vercel Bot commented Mar 16, 2026

Copy link
Copy Markdown

Someone is attempting to deploy a commit to the Manaflow Team on Vercel.

A member of the Team first needs to authorize it.

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@coderabbitai

coderabbitai Bot commented Mar 16, 2026 •

Copy link
Copy Markdown
📝 Walkthrough

Walkthrough

A single-line memory management change in Sources/Workspace.swift that switches from takeRetainedValue() to takeUnretainedValue() when obtaining a CoreText font from an opaque pointer, adjusting ownership semantics without modifying control flow or error handling.

Changes

Cohort / File(s) Summary
Memory Management Fix
Sources/Workspace.swift
Changed quicklookFont pointer handling from takeRetainedValue() to takeUnretainedValue(), adjusting CoreText font ownership lifecycle.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

🐰 A rabbit hops through memory lanes,
Where fonts once held in tight refrains,
Now unretained they float so free,
No crash upon the Intel tree! 🌲✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ❓ Inconclusive The description includes root cause analysis, fix explanation, and auto-generated summary, but lacks testing details and checklist completion required by the template. Add testing section describing how the fix was validated (manual testing on Intel Mac, test case if available) and complete the checklist items.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: fixing an EXC_BAD_ACCESS crash by correcting CoreText font memory management in Workspace.
Linked Issues check ✅ Passed The code change directly addresses the root cause in issue #1452 by replacing takeRetainedValue() with takeUnretainedValue() to fix ARC over-release crashes.
Out of Scope Changes check ✅ Passed The change is narrowly scoped to fixing the specific memory management bug in cmuxCurrentSurfaceFontSizePoints without altering unrelated code or behavior.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Tip

CodeRabbit can enforce grammar and style rules using `languagetool`.

Configure the reviews.tools.languagetool setting to enable/disable rules and categories. Refer to the LanguageTool Community to learn more.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No issues found across 1 file


Since this is your first cubic review, here's how it works:

  • cubic automatically reviews your code and comments on bugs and improvements
  • Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
  • Add one-off context when rerunning by tagging @cubic-dev-ai with guidance or docs links (including llms.txt)
  • Ask questions if you need clarification on any suggestion

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
Sources/Workspace.swift (1)

21-30: Fix correctly uses unretained pointer semantics.

The change from takeRetainedValue() to takeUnretainedValue() is correct. The C function ghostty_surface_quicklook_font() returns a borrowed (unretained) reference that the Ghostty library retains ownership of, not the Swift caller. Using takeUnretainedValue() prevents ARC from incorrectly releasing the font. The short scope of ctFont—used only for CTFontGetSize() on line 27—ensures the borrowed reference remains valid.

Consider documenting the ownership semantics to prevent future regressions:

+    // ghostty_surface_quicklook_font returns a borrowed (unretained) pointer;
+    // use takeUnretainedValue so ARC does not release the font.
     let ctFont = Unmanaged<CTFont>.fromOpaque(quicklookFont).takeUnretainedValue()
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@Sources/Workspace.swift` around lines 21 - 30, The change in
cmuxCurrentSurfaceFontSizePoints should keep using
Unmanaged<CTFont>.fromOpaque(...).takeUnretainedValue() because
ghostty_surface_quicklook_font() returns a borrowed (unretained) reference;
ensure the code does not call takeRetainedValue(). Add a brief inline comment
above the Unmanaged call explaining that ghostty_surface_quicklook_font()
returns an unretained/borrrowed CTFont owned by Ghostty so ARC must not release
it, and consider adding a short doc comment on cmuxCurrentSurfaceFontSizePoints
to record the ownership semantics to prevent future regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@Sources/Workspace.swift`:
- Around line 21-30: The change in cmuxCurrentSurfaceFontSizePoints should keep
using Unmanaged<CTFont>.fromOpaque(...).takeUnretainedValue() because
ghostty_surface_quicklook_font() returns a borrowed (unretained) reference;
ensure the code does not call takeRetainedValue(). Add a brief inline comment
above the Unmanaged call explaining that ghostty_surface_quicklook_font()
returns an unretained/borrrowed CTFont owned by Ghostty so ARC must not release
it, and consider adding a short doc comment on cmuxCurrentSurfaceFontSizePoints
to record the ownership semantics to prevent future regressions.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 9ab705b9-af52-4a06-9312-263993bbcfa6

📥 Commits

Reviewing files that changed from the base of the PR and between 2e4c482 and b3bac4f.

📒 Files selected for processing (1)
  • Sources/Workspace.swift

@gqueiroz13 gqueiroz13 mentioned this pull request Mar 17, 2026
@lawrencecchen
lawrencecchen merged commit 66f8f8b into manaflow-ai:main Mar 17, 2026
3 of 4 checks passed
@gqueiroz13

Copy link
Copy Markdown

Thank you mate!!!

elvistranhere added a commit to elvistranhere/cmux that referenced this pull request Mar 21, 2026
…le 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
manaflow-ai#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.
@greptile-apps greptile-apps Bot mentioned this pull request Mar 23, 2026
4 of 6 tasks
kokagex added a commit to kokagex/cmux that referenced this pull request Mar 28, 2026
…ed config

ghostty_surface_inherited_config() returns a config struct containing raw C
pointers (env_vars, working_directory, command) owned by the source surface.
On Intel x86_64, freed memory is recycled more aggressively than ARM64,
causing EXC_BAD_ACCESS when the new pane dereferences these stale pointers
during createSurface().

Three-layer fix:
- cmuxInheritedSurfaceConfig() now rebuilds a clean config with only font_size,
  matching the pattern already used in TabManager.workspaceCreationConfigTemplate()
- Added cmuxSurfacePointerAppearsLive() guard before ghostty_surface_inherited_config()
- Added malloc_size validation for env_vars pointer in createSurface() as defense-in-depth

Fixes manaflow-ai#1496, manaflow-ai#1870

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
…ont (manaflow-ai#1496)

The ghostty_surface_quicklook_font function returns an unretained pointer to a font object. Using takeRetainedValue() transferred non-existent ownership to ARC, leading to an over-release and an eventual EXC_BAD_ACCESS (SIGSEGV) crash when creating new surfaces (like cmd+t or cmd+d) on certain systems such as Intel Macs.

Replaced takeRetainedValue() with takeUnretainedValue() to correctly manage memory.

Co-authored-by: LeonLeung <leonleung.tech@gmail.com>
bn-l pushed a commit to bn-l/cmux that referenced this pull request Apr 3, 2026
…le 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
manaflow-ai#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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash on any new surface creation (tab, split) on Intel Mac — SIGSEGV in inheritedTerminalConfig

3 participants