Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

fix(wantlist): remove races on setup #72

Merged
merged 9 commits into from
Feb 20, 2019
Merged

Conversation

hannahhoward
Copy link
Contributor

@hannahhoward hannahhoward commented Feb 19, 2019

Goals

fix race conditions while setting up wantlists

Implementation

This change essentially solves bugs in initial wantlist handling using the strategy outlined by @Stebalien in #51.

This means two differences:

  • Have WantManager handle connect/disconnects and forward to the peer manager
  • In the case the peer manager accidentally receives a request to send a message to a peer it's not connected to, create a "temporary peer" queue on demand, which will automatically initiate the connection when it opens a message stream to send a message
  • This means to send a message we need the broadcast want list just in case

Other notable changes:

  • Remove the go routine from the PeerManager, since basically all it's doing is managing a map
  • Add a retry limit to peer message queues, cause we might be connecting to less reliable peers
  • Add sending initial changes on startup for a peer message queue if present, so that our initial message contains them

For Discussion

fix #51 fix #48

@ghost ghost assigned hannahhoward Feb 19, 2019
@ghost ghost added the status/in-progress In progress label Feb 19, 2019
@hannahhoward
Copy link
Contributor Author

Jenkins seems to be out of space, hence broken builds

peermanager/peermanager.go Outdated Show resolved Hide resolved
peermanager/peermanager.go Outdated Show resolved Hide resolved
peermanager/peermanager.go Show resolved Hide resolved
messagequeue/messagequeue.go Show resolved Hide resolved
}
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize this somewhat reimplements sync.Map, but I find sync.Map relatively useless due to the lack of typing on the values (which can't be avoided given Go's lack of Generics at the moment)

Copy link
Member

@Stebalien Stebalien left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current locking pattern looks a bit suspect. We're taking a lock to pull an item out of the map but then we're mutating that item without the lock.


// new peer, we will want to give them our full wantlist
// AddWantlist adds a complete session tracked want list to a message queue
func (mq *MessageQueue) AddWantlist(initialEntries []*wantlist.Entry) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO (maybe later): It would be kind of nice to deduplicate this with AddMessage. As far as I can tell, they do approximately the same thing; they just take different inputs.

