Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix crash when cancelling subscription for custom PersistenceKey #3494

Merged
merged 2 commits into from
Nov 14, 2024

Conversation

pyrtsa
Copy link
Contributor

@pyrtsa pyrtsa commented Nov 14, 2024

We have a custom conformance of PersistenceKey that called Shared<Value>.Subscription.cancel() on the base persistence key in its own onCancel closure:

struct PersistenceKeyProjection<Value: Sendable, Base: PersistenceReaderKey>: PersistenceReaderKey {
  let base: Base

  // ...

  func subscribe(
    initialValue: Value?,
    didSet: @escaping @Sendable (_ newValue: Value?) -> Void
  ) -> Shared<Value>.Subscription {
    let subscription = self.base.subscribe( /* ... */ )
    return Shared.Subscription {
      subscription.cancel()  // ← ⚠️
    }
  }
}

When upgrading to 1.16.0, that logic started crashing with AppStorageKey because Shared<Value>.Subscription also calls cancel() from its deinit and key-value observing does not allow that:

Caution

Cannot remove an observer <_TtCGV22ComposableArchitecture13AppStorageKeyGSqSS__P10$1353d4f8c8Observer 0x6000002848a0> for the key path "stringKey" from <NSUserDefaults 0x600000dd3cf0> because it is not registered as an observer.

In our case, the sufficient workaround was to change the call to subscription.cancel() into just an extended lifetime _ = subscription and call it a day.

But I think it's still a wart that Shared<Value>.Subscription allowed this to crash!

This PR reproduces the crash with a (rather artificial) unit test and follows up with a proposed fix.

@pyrtsa pyrtsa force-pushed the persistence-key-cancellation branch from b9a9bf5 to 98d9580 Compare November 14, 2024 13:35
@pyrtsa pyrtsa force-pushed the persistence-key-cancellation branch from 98d9580 to f9e82e9 Compare November 14, 2024 14:05
Copy link
Member

@stephencelis stephencelis left a comment

Choose a reason for hiding this comment

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

Thanks! We noticed that Shared.Subscription had this issue and also isn't Sendable a day or two ago. We'll merge this and add sendability soon.

@stephencelis stephencelis merged commit 69247ba into pointfreeco:main Nov 14, 2024
13 checks passed
@pyrtsa pyrtsa deleted the persistence-key-cancellation branch November 15, 2024 13:09
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