orbs-network / orbs-network-go

Orbs node virtual chain core reference implementation in Go
MIT License
48 stars 12 forks source link

BlockTracker may panic on double close() #95

Closed ronnno closed 6 years ago

ronnno commented 6 years ago

https://github.com/orbs-network/orbs-network-go/blob/fc0cf472dcb249de489bc11be5553bd06f93f073/services/statestorage/block_tracker.go#L35

Two goroutines concurrently calling IncrementHeight() may attempt close the same channel twice causing panic.

We could:

The first option seems more straight forward and readable. But might also be less efficient. @electricmonk, what do you think?

electricmonk commented 6 years ago

depends on what are the odds of this actually happening. Which goroutine should "normally" call the code that in turn calls IncrementHeight()?

ronnno commented 6 years ago

chances are pretty low of this colliding. Calling service is BlockStorage in Block Creation and Intra-Node Sync flows.

In a single block service scenario it's highly unlikely. If we ever have multiple instances of BlockStorage in a single node this might be more likely.

ronnno commented 6 years ago

better solution:

use atomic.LoadPointer and atomic.SwatPointer as in this example: https://gist.github.com/zviadm/c234426882bfc8acba88f3503edaaa36#file-cond2-go

ronnno commented 6 years ago

decided on the simple (rw)mutex solution. we cannot avoid a mutex and this is the simplest mutex solution.

on the way, addressed another possible race condition in waiting for loop in WaitForBlock(): if block height is incremented between the for loop condition and the select's latch evaluation we might wait an additional block accidentally - or if we're unlucky even reach timeout even tough the desired block has already arrived).