Do not timeout when WriteControl deadline is zero

A zero value for the Conn.WriteControl deadline specifies no timeout,
but the feature was implemented as a very long timeout (1000 hours).
This PR updates the code to use no timeout when the deadline is zero.

See the discussion in #895 for more details.
This commit is contained in:
Martin Greenwald 2024-02-14 19:06:54 -08:00 committed by Canelo Hill
parent 216f6aae45
commit 87352bcadd
2 changed files with 29 additions and 12 deletions

25
conn.go
View File

@ -435,23 +435,24 @@ func (c *Conn) WriteControl(messageType int, data []byte, deadline time.Time) er
maskBytes(key, 0, buf[6:])
}
d := 1000 * time.Hour
if !deadline.IsZero() {
d = deadline.Sub(time.Now())
if deadline.IsZero() {
// No timeout for zero time.
<-c.mu
} else {
d := time.Until(deadline)
if d < 0 {
return errWriteTimeout
}
}
select {
case <-c.mu:
default:
timer := time.NewTimer(d)
select {
case <-c.mu:
timer.Stop()
case <-timer.C:
return errWriteTimeout
default:
timer := time.NewTimer(d)
select {
case <-c.mu:
timer.Stop()
case <-timer.C:
return errWriteTimeout
}
}
}

View File

@ -148,6 +148,22 @@ func TestFraming(t *testing.T) {
}
}
func TestWriteControlDeadline(t *testing.T) {
t.Parallel()
message := []byte("hello")
var connBuf bytes.Buffer
c := newTestConn(nil, &connBuf, true)
if err := c.WriteControl(PongMessage, message, time.Time{}); err != nil {
t.Errorf("WriteControl(..., zero deadline) = %v, want nil", err)
}
if err := c.WriteControl(PongMessage, message, time.Now().Add(time.Second)); err != nil {
t.Errorf("WriteControl(..., future deadline) = %v, want nil", err)
}
if err := c.WriteControl(PongMessage, message, time.Now().Add(-time.Second)); err == nil {
t.Errorf("WriteControl(..., past deadline) = nil, want timeout error")
}
}
func TestConcurrencyWriteControl(t *testing.T) {
const message = "this is a ping/pong messsage"
loop := 10