Skip to content

Crash in Tile.start() — EXC_BAD_ACCESS in -[SCContentFilter initWithDesktopIndependentWindow:] (concurrent overlay install) #18

@cannikin

Description

@cannikin

Hit a crash on activation. Looks like a use-after-free / race on an SCWindow being passed into SCContentFilter from concurrent Tile.start() calls.

Environment

  • cmdcmd 0.2.2 (build 11)
  • macOS 26.3.1 (25D2128), Apple Silicon (Mac16,12 / arm64)

Exception

EXC_BAD_ACCESS (SIGSEGV) — KERN_INVALID_ADDRESS at 0x000044bd4dec1050
Faulting thread queue: com.apple.root.user-initiated-qos.cooperative

Faulting stack

0  libobjc.A.dylib                 objc_retain + 16
1  ScreenCaptureKit                -[SCContentFilter initWithDesktopIndependentWindow:] + 52
2  cmdcmd                          Tile.start() + 116
3  cmdcmd                          closure #1 in closure #1 in closure #6 in Overlay.installTiles(candidates:)

What it looks like

At least 6 cooperative-queue threads were concurrently inside Tile.start() at the time of the crash — several deep in SCStream initWithFilter:configuration:delegate:-[SCContentFilter copyWithZone:]-[SCWindow copyWithZone:]-[SCRunningApplication initWithPID:]. The triggered thread was earlier in the path, in initWithDesktopIndependentWindow:, and faulted on objc_retain of the window argument.

The bad pointer (0x44bd…) is well outside any mapped region, consistent with the SCWindow (or its backing object) being deallocated while another tile's start() was retaining it. There's also a separate Overlay.prewarmShareable() task running +[SCShareableContent getShareableContentExcludingDesktopWindows:…] concurrently, which may be refreshing the window list under the in-flight tiles.

Suspected cause

Race between Overlay.installTiles(candidates:) fanning out per-tile async work and the SCWindow candidates being mutated/replaced (e.g., by a concurrent prewarmShareable refresh, or by the candidates array being captured by reference rather than each tile's SCWindow being snapshotted/retained before crossing into the async closure).

Suggested fix directions

  • Capture each SCWindow by value into the per-tile closure before dispatching, so Tile.start() holds its own strong reference for the lifetime of SCContentFilter init.
  • Serialize tile installation with respect to prewarmShareable() (e.g., await the prewarm, or guard candidate access on a single actor).
  • Defensive: validate the window is still in SCShareableContent.windows immediately before initWithDesktopIndependentWindow:.

Full crash report at ~/Library/Logs/DiagnosticReports/cmdcmd-2026-05-06-111815.ips — happy to attach if useful. There's a similar earlier crash from 2026-05-05 16:36 in the same path.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions