Skip to content

Commit eacb484

Browse files
committed
ovsdb: always clean up callbacks in consumer
1 parent 56cae4b commit eacb484

File tree

1 file changed

+15
-9
lines changed

1 file changed

+15
-9
lines changed

ovsdb/client.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -161,22 +161,28 @@ func (c *Client) rpc(ctx context.Context, method string, out interface{}, args .
161161
Response: ch,
162162
})
163163

164+
// Ensure that the callback is always cleaned up on return from this function.
165+
// Note that this will result in the callback being deleted twice if the RPC
166+
// returns successfully, but that's okay; it's a no-op.
167+
//
168+
// TODO(mdlayher): a more robust solution around callback map modifications.
169+
defer func() {
170+
c.cbMu.Lock()
171+
defer c.cbMu.Unlock()
172+
173+
delete(c.callbacks, req.ID)
174+
}()
175+
164176
if err := c.c.Send(req); err != nil {
165177
return err
166178
}
167179

168180
// Await RPC completion or cancelation.
169181
select {
170182
case <-ctx.Done():
171-
// RPC canceled. Clean up the callback in case no message ever arrives
172-
// with its request ID, so we don't leak callbacks. If the other case
173-
// in the select fires (meaning we got a matching RPC response), it's
174-
// the producer's responsibility to clean up the callback.
175-
c.cbMu.Lock()
176-
defer c.cbMu.Unlock()
177-
178-
delete(c.callbacks, req.ID)
179-
183+
// RPC canceled. The callback is cleaned up by deferred function in
184+
// case no message ever arrives with its request ID, so we don't leak
185+
// callbacks.
180186
return ctx.Err()
181187
case res, ok := <-ch:
182188
if !ok {

0 commit comments

Comments
 (0)