Skip to content

Commit

Permalink
Do not timeout when WriteControl deadline is zero
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
Martin Greenwald authored and AlexVulaj committed Mar 6, 2024
1 parent 695e909 commit b2a86a1
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
25 changes: 13 additions & 12 deletions conn.go
Original file line number Diff line number Diff line change
Expand Up @@ -438,23 +438,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 = time.Until(deadline)
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
}
}
}

Expand Down
16 changes: 16 additions & 0 deletions conn_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit b2a86a1

Please sign in to comment.