Skip to content

Commit db39a71

Browse files
authored
Merge pull request #87 from mschneider82/master
protocol: fixed deadline datarace #86
2 parents 2e44d7a + b4887c1 commit db39a71

File tree

2 files changed

+14
-9
lines changed

2 files changed

+14
-9
lines changed

.github/workflows/test.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jobs:
3333
run: go vet
3434

3535
- name: Test
36-
run: go test -v -covermode=count -coverprofile=coverage.out
36+
run: go test -race -v -covermode=atomic -coverprofile=coverage.out
3737

3838
- name: actions-goveralls
3939
uses: shogo82148/[email protected]

protocol.go

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io"
66
"net"
77
"sync"
8+
"sync/atomic"
89
"time"
910
)
1011

@@ -33,15 +34,15 @@ type Listener struct {
3334
// return the address of the client instead of the proxy address. Each connection
3435
// will have its own readHeaderTimeout and readDeadline set by the Accept() call.
3536
type Conn struct {
36-
bufReader *bufio.Reader
37+
readDeadline atomic.Value // time.Time
38+
once sync.Once
39+
readErr error
3740
conn net.Conn
41+
Validate Validator
42+
bufReader *bufio.Reader
3843
header *Header
39-
once sync.Once
4044
ProxyHeaderPolicy Policy
41-
Validate Validator
42-
readErr error
4345
readHeaderTimeout time.Duration
44-
readDeadline time.Time
4546
}
4647

4748
// Validator receives a header and decides whether it is a valid one
@@ -215,7 +216,7 @@ func (p *Conn) UDPConn() (conn *net.UDPConn, ok bool) {
215216

216217
// SetDeadline wraps original conn.SetDeadline
217218
func (p *Conn) SetDeadline(t time.Time) error {
218-
p.readDeadline = t
219+
p.readDeadline.Store(t)
219220
return p.conn.SetDeadline(t)
220221
}
221222

@@ -224,7 +225,7 @@ func (p *Conn) SetReadDeadline(t time.Time) error {
224225
// Set a local var that tells us the desired deadline. This is
225226
// needed in order to reset the read deadline to the one that is
226227
// desired by the user, rather than an empty deadline.
227-
p.readDeadline = t
228+
p.readDeadline.Store(t)
228229
return p.conn.SetReadDeadline(t)
229230
}
230231

@@ -250,7 +251,11 @@ func (p *Conn) readHeader() error {
250251
// Therefore, we check whether the error is a net.Timeout and if it is, we decide
251252
// the proxy proto does not exist and set the error accordingly.
252253
if p.readHeaderTimeout > 0 {
253-
p.conn.SetReadDeadline(p.readDeadline)
254+
t := p.readDeadline.Load()
255+
if t == nil {
256+
t = time.Time{}
257+
}
258+
p.conn.SetReadDeadline(t.(time.Time))
254259
if netErr, ok := err.(net.Error); ok && netErr.Timeout() {
255260
err = ErrNoProxyProtocol
256261
}

0 commit comments

Comments
 (0)