message.handle(pm)
case <-pm.ctx.Done():
return
if ok {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are Disconnect/Connect really safe? pm.get takes a lock internally but then we modify stuff without a lock. That seems a bit odd.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean you're potentially mutating the object, but not its reference. The object itself is responsible for keeping internal mutations threadsafe. THOUGH I acknowledge that actually currently the refcount stuff is not thread safe. I think that should be handled inside the object though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about remove I need to double check.

log.Infof("tried sending wantlist change to non-partner peer: %s", t)
continue
p = pm.createPeerQueue(t)
pm.set(t, p)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can nothing call this concurrently? If so, I assume we'd need some kind of atomic GetOrCreate kind of thing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

mmm. good point. I get it.

@hannahhoward
Copy link
Contributor Author

@Stebalien I think I fixed the locking pattern, but feel free to double check. Also builds seem stalled for linux.

@Stebalien
Copy link
Member

When rebased on #76 and tested against the race detector, I'm getting the following error. It looks like len(peerQueues) is triggering this.

==================
WARNING: DATA RACE
Read at 0x00c000b65560 by goroutine 111:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:205 +0x8fc
  github.com/ipfs/go-bitswap.TestLargeSwarm()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:149 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c000b65560 by goroutine 515:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 111 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 515 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeSwarm()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:149 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
--- FAIL: TestLargeSwarm (13.05s)
    bitswap_test.go:200: Give the blocks to the first instance
    bitswap_test.go:222: Distribute!
    bitswap_test.go:251: Verify!
    testing.go:771: race detected during execution of test
==================
WARNING: DATA RACE
Read at 0x00c004a5ecf0 by goroutine 3703:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:205 +0x8fc
  github.com/ipfs/go-bitswap.TestLargeFileNoRebroadcast()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:174 +0xe8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c004a5ecf0 by goroutine 2003:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 3703 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 2003 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFileNoRebroadcast()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:174 +0xe8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
==================
WARNING: DATA RACE
Read at 0x00c004a517a0 by goroutine 3703:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:208 +0x7da
  github.com/ipfs/go-bitswap.TestLargeFileNoRebroadcast()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:174 +0xe8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c004a517a0 by goroutine 4754:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 3703 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 4754 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFileNoRebroadcast()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:174 +0xe8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
--- FAIL: TestLargeFileNoRebroadcast (4.34s)
    bitswap_test.go:200: Give the blocks to the first instance
    bitswap_test.go:222: Distribute!
    bitswap_test.go:251: Verify!
    testing.go:771: race detected during execution of test
==================
WARNING: DATA RACE
Read at 0x00c0021695f0 by goroutine 172:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:208 +0x7da
  github.com/ipfs/go-bitswap.TestLargeFileTwoPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:184 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c0021695f0 by goroutine 3916:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 172 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 3916 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFileTwoPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:184 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
==================
WARNING: DATA RACE
Read at 0x00c003f548a0 by goroutine 172:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:205 +0x8fc
  github.com/ipfs/go-bitswap.TestLargeFileTwoPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:184 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c003f548a0 by goroutine 1324:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 172 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 1324 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFileTwoPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:184 +0x7f
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
--- FAIL: TestLargeFileTwoPeers (0.58s)
    bitswap_test.go:200: Give the blocks to the first instance
    bitswap_test.go:222: Distribute!
    bitswap_test.go:251: Verify!
    testing.go:771: race detected during execution of test
13:08:36.742 ERROR    bitswap: undefined cid in GetBlock getter.go:26
==================
WARNING: DATA RACE
Read at 0x00c003f7f830 by goroutine 5033:
  github.com/ipfs/go-bitswap.(*Bitswap).Stat()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/stat.go:34 +0x331
  github.com/ipfs/go-bitswap.TestBasicBitswap()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:379 +0xa63
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c003f7f830 by goroutine 1408:
  sync/atomic.AddInt64()
      /usr/lib/go/src/runtime/race_amd64.s:276 +0xb
  github.com/ipfs/go-bitswap.(*Bitswap).ReceiveMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:294 +0x7a
  github.com/ipfs/go-bitswap/testnet.(*receiverQueue).process()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:317 +0x3a4

Goroutine 5033 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 1408 (finished) created at:
  github.com/ipfs/go-bitswap/testnet.(*receiverQueue).enqueue()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:286 +0x1c5
  github.com/ipfs/go-bitswap/testnet.(*network).SendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:161 +0x39b
  github.com/ipfs/go-bitswap/testnet.(*networkClient).SendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:178 +0xd4
  github.com/ipfs/go-bitswap/testnet.(*messagePasser).SendMsg()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:226 +0xae
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).attemptSendAndRecovery()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:225 +0xd1
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).sendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:206 +0x1f8
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).sendMessages()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:187 +0x66
==================
--- FAIL: TestBasicBitswap (0.14s)
    bitswap_test.go:351: Test a one node trying to get one block from another
    bitswap_test.go:394: stat node 0
    bitswap_test.go:396: stat node 1
    bitswap_test.go:398: stat node 2
    bitswap_test.go:405: [Block QmTTA2daxGqo5denp6SwLzzkLJm3fuisYEi9CoWsuHpzfb]
    testing.go:771: race detected during execution of test
==================
WARNING: DATA RACE
Read at 0x00c003ee75b0 by goroutine 2249:
  github.com/ipfs/go-bitswap.TestSessionBetweenPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_with_sessions_test.go:107 +0xb7d
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c003ee75b0 by goroutine 166:
  [failed to restore the stack]

