{"action":"opened","issue":{"url":"https://api.github.com/repos/ReactiveCocoa/ReactiveSwift/issues/135","repository_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveSwift","labels_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveSwift/issues/135/labels{/name}","comments_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveSwift/issues/135/comments","events_url":"https://api.github.com/repos/ReactiveCocoa/ReactiveSwift/issues/135/events","html_url":"https://github.com/ReactiveCocoa/ReactiveSwift/issues/135","id":192408028,"number":135,"title":"Deadlock in binding to a MutableProperty","user":{"login":"sharplet","id":147686,"avatar_url":"https://avatars.githubusercontent.com/u/147686?v=3","gravatar_id":"","url":"https://api.github.com/users/sharplet","html_url":"https://github.com/sharplet","followers_url":"https://api.github.com/users/sharplet/followers","following_url":"https://api.github.com/users/sharplet/following{/other_user}","gists_url":"https://api.github.com/users/sharplet/gists{/gist_id}","starred_url":"https://api.github.com/users/sharplet/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sharplet/subscriptions","organizations_url":"https://api.github.com/users/sharplet/orgs","repos_url":"https://api.github.com/users/sharplet/repos","events_url":"https://api.github.com/users/sharplet/events{/privacy}","received_events_url":"https://api.github.com/users/sharplet/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":0,"created_at":"2016-11-29T21:37:32Z","updated_at":"2016-11-29T21:37:32Z","closed_at":null,"body":"I'm seeing a deadlock in a binding from a signal to a mutable property. Here's the relevant part of the stack trace:\r\n\r\n![image](https://cloud.githubusercontent.com/assets/147686/20729626/d5d6dc8c-b650-11e6-8fec-940b170009d9.png)\r\n\r\n(2) and (19) are the same signal, hitting the recursive send. Here's the implementation of `<~`:\r\n\r\n```swift\r\n\tpublic static func <~ <Source: SignalProtocol>(target: Self, signal: Source) -> Disposable? where Source.Value == Value, Source.Error == NoError {\r\n\t\treturn signal\r\n\t\t\t.take(during: target.lifetime)\r\n\t\t\t.observeValues { [weak target] value in\r\n\t\t\t\ttarget?.consume(value)\r\n\t\t\t}\r\n\t}\r\n```\r\n\r\nI _think_ what's happening is:\r\n\r\n1. Signal at (19) sends a value\r\n2. The `observeValues` block is called with the value\r\n3. Upon reading `target`, which has gone out of scope, the target's `deinit` gets called\r\n4. This triggers `lifetime.ended` to complete\r\n5. Because of `take(during:)`, the signal immediately tries to complete (lifetime has ended)\r\n6. Deadlock, because the same signal is in the middle of sending a value\r\n\r\nUnfortunately I haven't been able to write a test case that reproduces this."}}
{"actor":{"display_login":"sharplet"}}