Skip to content

Fix CanvasLayoutStore teardown crash on older Swift runtimes - #837

Merged
onevcat merged 2 commits into
mainfrom
fix/canvas-layout-store-deinit
Sep 29, 2026
Merged

onevcat merged 2 commits into
mainfrom
fix/canvas-layout-store-deinit

Conversation

@onevtail

@onevtail onevtail commented Sep 28, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

Add an explicit empty nonisolated deinit to CanvasLayoutStore to avoid the TaskLocal invalid-free crash in older system Swift concurrency runtimes (Sentry PROWL-MACOS-KB / PROWL-MACOS-KC).

Root cause

Under the default main-actor isolation, the compiler infers an isolated deinit for CanvasLayoutStore. Its destructor calls swift_task_deinitOnExecutor. On older system runtimes (for example macOS 26.3.1), a synchronous release while TaskLocal storage is bound hits the invalid free fixed upstream in swiftlang/swift#85204. The fix is in the runtime, so a newer Xcode does not help: the app links the system libswift_Concurrency.dylib.

The published 2026.9.25 build (Xcode 27, 27A266a) still branches to swift_task_deinitOnExecutor from the CanvasLayoutStore heap destructor.

The store has no actor-bound teardown work. Persistence happens on mutation, not on destruction. State access stays main-actor isolated.

Changes

  • CanvasLayoutStore: explicit empty nonisolated deinit.
  • CanvasLayoutStoreTests: release the store synchronously on a main-queue callback (no current Task) with a live TaskLocal binding. Check lifetime, binding restoration, and persistence.

Validation

  • Extracted store on iOS 26.2 simulator (affected runtime): original source aborts with the same swift_task_deinitOnExecutorImpl / invalid-free stack; patched source completes 10,000 releases outside a Task.
  • iOS 26.4 simulator: original and patched both complete 10,000 releases.
  • SIL (Xcode 26.3 and 26.6): original destructor calls swift_task_deinitOnExecutor; patched destructor does not.
  • make build-app, make check, and all 5 CanvasLayoutStoreTests pass (Xcode 26.6).

Not yet verified

  • Build and tests with the release Xcode 27 toolchain and original dependency pins (local validation used Xcode 26.6; the lockfile rewrite was reverted and is not part of this PR).
  • Sidebar switch / archive regression on macOS 26.3.1.

onevtail - an assistant to @onevcat

This fix is too small for a durable docs-ai record. The pull request keeps the rationale.
@onevcat
onevcat merged commit ac5cb7b into main Sep 29, 2026
1 check passed
@onevcat
onevcat deleted the fix/canvas-layout-store-deinit branch September 29, 2026 10:53
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.

2 participants