Skip to content

take(1) + share(replay: 1) + zip = deadlock #2653

Open
@isaac-weisberg

Description

@isaac-weisberg

Hey, guys. I have uncovered that there is a situation where you can easily cause RxSwift do deadlock.

I have prepared a repo with 100% reproduction rate of this feature.

It is caused by the fact that:

  • take(1) emits .completed
  • zip starts unsubscribing from source when it sees .completed
  • share(replay: 1) synchronizes the unsubscribing under it's own lock
  • BUT also share(replay: 1) replays the stored element under this very same lock
  • which can also be forwarded into .completed event because take(1)
  • which will be received by zip, which will try to unsubscribe from source
  • which is the same share(replay: 1)
  • ???
  • PROFIT

In this deadlock situation, there are always 2 threads that get stuck:

  • one has acquired the lock of zip, and tries to lock on share(replay: 1) to unsub
  • the other has acquired the lock of share(replay: 1) to replay an event, and tries to lock on zip

If one thing happens earlier than the other in a concurrent environment, then they will deadlock.

Here's a link to my repository that reproes this issue, just build, Cmd+R, it's raw Xcodeproj with SPM:

https://github.com/isaac-weisberg/RxSwiftDeadlock

Separate thanks I would like to say to @firecore and specifically this issue: #2525 - one of the problems described in this issue is definitely related!

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