mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-18 09:53:48 +00:00
rpc: Closing Notifier must tear down subscriptions
* Fixes #15553 * Add a pipeline on the `Notifier`'s `codec` that propagates the `close` to `Subscription`s * Adjust `subscription_test` accordingly since closing the notifier now implies closing the subscription * This should automatically test the initial issue and also makes the tests more determistic by saving the `select`
This commit is contained in:
parent
fe070ab5c3
commit
f5ec3e00d5
2 changed files with 24 additions and 12 deletions
|
|
@ -55,16 +55,34 @@ type Notifier struct {
|
||||||
subMu sync.RWMutex // guards active and inactive maps
|
subMu sync.RWMutex // guards active and inactive maps
|
||||||
active map[ID]*Subscription
|
active map[ID]*Subscription
|
||||||
inactive map[ID]*Subscription
|
inactive map[ID]*Subscription
|
||||||
|
closed chan interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newNotifier creates a new notifier that can be used to send subscription
|
// newNotifier creates a new notifier that can be used to send subscription
|
||||||
// notifications to the client.
|
// notifications to the client.
|
||||||
func newNotifier(codec ServerCodec) *Notifier {
|
func newNotifier(codec ServerCodec) *Notifier {
|
||||||
return &Notifier{
|
n := &Notifier{
|
||||||
codec: codec,
|
codec: codec,
|
||||||
active: make(map[ID]*Subscription),
|
active: make(map[ID]*Subscription),
|
||||||
inactive: make(map[ID]*Subscription),
|
inactive: make(map[ID]*Subscription),
|
||||||
|
closed: make(chan interface{}),
|
||||||
}
|
}
|
||||||
|
in := n.codec.Closed()
|
||||||
|
go func() {
|
||||||
|
for e := range in {
|
||||||
|
n.closed <- e
|
||||||
|
}
|
||||||
|
n.subMu.Lock()
|
||||||
|
defer n.subMu.Unlock()
|
||||||
|
for _, subscription := range n.active {
|
||||||
|
close(subscription.err)
|
||||||
|
}
|
||||||
|
for _, subscription := range n.inactive {
|
||||||
|
close(subscription.err)
|
||||||
|
}
|
||||||
|
close(n.closed)
|
||||||
|
}()
|
||||||
|
return n
|
||||||
}
|
}
|
||||||
|
|
||||||
// NotifierFromContext returns the Notifier value stored in ctx, if any.
|
// NotifierFromContext returns the Notifier value stored in ctx, if any.
|
||||||
|
|
@ -104,7 +122,7 @@ func (n *Notifier) Notify(id ID, data interface{}) error {
|
||||||
|
|
||||||
// Closed returns a channel that is closed when the RPC connection is closed.
|
// Closed returns a channel that is closed when the RPC connection is closed.
|
||||||
func (n *Notifier) Closed() <-chan interface{} {
|
func (n *Notifier) Closed() <-chan interface{} {
|
||||||
return n.codec.Closed()
|
return n.closed
|
||||||
}
|
}
|
||||||
|
|
||||||
// unsubscribe a subscription.
|
// unsubscribe a subscription.
|
||||||
|
|
|
||||||
|
|
@ -72,16 +72,10 @@ func (s *NotificationTestService) SomeSubscription(ctx context.Context, n, val i
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
select {
|
<-subscription.Err()
|
||||||
case <-notifier.Closed():
|
|
||||||
s.mu.Lock()
|
s.mu.Lock()
|
||||||
s.unsubscribed = true
|
s.unsubscribed = true
|
||||||
s.mu.Unlock()
|
s.mu.Unlock()
|
||||||
case <-subscription.Err():
|
|
||||||
s.mu.Lock()
|
|
||||||
s.unsubscribed = true
|
|
||||||
s.mu.Unlock()
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
|
|
||||||
return subscription, nil
|
return subscription, nil
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue