mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 13:21:37 +00:00
A goroutine is used to manage the lifetime of subscriptions managed by resubscriptions. When the subscription ends with no error, the resub goroutine ends as well. However, the resub goroutine needs to live long enough to read from the unsub channel. Otheriwse, an Unsubscribe call deadlocks when writing to the unsub channel. This is fixed by adding a buffer to the unsub channel. Co-authored-by: Inphi <mlaw2501@gmail.com>
This commit is contained in:
parent
53b3431af5
commit
173214524f
2 changed files with 25 additions and 1 deletions
|
|
@ -120,7 +120,7 @@ func ResubscribeErr(backoffMax time.Duration, fn ResubscribeErrFunc) Subscriptio
|
|||
backoffMax: backoffMax,
|
||||
fn: fn,
|
||||
err: make(chan error),
|
||||
unsub: make(chan struct{}),
|
||||
unsub: make(chan struct{}, 1),
|
||||
}
|
||||
go s.loop()
|
||||
return s
|
||||
|
|
|
|||
|
|
@ -154,3 +154,27 @@ func TestResubscribeWithErrorHandler(t *testing.T) {
|
|||
t.Fatalf("unexpected subscription errors %v, want %v", subErrs, expectedSubErrs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestResubscribeWithCompletedSubscription(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
quitProducerAck := make(chan struct{})
|
||||
quitProducer := make(chan struct{})
|
||||
|
||||
sub := ResubscribeErr(100*time.Millisecond, func(ctx context.Context, lastErr error) (Subscription, error) {
|
||||
return NewSubscription(func(unsubscribed <-chan struct{}) error {
|
||||
select {
|
||||
case <-quitProducer:
|
||||
quitProducerAck <- struct{}{}
|
||||
return nil
|
||||
case <-unsubscribed:
|
||||
return nil
|
||||
}
|
||||
}), nil
|
||||
})
|
||||
|
||||
// Ensure producer has started and exited before Unsubscribe
|
||||
close(quitProducer)
|
||||
<-quitProducerAck
|
||||
sub.Unsubscribe()
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue