提交 6c6dcfce 作者: Juan Batiz-Benet

Merge pull request #640 from jbenet/races

more races 2015-01-24
...@@ -89,10 +89,17 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee ...@@ -89,10 +89,17 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
laddr := pickLocalAddr(d.LocalAddrs, raddr) laddr := pickLocalAddr(d.LocalAddrs, raddr)
log.Debugf("%s dialing %s -- %s --> %s", d.LocalPeer, remote, laddr, raddr) log.Debugf("%s dialing %s -- %s --> %s", d.LocalPeer, remote, laddr, raddr)
// make a copy of the manet.Dialer, we may need to change its timeout.
madialer := d.Dialer
if laddr != nil && reuseport.Available() { if laddr != nil && reuseport.Available() {
// we're perhaps going to dial twice. half the timeout, so we can afford to.
// otherwise our context would expire right after the first dial.
madialer.Dialer.Timeout = (madialer.Dialer.Timeout / 2)
// dial using reuseport.Dialer, because we're probably reusing addrs. // dial using reuseport.Dialer, because we're probably reusing addrs.
// this is optimistic, as the reuseDial may fail to bind the port. // this is optimistic, as the reuseDial may fail to bind the port.
if nconn, retry, reuseErr := d.reuseDial(laddr, raddr); reuseErr == nil { if nconn, retry, reuseErr := reuseDial(madialer.Dialer, laddr, raddr); reuseErr == nil {
// if it worked, wrap the raw net.Conn with our manet.Conn // if it worked, wrap the raw net.Conn with our manet.Conn
log.Debugf("%s reuse worked! %s %s %s", d.LocalPeer, laddr, nconn.RemoteAddr(), nconn) log.Debugf("%s reuse worked! %s %s %s", d.LocalPeer, laddr, nconn.RemoteAddr(), nconn)
return manet.WrapNetConn(nconn) return manet.WrapNetConn(nconn)
...@@ -105,22 +112,18 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee ...@@ -105,22 +112,18 @@ func (d *Dialer) rawConnDial(ctx context.Context, raddr ma.Multiaddr, remote pee
} }
} }
// no local addr, or reuseport failed. just dial straight with a new port. return madialer.Dial(raddr)
return d.Dialer.Dial(raddr)
} }
func (d *Dialer) reuseDial(laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) { func reuseDial(dialer net.Dialer, laddr, raddr ma.Multiaddr) (conn net.Conn, retry bool, err error) {
if laddr == nil { if laddr == nil {
// if we're given no local address no sense in using reuseport to dial, dial out as usual. // if we're given no local address no sense in using reuseport to dial, dial out as usual.
return nil, true, reuseport.ErrReuseFailed return nil, true, reuseport.ErrReuseFailed
} }
// half the timeout so we can retry regularly if this fails.
d.Dialer.Dialer.Timeout = (d.Dialer.Dialer.Timeout / 2)
// give reuse.Dialer the manet.Dialer's Dialer. // give reuse.Dialer the manet.Dialer's Dialer.
// (wow, Dialer should've so been an interface...) // (wow, Dialer should've so been an interface...)
rd := reuseport.Dialer{d.Dialer.Dialer} rd := reuseport.Dialer{dialer}
// get the local net.Addr manually // get the local net.Addr manually
rd.D.LocalAddr, err = manet.ToNetAddr(laddr) rd.D.LocalAddr, err = manet.ToNetAddr(laddr)
......
...@@ -10,6 +10,7 @@ import ( ...@@ -10,6 +10,7 @@ import (
peer "github.com/jbenet/go-ipfs/p2p/peer" peer "github.com/jbenet/go-ipfs/p2p/peer"
testutil "github.com/jbenet/go-ipfs/util/testutil" testutil "github.com/jbenet/go-ipfs/util/testutil"
ci "github.com/jbenet/go-ipfs/util/testutil/ci"
jenkins "github.com/jbenet/go-ipfs/util/testutil/ci/jenkins" jenkins "github.com/jbenet/go-ipfs/util/testutil/ci/jenkins"
travis "github.com/jbenet/go-ipfs/util/testutil/ci/travis" travis "github.com/jbenet/go-ipfs/util/testutil/ci/travis"
...@@ -377,9 +378,9 @@ func TestDialBackoffClears(t *testing.T) { ...@@ -377,9 +378,9 @@ func TestDialBackoffClears(t *testing.T) {
defer s2.Close() defer s2.Close()
s1.dialT = time.Millisecond * 300 // lower timeout for tests. s1.dialT = time.Millisecond * 300 // lower timeout for tests.
s2.dialT = time.Millisecond * 300 // lower timeout for tests. s2.dialT = time.Millisecond * 300 // lower timeout for tests.
if travis.IsRunning() { if ci.IsRunning() {
s1.dialT = time.Second s1.dialT = 2 * time.Second
s2.dialT = time.Second s2.dialT = 2 * time.Second
} }
// use another address first, that accept and hang on conns // use another address first, that accept and hang on conns
......
...@@ -19,6 +19,9 @@ import ( ...@@ -19,6 +19,9 @@ import (
netutil "github.com/jbenet/go-ipfs/p2p/test/util" netutil "github.com/jbenet/go-ipfs/p2p/test/util"
routing "github.com/jbenet/go-ipfs/routing" routing "github.com/jbenet/go-ipfs/routing"
u "github.com/jbenet/go-ipfs/util" u "github.com/jbenet/go-ipfs/util"
ci "github.com/jbenet/go-ipfs/util/testutil/ci"
travisci "github.com/jbenet/go-ipfs/util/testutil/ci/travis"
) )
var testCaseValues = map[u.Key][]byte{} var testCaseValues = map[u.Key][]byte{}
...@@ -330,6 +333,9 @@ func TestBootstrap(t *testing.T) { ...@@ -330,6 +333,9 @@ func TestBootstrap(t *testing.T) {
func TestPeriodicBootstrap(t *testing.T) { func TestPeriodicBootstrap(t *testing.T) {
// t.Skip("skipping test to debug another") // t.Skip("skipping test to debug another")
if ci.IsRunning() {
t.Skip("skipping on CI. highly timing dependent")
}
if testing.Short() { if testing.Short() {
t.SkipNow() t.SkipNow()
} }
...@@ -734,6 +740,9 @@ func TestConnectCollision(t *testing.T) { ...@@ -734,6 +740,9 @@ func TestConnectCollision(t *testing.T) {
if testing.Short() { if testing.Short() {
t.SkipNow() t.SkipNow()
} }
if travisci.IsRunning() {
t.Skip("Skipping on Travis-CI.")
}
runTimes := 10 runTimes := 10
...@@ -763,7 +772,7 @@ func TestConnectCollision(t *testing.T) { ...@@ -763,7 +772,7 @@ func TestConnectCollision(t *testing.T) {
errs <- err errs <- err
}() }()
timeout := time.After(time.Second) timeout := time.After(5 * time.Second)
select { select {
case e := <-errs: case e := <-errs:
if e != nil { if e != nil {
......
...@@ -19,6 +19,17 @@ func newBucket() *Bucket { ...@@ -19,6 +19,17 @@ func newBucket() *Bucket {
return b return b
} }
func (b *Bucket) Peers() []peer.ID {
b.lk.RLock()
defer b.lk.RUnlock()
ps := make([]peer.ID, 0, b.list.Len())
for e := b.list.Front(); e != nil; e = e.Next() {
id := e.Value.(peer.ID)
ps = append(ps, id)
}
return ps
}
func (b *Bucket) find(id peer.ID) *list.Element { func (b *Bucket) find(id peer.ID) *list.Element {
b.lk.RLock() b.lk.RLock()
defer b.lk.RUnlock() defer b.lk.RUnlock()
...@@ -91,7 +102,3 @@ func (b *Bucket) Split(cpl int, target ID) *Bucket { ...@@ -91,7 +102,3 @@ func (b *Bucket) Split(cpl int, target ID) *Bucket {
} }
return newbuck return newbuck
} }
func (b *Bucket) getIter() *list.Element {
return b.list.Front()
}
...@@ -193,11 +193,11 @@ func (rt *RoutingTable) Size() int { ...@@ -193,11 +193,11 @@ func (rt *RoutingTable) Size() int {
// NOTE: This is potentially unsafe... use at your own risk // NOTE: This is potentially unsafe... use at your own risk
func (rt *RoutingTable) ListPeers() []peer.ID { func (rt *RoutingTable) ListPeers() []peer.ID {
var peers []peer.ID var peers []peer.ID
rt.tabLock.RLock()
for _, buck := range rt.Buckets { for _, buck := range rt.Buckets {
for e := buck.getIter(); e != nil; e = e.Next() { peers = append(peers, buck.Peers()...)
peers = append(peers, e.Value.(peer.ID))
}
} }
rt.tabLock.RUnlock()
return peers return peers
} }
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论