Skip to content

Add ghostty_surface_set_userdata setter#70

Open
b1nhm1nh wants to merge 1 commit into
manaflow-ai:mainfrom
b1nhm1nh:cmux-surface-set-userdata
Open

Add ghostty_surface_set_userdata setter#70
b1nhm1nh wants to merge 1 commit into
manaflow-ai:mainfrom
b1nhm1nh:cmux-surface-set-userdata

Conversation

@b1nhm1nh

@b1nhm1nh b1nhm1nh commented Jun 2, 2026

Copy link
Copy Markdown

Summary

Adds a ghostty_surface_set_userdata C API export so embedders can clear (or change) the userdata pointer associated with a surface. The embedded apprt already exposed ghostty_surface_userdata (getter) but no setter.

GHOSTTY_API void  ghostty_surface_set_userdata(ghostty_surface_t, void*);
export fn ghostty_surface_set_userdata(surface: *Surface, userdata: ?*anyopaque) void {
    surface.userdata = userdata;
}

Motivation

A host that stores a retained heap object as the surface userdata has no way to detach it before freeing that object. This matters because a surface can outlive the host-side userdata:

  • The host releases its callback-context object (e.g. on surface re-create or teardown) while the native Surface is still alive.
  • A previously-queued mailbox action (e.g. scrollbar from Surface.updateScrollbar) then drains in App.drainMailboxsurfaceMessage (which validates the *Surface with hasSurface(), so it passes) → the host action callback.
  • The callback calls ghostty_surface_userdata() and gets the freed pointer back, then dereferences it → use-after-free crash.

hasSurface() guards the surface pointer but cannot know the host freed the userdata. With a setter, the host can null the userdata at release time and callbacks safely see null.

This is the upstream half of a fix for an intermittent EXC_BAD_ACCESS we hit in cmux (GhosttyApp.handleAction → freed callback context). The cmux side calls ghostty_surface_set_userdata(surface, nil) before releasing its context on the paths where the surface survives.

Changes

  • src/apprt/embedded.zig — new ghostty_surface_set_userdata export next to the existing getter.
  • include/ghostty.h — matching declaration.

Risk

Minimal: a single field assignment, additive API, no behavior change for existing callers. null is a valid value (detaches userdata).


View with Codesmith Autofix with Codesmith
Need help on this PR? Tag /codesmith with what you need. Autofix is disabled.


Summary by cubic

Adds a ghostty_surface_set_userdata(ghostty_surface_t, void*) C API so embedders can clear or change a surface’s userdata. This lets hosts detach freed callback contexts and prevents use‑after‑free when queued callbacks read ghostty_surface_userdata() after teardown.

Written for commit 9254edc. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features
    • Added ghostty_surface_set_userdata() C API function for embedded development. This new function enables developers to set and manage custom userdata pointers associated with surface objects. It complements the existing userdata getter functionality, providing bidirectional access to surface-attached data. The function supports null values for detaching custom data associations.

Hosts that retain a heap object as the surface userdata need to clear it
before freeing that object. A surface can outlive its host-side userdata
(e.g. a queued mailbox action drains after the host released its callback
context), and surface callbacks would then hand back a dangling pointer.
The existing API only exposed a getter. Add a setter so the host can detach
(null) the userdata at release time.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: efe3bc1c-ec59-4ad6-afe0-9a5de253c295

📥 Commits

Reviewing files that changed from the base of the PR and between 15b877e and 9254edc.

📒 Files selected for processing (2)
  • include/ghostty.h
  • src/apprt/embedded.zig

📝 Walkthrough

Walkthrough

This PR adds a new C API function, ghostty_surface_set_userdata, that allows embedders to set a userdata pointer on a ghostty_surface_t. The change includes the public declaration and implementation that assigns the pointer directly to the surface's userdata field.

Changes

Surface Userdata Setter

Layer / File(s) Summary
Surface userdata setter API
include/ghostty.h, src/apprt/embedded.zig
Declares and implements ghostty_surface_set_userdata, enabling embedders to attach or detach (via null) a userdata pointer on a Surface, complementing the existing getter.

Estimated code review effort

🎯 1 (Trivial) | ⏱️ ~3 minutes

Poem

🐰 A surface now remembers what you store,
A little pointer, nothing more!
Set it once, or clear it clean,
Simplest getter-setter we've seen. ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately and concisely summarizes the main change: adding a setter function for ghostty_surface_set_userdata, which directly matches the primary objective of this pull request.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@greptile-apps

greptile-apps Bot commented Jun 2, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds ghostty_surface_set_userdata, a companion setter to the existing ghostty_surface_userdata getter in the embedded apprt C API, so host embedders can null out a surface's userdata pointer before freeing the associated callback-context object.

  • src/apprt/embedded.zig: exports ghostty_surface_set_userdata(surface, userdata) as a one-line field assignment directly next to the getter; the Zig parameter is correctly typed ?*anyopaque (nullable).
  • include/ghostty.h: adds the matching GHOSTTY_API void ghostty_surface_set_userdata(ghostty_surface_t, void*) declaration; placement and style are consistent with the surrounding surface API.

Confidence Score: 5/5

Additive, one-line change that mirrors an existing getter; no existing call paths are altered.

The change is a single field assignment with a well-documented doc comment, placed directly beside the existing getter, and consistent with the getter's return type. No existing code paths are modified and the new export introduces no side effects.

No files require special attention; both changed files are straightforward.

Important Files Changed

Filename Overview
src/apprt/embedded.zig Adds ghostty_surface_set_userdata export function next to the existing getter; single-line field assignment with no behaviour change to other paths.
include/ghostty.h Adds matching C declaration GHOSTTY_API void ghostty_surface_set_userdata(ghostty_surface_t, void*) immediately after the getter declaration; consistent with existing style.

Sequence Diagram

sequenceDiagram
    participant Host
    participant SurfaceAPI as "Surface (C API)"
    participant Mailbox

    Host->>SurfaceAPI: "ghostty_surface_new() — sets userdata"
    Host->>SurfaceAPI: "ghostty_surface_set_userdata(surface, null)"
    Note over Host: "Detaches userdata before freeing callback context"
    Host->>Host: "free callback context (safe)"
    Mailbox->>SurfaceAPI: "ghostty_surface_userdata()"
    SurfaceAPI-->>Mailbox: "null"
    Note over Mailbox: "Callback sees null — no dangling dereference"
Loading

Reviews (1): Last reviewed commit: "Add ghostty_surface_set_userdata setter" | Re-trigger Greptile

Comment thread include/ghostty.h
const ghostty_surface_config_s*);
GHOSTTY_API void ghostty_surface_free(ghostty_surface_t);
GHOSTTY_API void* ghostty_surface_userdata(ghostty_surface_t);
GHOSTTY_API void ghostty_surface_set_userdata(ghostty_surface_t, void*);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 The void* parameter type doesn't communicate to C callers that NULL is a valid and meaningful value (it detaches the userdata). The existing getter already returns plain void* without a nullability annotation, so this is consistent — but it's worth noting for embedder documentation. If the project ever adopts _Nullable/_Nonnull annotations (common in Apple SDKs), this parameter would be the natural first candidate.

Suggested change
GHOSTTY_API void ghostty_surface_set_userdata(ghostty_surface_t, void*);
GHOSTTY_API void ghostty_surface_set_userdata(ghostty_surface_t, void* _Nullable);

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

@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 2 files

Re-trigger cubic

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.

1 participant