Skip to content

Commit 8202bae

Browse files
committed
Merge pull request ethereum#1939 from karalabe/fix-blocked-sync-goroutines
eth: don't block sync goroutines that short circuit
2 parents 56f8699 + 667987e commit 8202bae

File tree

3 files changed

+27
-15
lines changed

3 files changed

+27
-15
lines changed

core/blockchain.go

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -411,28 +411,35 @@ func (self *BlockChain) ExportN(w io.Writer, first uint64, last uint64) error {
411411

412412
// insert injects a new head block into the current block chain. This method
413413
// assumes that the block is indeed a true head. It will also reset the head
414-
// header and the head fast sync block to this very same block to prevent them
415-
// from pointing to a possibly old canonical chain (i.e. side chain by now).
414+
// header and the head fast sync block to this very same block if they are older
415+
// or if they are on a different side chain.
416416
//
417417
// Note, this function assumes that the `mu` mutex is held!
418418
func (bc *BlockChain) insert(block *types.Block) {
419+
// If the block is on a side chain or an unknown one, force other heads onto it too
420+
updateHeads := GetCanonicalHash(bc.chainDb, block.NumberU64()) != block.Hash()
421+
419422
// Add the block to the canonical chain number scheme and mark as the head
420423
if err := WriteCanonicalHash(bc.chainDb, block.Hash(), block.NumberU64()); err != nil {
421424
glog.Fatalf("failed to insert block number: %v", err)
422425
}
423426
if err := WriteHeadBlockHash(bc.chainDb, block.Hash()); err != nil {
424427
glog.Fatalf("failed to insert head block hash: %v", err)
425428
}
426-
if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil {
427-
glog.Fatalf("failed to insert head header hash: %v", err)
428-
}
429-
if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil {
430-
glog.Fatalf("failed to insert head fast block hash: %v", err)
431-
}
432-
// Update the internal state with the head block
433429
bc.currentBlock = block
434-
bc.currentHeader = block.Header()
435-
bc.currentFastBlock = block
430+
431+
// If the block is better than out head or is on a different chain, force update heads
432+
if updateHeads {
433+
if err := WriteHeadHeaderHash(bc.chainDb, block.Hash()); err != nil {
434+
glog.Fatalf("failed to insert head header hash: %v", err)
435+
}
436+
bc.currentHeader = block.Header()
437+
438+
if err := WriteHeadFastBlockHash(bc.chainDb, block.Hash()); err != nil {
439+
glog.Fatalf("failed to insert head fast block hash: %v", err)
440+
}
441+
bc.currentFastBlock = block
442+
}
436443
}
437444

438445
// Accessors

eth/downloader/downloader.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,10 +248,11 @@ func (d *Downloader) UnregisterPeer(id string) error {
248248

249249
// Synchronise tries to sync up our local block chain with a remote peer, both
250250
// adding various sanity checks as well as wrapping it with various log entries.
251-
func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) {
251+
func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error {
252252
glog.V(logger.Detail).Infof("Attempting synchronisation: %v, head [%x…], TD %v", id, head[:4], td)
253253

254-
switch err := d.synchronise(id, head, td, mode); err {
254+
err := d.synchronise(id, head, td, mode)
255+
switch err {
255256
case nil:
256257
glog.V(logger.Detail).Infof("Synchronisation completed")
257258

@@ -268,6 +269,7 @@ func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode
268269
default:
269270
glog.V(logger.Warn).Infof("Synchronisation failed: %v", err)
270271
}
272+
return err
271273
}
272274

273275
// synchronise will select the peer and use it for synchronising. If an empty string is given

eth/sync.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,13 +170,16 @@ func (pm *ProtocolManager) synchronise(peer *peer) {
170170
if pm.fastSync {
171171
mode = downloader.FastSync
172172
}
173-
pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode)
174-
173+
if err := pm.downloader.Synchronise(peer.id, peer.Head(), peer.Td(), mode); err != nil {
174+
return
175+
}
175176
// If fast sync was enabled, and we synced up, disable it
176177
if pm.fastSync {
178+
// Wait until all pending imports finish processing
177179
for pm.downloader.Synchronising() {
178180
time.Sleep(100 * time.Millisecond)
179181
}
182+
// Disable fast sync if we indeed have something in our chain
180183
if pm.blockchain.CurrentBlock().NumberU64() > 0 {
181184
glog.V(logger.Info).Infof("fast sync complete, auto disabling")
182185
pm.fastSync = false

0 commit comments

Comments
 (0)