Skip to content

share(replay: 2+, scope: .whileConnected) misses events in multithreaded environment #2655

Open
@isaac-weisberg

Description

@isaac-weisberg

I have been writing unit tests for #2654 and found a bug in ConnectableObservableAdapter:

  • Multicast operator produces a ConnectableObservableAdapter
  • when you subscribe to it via Observable interface, it evaluates lazySubject computed property to instantiate a Subject without synchronization
  • this can cause the makeSubject to be called more than once if you perform several calls to subscribe concurrently
  • and if it's going to return different instances of Subject, this means that some of the concurrent subscriptions will actually be looking at the wrong instance of Subject, which will be overwritten during the data race.

This setup will naturally occur if:

  • you are doing flatMap into a connectable observable concurrently
  • if you use refCount operator, subscribing concurrently
  • share(replay: 2+, scope: .whileConnected) because it's implemented via multicast + refCount

You can see the code that reproduces this issue here: https://github.com/isaac-weisberg/RxSwiftDeadlock/tree/connect-unsafe

I am going to provide a fix for this issue inside #2654 since it's required to make all the tests run successfully.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions