Browse Source

packets: reset read deadline before conn check (#964)

* packets: reset read deadline before conn check

If a MySQL connection has been configured with a short `ReadTimeout`,
each read from the TCP connection will be preceded by a
`SetReadDeadline` call, which lingers until the next `SetReadDeadline`.

This can be an issue if the connection becomes stale after staying too
long in the connection pool, because when we attempt to perform a stale
connection check, the Go runtime scheduler will return a timedout error
from the scheduler itself, without letting us get to the kernel to
perform the non-blocking read.

To fix this, reset the read deadline before we perform the connection
check.

* packets: set a 0 deadline
Vicent Martí 6 years ago
parent
commit
8056f2ca4a
1 changed files with 11 additions and 1 deletions
  1. 11 1
      packets.go

+ 11 - 1
packets.go

@@ -108,7 +108,17 @@ func (mc *mysqlConn) writePacket(data []byte) error {
 		if mc.rawConn != nil {
 			conn = mc.rawConn
 		}
-		if err := connCheck(conn); err != nil {
+		var err error
+		// If this connection has a ReadTimeout which we've been setting on
+		// reads, reset it to its default value before we attempt a non-blocking
+		// read, otherwise the scheduler will just time us out before we can read
+		if mc.cfg.ReadTimeout != 0 {
+			err = conn.SetReadDeadline(time.Time{})
+		}
+		if err == nil {
+			err = connCheck(conn)
+		}
+		if err != nil {
 			errLog.Print("closing bad idle connection: ", err)
 			mc.Close()
 			return driver.ErrBadConn