diff --git a/rpc/client.go b/rpc/client.go index 5bce400865..7f64df14e6 100644 --- a/rpc/client.go +++ b/rpc/client.go @@ -124,6 +124,9 @@ func (c *Client) newClientConn(conn ServerCodec) *clientConn { } func (cc *clientConn) close(err error, inflightReq *requestOp) { + // The client-side pool is per-connection (created in newClientConn), so it + // is owned here and must be stopped to release its metric goroutine. + cc.handler.executionPool.Stop() cc.handler.close(err, inflightReq) cc.codec.close() } diff --git a/rpc/handler.go b/rpc/handler.go index 2543ebfb12..6e8f7b47d2 100644 --- a/rpc/handler.go +++ b/rpc/handler.go @@ -334,7 +334,12 @@ func (h *handler) close(err error, inflightReq *requestOp) { h.callWG.Wait() h.cancelRoot() h.cancelServerSubscriptions(err) - h.executionPool.Stop() + + // The execution pool is deliberately not stopped here. On the server side + // it is shared across all handlers and owned by Server, which stops it in + // Server.Stop(); stopping it per-handler would kill the shared pool's + // metric goroutine on the first request (regression introduced in #1005). + // On the client side the per-connection pool is stopped by clientConn.close. } // addRequestOp registers a request operation.