Avoid overriding aLongTimeAgo read deadline (#774)

* Avoid overriding aLongTimeAgo read deadline

The (*Server).readTCP and (*Server).readUDP methods both call
SetReadDeadline. If they race with ShutdownContext, they can override
the aLongTimeAgo read deadline that is set in ShutdownContext. That
will cause ShutdownContext to hang or timeout.

* Reword readTCP comment
This commit is contained in:
Tom Thorogood 2018-10-06 01:46:28 +09:30 committed by GitHub
parent 7ca2be95a9
commit 36ffedf7d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 13 additions and 2 deletions

View File

@ -666,7 +666,14 @@ func (srv *Server) serveDNS(w *response) {
}
func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error) {
conn.SetReadDeadline(time.Now().Add(timeout))
if srv.isStarted() {
// If we race with ShutdownContext, the read deadline may
// have been set in the distant past to unblock the read
// below. We must not override it, otherwise we may block
// ShutdownContext.
conn.SetReadDeadline(time.Now().Add(timeout))
}
l := make([]byte, 2)
n, err := conn.Read(l)
if err != nil || n != 2 {
@ -701,7 +708,11 @@ func (srv *Server) readTCP(conn net.Conn, timeout time.Duration) ([]byte, error)
}
func (srv *Server) readUDP(conn *net.UDPConn, timeout time.Duration) ([]byte, *SessionUDP, error) {
conn.SetReadDeadline(time.Now().Add(timeout))
if srv.isStarted() {
// See the comment in readTCP above.
conn.SetReadDeadline(time.Now().Add(timeout))
}
m := srv.udpPool.Get().([]byte)
n, s, err := ReadFromSessionUDP(conn, m)
if err != nil {