rpc: fix data race in timeoutconn
- `timeoutconn` handles state, yet calls to Read/Write make a copy of
that state (non-pointer receiver) so any outbound calls will not have
the state updated
- Even without the copy issue, the renew methods can in edge cases set a
new deadline _after_ DisableTimeouts have been called, consider the
following racy behavior:
1. `renewReadDeadline` is called, checks `renewDeadlinesDisabled`
(not disabled)
2. `DisableTimeouts` is called, sets `renewDeadlinesDisabled`
3. `DisableTimeouts` invokes `c.SetDeadline`
4. `renewReadDeadline` invokes `c.SetReadDeadline`
To fix the above, the `Conn` receiver was made to be a pointer
everywhere and access to renewDeadlinesDisabled is now guarded
by an RWMutex instead of using atomics.
closes #415
This commit is contained in:
committed by
Christian Schwarz
parent
48be4032a2
commit
d118bcc717
@@ -47,7 +47,7 @@ func (f *FrameHeader) Unmarshal(buf []byte) {
|
||||
|
||||
type Conn struct {
|
||||
readMtx, writeMtx sync.Mutex
|
||||
nc timeoutconn.Conn
|
||||
nc *timeoutconn.Conn
|
||||
readNextValid bool
|
||||
readNext FrameHeader
|
||||
nextReadErr error
|
||||
@@ -55,7 +55,7 @@ type Conn struct {
|
||||
shutdown shutdownFSM
|
||||
}
|
||||
|
||||
func Wrap(nc timeoutconn.Conn) *Conn {
|
||||
func Wrap(nc *timeoutconn.Conn) *Conn {
|
||||
return &Conn{
|
||||
nc: nc,
|
||||
// ncBuf: bufio.NewReadWriter(bufio.NewReaderSize(nc, 1<<23), bufio.NewWriterSize(nc, 1<<23)),
|
||||
|
||||
Reference in New Issue
Block a user