Skip to content

Commit 3c6d88a

Browse files
committed
Fixed a deadlock upon disposal in AggregateBuilder.
1 parent 9af532e commit 3c6d88a

File tree

3 files changed

+17
-24
lines changed

3 files changed

+17
-24
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# master
22
*Please add new entries at the top.*
33

4+
1. Fixed a deadlock upon disposal when combining operators, i.e. `zip` and `combineLatest`, are used. (#471, kudos to @stevebrambilla for catching the bug)
5+
46
# 2.0.0-rc.1
57
1. If the input observer of a `Signal` deinitializes while the `Signal` has not yet terminated, an `interrupted` event would now be automatically sent. (#463, kudos to @andersio)
68

Sources/Signal.swift

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,11 +2132,7 @@ extension Signal {
21322132
disposables += action(index, strategy) { observer.action($0.map { _ in fatalError() }) }
21332133
}
21342134

2135-
return AnyDisposable {
2136-
strategy.modify { _ in
2137-
disposables.dispose()
2138-
}
2139-
}
2135+
return disposables
21402136
}
21412137
}
21422138

Tests/ReactiveSwiftTests/SignalSpec.swift

Lines changed: 14 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,27 +14,8 @@ import Nimble
1414
import Quick
1515
@testable import ReactiveSwift
1616

17-
private class StateA<U, V> {}
18-
private class StateB<U, V> {}
19-
private enum SignalState<U, V> {
20-
case alive(StateA<U, V>)
21-
case terminating(StateB<U, V>)
22-
case terminated
23-
}
24-
2517
class SignalSpec: QuickSpec {
2618
override func spec() {
27-
describe("thread safety") {
28-
it("should have the same memory layout as a native pointer") {
29-
let enumLayout = MemoryLayout<SignalState<Int, Error>>.self
30-
let pointerLayout = MemoryLayout<UnsafeMutableRawPointer>.self
31-
32-
expect(enumLayout.alignment) == pointerLayout.alignment
33-
expect(enumLayout.size) == pointerLayout.size
34-
expect(enumLayout.stride) == pointerLayout.stride
35-
}
36-
}
37-
3819
describe("init") {
3920
var testScheduler: TestScheduler!
4021

@@ -2798,6 +2779,20 @@ class SignalSpec: QuickSpec {
27982779
}
27992780
}
28002781

2782+
describe("AggregateBuilder") {
2783+
it("should not deadlock upon disposal") {
2784+
let (a, aObserver) = Signal<(), NoError>.pipe()
2785+
let (b, bObserver) = Signal<(), NoError>.pipe()
2786+
2787+
Signal.zip(a, b)
2788+
.take(first: 1)
2789+
.observeValues { _ in }
2790+
2791+
aObserver.send(value: ())
2792+
bObserver.send(value: ())
2793+
}
2794+
}
2795+
28012796
describe("combineLatest") {
28022797
var signalA: Signal<Int, NoError>!
28032798
var signalB: Signal<Int, NoError>!

0 commit comments

Comments
 (0)