Skip to content

Commit 6209545

Browse files
committed
p2p: Wrap conn.flags ops with atomic.Load/Store
1 parent 193a402 commit 6209545

File tree

3 files changed

+28
-20
lines changed

3 files changed

+28
-20
lines changed

p2p/peer.go

Lines changed: 12 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,10 @@ type PeerEvent struct {
9595

9696
// Peer represents a connected remote node.
9797
type Peer struct {
98-
rw *conn
99-
isInbound bool // Cached from rw.flags to avoid a race condition
100-
running map[string]*protoRW
101-
log log.Logger
102-
created mclock.AbsTime
98+
rw *conn
99+
running map[string]*protoRW
100+
log log.Logger
101+
created mclock.AbsTime
103102

104103
wg sync.WaitGroup
105104
protoErr chan error
@@ -161,20 +160,19 @@ func (p *Peer) String() string {
161160

162161
// Inbound returns true if the peer is an inbound connection
163162
func (p *Peer) Inbound() bool {
164-
return p.isInbound
163+
return p.rw.is(inboundConn)
165164
}
166165

167166
func newPeer(conn *conn, protocols []Protocol) *Peer {
168167
protomap := matchProtocols(protocols, conn.caps, conn)
169168
p := &Peer{
170-
rw: conn,
171-
isInbound: conn.is(inboundConn),
172-
running: protomap,
173-
created: mclock.Now(),
174-
disc: make(chan DiscReason),
175-
protoErr: make(chan error, len(protomap)+1), // protocols + pingLoop
176-
closed: make(chan struct{}),
177-
log: log.New("id", conn.id, "conn", conn.flags),
169+
rw: conn,
170+
running: protomap,
171+
created: mclock.Now(),
172+
disc: make(chan DiscReason),
173+
protoErr: make(chan error, len(protomap)+1), // protocols + pingLoop
174+
closed: make(chan struct{}),
175+
log: log.New("id", conn.id, "conn", conn.flags),
178176
}
179177
return p
180178
}

p2p/server.go

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"fmt"
2424
"net"
2525
"sync"
26+
"sync/atomic"
2627
"time"
2728

2829
"github.com/ethereum/go-ethereum/common"
@@ -187,7 +188,7 @@ type peerDrop struct {
187188
requested bool // true if signaled by the peer
188189
}
189190

190-
type connFlag int
191+
type connFlag int32
191192

192193
const (
193194
dynDialedConn connFlag = 1 << iota
@@ -252,7 +253,18 @@ func (f connFlag) String() string {
252253
}
253254

254255
func (c *conn) is(f connFlag) bool {
255-
return c.flags&f != 0
256+
flags := connFlag(atomic.LoadInt32((*int32)(&c.flags)))
257+
return flags&f != 0
258+
}
259+
260+
func (c *conn) set(f connFlag, val bool) {
261+
flags := connFlag(atomic.LoadInt32((*int32)(&c.flags)))
262+
if val {
263+
flags |= f
264+
} else {
265+
flags &= ^f
266+
}
267+
atomic.StoreInt32((*int32)(&c.flags), int32(flags))
256268
}
257269

258270
// Peers returns all connected peers.
@@ -632,7 +644,7 @@ running:
632644
trusted[n.ID] = true
633645
// Mark any already-connected peer as trusted
634646
if p, ok := peers[n.ID]; ok {
635-
p.rw.flags |= trustedConn
647+
p.rw.set(trustedConn, true)
636648
}
637649
case n := <-srv.removetrusted:
638650
// This channel is used by RemoveTrustedPeer to remove an enode
@@ -643,7 +655,7 @@ running:
643655
}
644656
// Unmark any already-connected peer as trusted
645657
if p, ok := peers[n.ID]; ok {
646-
p.rw.flags &= ^trustedConn
658+
p.rw.set(trustedConn, false)
647659
}
648660
case op := <-srv.peerOp:
649661
// This channel is used by Peers and PeerCount.

p2p/server_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,10 @@ func TestServerDial(t *testing.T) {
189189
}
190190
done <- true
191191
}()
192-
193192
// Trigger potential race conditions
194193
peer = srv.Peers()[0]
195194
_ = peer.Inbound()
196195
_ = peer.Info()
197-
198196
<-done
199197
case <-time.After(1 * time.Second):
200198
t.Error("server did not launch peer within one second")

0 commit comments

Comments
 (0)