Fix crash when executing/canceling effect inside BaseMiddleware#108
Open
IosifSuzuki wants to merge 4 commits into1.5.2from
Open
Conversation
added 3 commits
April 22, 2026 15:36
…dleware Add test case for concurrent cancellations for _BaseMiddleware
| cancellations[key] = cancellable | ||
| } | ||
|
|
||
| func deleteCancellation(forKey key: AnyHashable) { |
Collaborator
There was a problem hiding this comment.
Давай може краще успадкуємо неймінг по принципу як і removeValue в словнику? Змінемо ім'я на removeCancellation.
Remove usage GCD from swift concurrency code
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
This merge request fixes a thread-safety issue in middleware cancellation handling.
_BaseMiddlewarewas storing and mutating itscancellationsdictionary from multiple execution contexts without synchronization, which could cause data races when several cancellation actions were dispatched at the same time.The change is necessary because cancellation can be triggered concurrently from Combine pipelines and async tasks, and the middleware was marked
@unchecked Sendablewhile still relying on unsynchronized mutable state. An alternative would have been to isolate cancellation state behind an actor or move all access onto a single serialized queue, but this MR keeps the current design and adds explicit locking around the shared mutable state.Changes Made
Made middleware cancellation storage thread-safe by replacing direct access to:
with lock-protected access backed by:
Introduced a private
MutableStatecontainer to encapsulate thecancellationsdictionary and provide controlled mutation helpers:set(cancellable:forKey:)deleteCancellation(forKey:)Updated all cancellation lifecycle paths in
_BaseMiddlewareto use the lock:cancel(by:)receiveCancelPreserved the public
cancellationsAPI as a computed property that now returns a lock-protected snapshot of the internal state.Added regression tests for concurrent cancellation in both middleware test suites:
ConcurrencyMiddlewareCancellationTests.testMiddlewareCancellationDataRaceMiddlewareCancellationTests.testMiddlewareCancellationDataRaceThe new tests dispatch
CancelLoading()concurrently from multiple tasks and verify that middleware reaches one of the expected cancellation states without crashing or corrupting state.ClickUp task
https://app.clickup.com/t/869d0m455