Skip to content

fix: fix thread-safety crash in Matcher when tests run in parallel#139

Merged
Kolos65 merged 1 commit intomainfrom
fix/thread-safe-matcher
Feb 12, 2026
Merged

fix: fix thread-safety crash in Matcher when tests run in parallel#139
Kolos65 merged 1 commit intomainfrom
fix/thread-safe-matcher

Conversation

@Kolos65
Copy link
Copy Markdown
Owner

@Kolos65 Kolos65 commented Feb 12, 2026

The Matcher singleton's matchers array is accessed without synchronization. Under Swift Testing's parallel execution, concurrent register() writes and comparator() reads from multiple test init() methods cause data races that crash the test process.

Observed crash sites:

  • Matcher.register<A>(_:) — concurrent appends to the array
  • closure #1 in Parameter.eraseToGenericValue() — concurrent reads via Matcher.comparator(for:) while another thread appends

Add an NSLock to synchronize all matchers array access. The lock is applied at the leaf level (append and snapshot-read) to avoid re-entrancy in the Sequence comparator path which calls comparator(by:)comparator(for: T.Element.self)comparator(by:).

The `Matcher` singleton's `matchers` array is accessed without
synchronization. Under Swift Testing's parallel execution, concurrent
`register()` writes and `comparator()` reads from multiple test
`init()` methods cause data races that crash the test process.

Observed crash sites:
- `Matcher.register<A>(_:)` — concurrent appends to the array
- `closure #1 in Parameter.eraseToGenericValue()` — concurrent reads
  via `Matcher.comparator(for:)` while another thread appends

Add an NSLock to synchronize all matchers array access. The lock is
applied at the leaf level (append and snapshot-read) to avoid
re-entrancy in the Sequence comparator path which calls
`comparator(by:)` → `comparator(for: T.Element.self)` →
`comparator(by:)`.
@Kolos65 Kolos65 merged commit 92523c3 into main Feb 12, 2026
10 checks passed
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