p2p/net/dial: fixed data race
Juan Batiz-Benet committed
Jan 24, 2015 at 00:09 UTC
87458f6d6a9d52d52a72d6b97f1433beda3c4fb1
1 file changed
+11
-8
p2p/net/conn/dial.go
+11
-8
@@ -89,10 +89,17 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
89
laddr := pickLocalAddr(d.LocalAddrs, raddr)
90
log.Debugf("%s dialing %s -- %s --> %s", d.LocalPeer, remote, laddr, raddr)
91
92
+ // make a copy of the manet.Dialer, we may need to change its timeout.
93
+ madialer := d.Dialer
94
+
95
if laddr != nil && reuseport.Available() {
96
+ // we're perhaps going to dial twice. half the timeout, so we can afford to.
97
+ // otherwise our context would expire right after the first dial.
98
+ madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2)
99
+
100
// dial using reuseport.Dialer, because we're probably reusing addrs.
101
// this is optimistic, as the reuseDial may fail to bind the port.
95
- if nconn, retry, reuseErr := d.reuseDial(laddr, raddr); reuseErr == nil {
102
+ if nconn, retry, reuseErr := reuseDial(madialer.Dialer, laddr, raddr); reuseErr == nil {
103
// if it worked, wrap the raw net.Conn with our manet.Conn
104
log.Debugf("%s reuse worked! %s %s %s", d.LocalPeer, laddr, nconn.RemoteAddr(), nconn)
105
return manet.WrapNetConn(nconn)
@@ -105,22 +112,18 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
112
}
113
}
114
108
- // no local addr, or reuseport failed. just dial straight with a new port.
109
- return d.Dialer.Dial(raddr)
115
+ return madialer.Dial(raddr)
116
}
117
112
-func (d *Dialer) reuseDial(laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
118
+func reuseDial(dialer net.Dialer, laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
119
if laddr == nil {
120
// if we're given no local address no sense in using reuseport to dial, dial out as usual.
121
return nil, true, reuseport.ErrReuseFailed
122
}
123
118
- // half the timeout so we can retry regularly if this fails.
119
- d.Dialer.Dialer.Timeout = (d.Dialer.Dialer.Timeout / 2)
120
-
124
// give reuse.Dialer the manet.Dialer's Dialer.
125
// (wow, Dialer should've so been an interface...)
123
- rd := reuseport.Dialer{d.Dialer.Dialer}
126
+ rd := reuseport.Dialer{dialer}
127
128
// get the local net.Addr manually
129
rd.D.LocalAddr, err = manet.ToNetAddr(laddr)