diff --git a/go/mysql/server.go b/go/mysql/server.go index c32f0d6d85f..7a5d61c8f18 100644 --- a/go/mysql/server.go +++ b/go/mysql/server.go @@ -331,8 +331,10 @@ func (l *Listener) Accept() { // handle is called in a go routine for each client connection. // FIXME(alainjobart) handle per-connection logs in a way that makes sense. func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Time) { + var connWithTimeouts netutil.ConnWithTimeouts if l.connReadTimeout != 0 || l.connWriteTimeout != 0 { - conn = netutil.NewConnWithTimeouts(conn, l.connReadTimeout, l.connWriteTimeout) + connWithTimeouts = netutil.NewConnWithTimeouts(conn, l.connReadTimeout, l.connWriteTimeout) + conn = connWithTimeouts } c := newServerConn(conn, l) c.ConnectionID = connectionID @@ -519,6 +521,8 @@ func (l *Listener) handle(conn net.Conn, connectionID uint32, acceptTime time.Ti l.handler.ConnectionReady(c) for { + waitTimeout := 10 * time.Second + (&connWithTimeouts).SetNextReadTimeout(waitTimeout) kontinue := c.handleNextCommand(l.handler) if !kontinue { return diff --git a/go/netutil/conn.go b/go/netutil/conn.go index e4f8ab7ebe2..ddf3475a0ba 100644 --- a/go/netutil/conn.go +++ b/go/netutil/conn.go @@ -23,6 +23,7 @@ var _ net.Conn = (*ConnWithTimeouts)(nil) // A ConnWithTimeouts is a wrapper to net.Comm that allows to set a read and write timeouts. type ConnWithTimeouts struct { net.Conn + nextReadTimeout time.Duration readTimeout time.Duration writeTimeout time.Duration } @@ -36,13 +37,16 @@ func NewConnWithTimeouts(conn net.Conn, readTimeout time.Duration, writeTimeout // Read sets a read deadilne and delegates to conn.Read. func (c ConnWithTimeouts) Read(b []byte) (int, error) { - if c.readTimeout == 0 { + if c.nextReadTimeout == 0 { return c.Conn.Read(b) } - if err := c.Conn.SetReadDeadline(time.Now().Add(c.readTimeout)); err != nil { + if err := c.Conn.SetReadDeadline(time.Now().Add(c.nextReadTimeout)); err != nil { return 0, err } - return c.Conn.Read(b) + n, err := c.Conn.Read(b) + // how do I reset the read timeout here without a pointer receiver? + c.nextReadTimeout = c.readTimeout + return n, err } // Write sets a write deadline and delegates to conn.Write @@ -56,6 +60,10 @@ func (c ConnWithTimeouts) Write(b []byte) (int, error) { return c.Conn.Write(b) } +func (c *ConnWithTimeouts) SetNextReadTimeout(timeout time.Duration) { + c.nextReadTimeout = timeout +} + // SetDeadline implements the Conn SetDeadline method. func (c ConnWithTimeouts) SetDeadline(t time.Time) error { panic("can't call SetDeadline for ConnWithTimeouts")