Goroutine 2249 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 166 (finished) created at:
  github.com/ipfs/go-bitswap/testnet.(*receiverQueue).enqueue()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:286 +0x1c5
  github.com/ipfs/go-bitswap/testnet.(*network).SendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:161 +0x39b
  github.com/ipfs/go-bitswap/testnet.(*networkClient).SendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:178 +0xd4
  github.com/ipfs/go-bitswap/testnet.(*messagePasser).SendMsg()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testnet/virtual.go:226 +0xae
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).attemptSendAndRecovery()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:225 +0xd1
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).sendMessage()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:206 +0x1f8
  github.com/ipfs/go-bitswap/messagequeue.(*MessageQueue).sendMessages()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/messagequeue/messagequeue.go:187 +0x66
==================
--- FAIL: TestSessionBetweenPeers (0.76s)
    testing.go:771: race detected during execution of test
==================
WARNING: DATA RACE
Read at 0x00c002fb2a50 by goroutine 3779:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:205 +0x8fc
  github.com/ipfs/go-bitswap.TestLargeFile()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:163 +0x8a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c002fb2a50 by goroutine 1892:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 3779 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 1892 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFile()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:163 +0x8a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
==================
WARNING: DATA RACE
Read at 0x00c00382ee70 by goroutine 3779:
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).ConnectedPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:60 +0x69
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:208 +0x7da
  github.com/ipfs/go-bitswap.TestLargeFile()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:163 +0x8a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c00382ee70 by goroutine 3436:
  runtime.mapassign_faststr()
      /usr/lib/go/src/runtime/map_faststr.go:190 +0x0
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).getOrCreate()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:116 +0x1d2
  github.com/ipfs/go-bitswap/peermanager.(*PeerManager).Connected()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/peermanager/peermanager.go:70 +0x50
  github.com/ipfs/go-bitswap/wantmanager.(*connectedMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:277 +0xc7
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:182 +0x62

Goroutine 3779 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:90 +0x221

Goroutine 3436 (running) created at:
  github.com/ipfs/go-bitswap/wantmanager.(*WantManager).Startup()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/wantmanager/wantmanager.go:168 +0x4c
  github.com/ipfs/go-bitswap.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap.go:136 +0xff7
  github.com/ipfs/go-bitswap.MkSession()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:102 +0x41d
  github.com/ipfs/go-bitswap.(*SessionGenerator).Next()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:50 +0x157
  github.com/ipfs/go-bitswap.(*SessionGenerator).Instances()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/testutils.go:56 +0x9b
  github.com/ipfs/go-bitswap.PerformDistributionTest()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:197 +0x6b3
  github.com/ipfs/go-bitswap.TestLargeFile()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/bitswap_test.go:163 +0x8a
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
--- FAIL: TestLargeFile (5.06s)
    bitswap_test.go:200: Give the blocks to the first instance
    bitswap_test.go:222: Distribute!
    bitswap_test.go:251: Verify!
    testing.go:771: race detected during execution of test
FAIL
FAIL	github.com/ipfs/go-bitswap	30.473s
ok  	github.com/ipfs/go-bitswap/decision	6.723s
?   	github.com/ipfs/go-bitswap/getter	[no test files]
ok  	github.com/ipfs/go-bitswap/message	1.888s
?   	github.com/ipfs/go-bitswap/message/pb	[no test files]
ok  	github.com/ipfs/go-bitswap/messagequeue	1.830s
?   	github.com/ipfs/go-bitswap/network	[no test files]
ok  	github.com/ipfs/go-bitswap/notifications	(cached)
ok  	github.com/ipfs/go-bitswap/peermanager	2.270s
ok  	github.com/ipfs/go-bitswap/providerquerymanager	2.067s
ok  	github.com/ipfs/go-bitswap/session	1.922s
ok  	github.com/ipfs/go-bitswap/sessionmanager	(cached)
==================
WARNING: DATA RACE
Read at 0x00c000097a10 by goroutine 25:
  github.com/ipfs/go-bitswap/sessionpeermanager.TestUntaggingPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager_test.go:219 +0x3f2
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162

Previous write at 0x00c000097a10 by goroutine 26:
  github.com/ipfs/go-bitswap/sessionpeermanager.(*fakePeerTagger).TagPeer()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager_test.go:50 +0xf3
  github.com/ipfs/go-bitswap/sessionpeermanager.(*SessionPeerManager).tagPeer()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager.go:135 +0xae
  github.com/ipfs/go-bitswap/sessionpeermanager.(*peerFoundMessage).handle()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager.go:176 +0x242
  github.com/ipfs/go-bitswap/sessionpeermanager.(*SessionPeerManager).run()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager.go:126 +0x62

Goroutine 25 (running) created at:
  testing.(*T).Run()
      /usr/lib/go/src/testing/testing.go:878 +0x659
  testing.runTests.func1()
      /usr/lib/go/src/testing/testing.go:1119 +0xa8
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
  testing.runTests()
      /usr/lib/go/src/testing/testing.go:1117 +0x4ee
  testing.(*M).Run()
      /usr/lib/go/src/testing/testing.go:1034 +0x2ee
  main.main()
      _testmain.go:48 +0x221

Goroutine 26 (running) created at:
  github.com/ipfs/go-bitswap/sessionpeermanager.New()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager.go:66 +0x2e2
  github.com/ipfs/go-bitswap/sessionpeermanager.TestUntaggingPeers()
      /home/steb/projects/go/src/github.com/ipfs/go-bitswap/sessionpeermanager/sessionpeermanager_test.go:209 +0x2c4
  testing.tRunner()
      /usr/lib/go/src/testing/testing.go:827 +0x162
==================
--- FAIL: TestUntaggingPeers (0.01s)
    testing.go:771: race detected during execution of test
FAIL
FAIL	github.com/ipfs/go-bitswap/sessionpeermanager	1.000s
ok  	github.com/ipfs/go-bitswap/sessionrequestsplitter	2.098s
ok  	github.com/ipfs/go-bitswap/testnet	2.546s
?   	github.com/ipfs/go-bitswap/testutil	[no test files]
ok  	github.com/ipfs/go-bitswap/wantlist	1.035s
ok  	github.com/ipfs/go-bitswap/wantmanager	1.814s

@Stebalien
Copy link
Member

Diff to fix the current race:

diff --git a/peermanager/peermanager.go b/peermanager/peermanager.go
index 0abb25b..d95b4a6 100644
--- a/peermanager/peermanager.go
+++ b/peermanager/peermanager.go
@@ -56,11 +56,12 @@ func New(ctx context.Context, createPeerQueue PeerQueueFactory) *PeerManager {
 
 // ConnectedPeers returns a list of peers this PeerManager is managing.
 func (pm *PeerManager) ConnectedPeers() []peer.ID {
-
+	pm.peerQueuesLk.RLock()
+	defer pm.peerQueuesLk.RUnlock()
 	peers := make([]peer.ID, 0, len(pm.peerQueues))
-	pm.iterate(func(p peer.ID, _ PeerQueue) {
+	for p := range pm.peerQueues {
 		peers = append(peers, p)
-	})
+	}
 	return peers
 }

Other than that, the race detector isn't agreeing with my spidy senses.

fix race conditions while setting up wantlists by creating peer queues on demand

BREAKING CHANGE: PeerManager SendMessage signature changed

fix #51
Limit retrying sending of a message even when a successful reconnect occurs
If wantlist changes are present, send them immediately on startup, rather than as a seperate message
Breakup Startup function so that wantlists are not sent with each call to SendMessage
Constrain use of mutex to actual operations on the peerQueues map via utility functions
repace get/set with getOrCreate to keep operations atomic
Keep all of disconnection in a mutex
fix remaining issues for race detector in peer manager
Move refcnt tracking from the messagequeue to the peermanager, where it's relevant
@Stebalien Stebalien merged commit 472a8ab into master Feb 20, 2019
@ghost ghost removed the status/in-progress In progress label Feb 20, 2019
@Stebalien Stebalien deleted the bugs/racy-wantlist-handling branch February 21, 2019 00:23
Jorropo pushed a commit to Jorropo/go-libipfs that referenced this pull request Jan 26, 2023
…ndling

fix(wantlist): remove races on setup

This commit was moved from ipfs/go-bitswap@472a8ab
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Initial wantlist handling is racy Limit the number of retries when sending messages
2 participants