From b916fde75bb87b337e42f6ee8faa08d1203eebdd Mon Sep 17 00:00:00 2001 From: charredlot Date: Mon, 24 Jun 2024 14:21:41 -0700 Subject: [PATCH] fix(query): always close client.conn in cancelQuery (issue #405) When the server closes the connection unexpectedly, the client will call cancelQuery (e.g. when client.packet fails). In client.cancelQuery, if client.flushBuf has data to flush, it will return a non-nil error and return early without calling conn.Close. This prevents the chpool from removing the client after client.Do and leaves the client.conn in a bad state such that future writes will always fail with a "broken pipe" error. --- query.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/query.go b/query.go index f3307e07..a3dcd17b 100644 --- a/query.go +++ b/query.go @@ -36,16 +36,18 @@ func (c *Client) cancelQuery() error { Buf: make([]byte, 1), } proto.ClientCodeCancel.Encode(&b) + + var retErr error if err := c.flushBuf(ctx, &b); err != nil { - return errors.Wrap(err, "flush") + retErr = errors.Join(retErr, errors.Wrap(err, "flush")) } - // Closing connection to prevent further queries. + // Always close connection to prevent further queries. if err := c.Close(); err != nil { - return errors.Wrap(err, "close") + retErr = errors.Join(retErr, errors.Wrap(err, "close")) } - return nil + return retErr } func (c *Client) querySettings(q Query) []proto.Setting {