code: func (bc *BlockChain) Stop() {
  	if !atomic.CompareAndSwapInt32(&bc.running, 0, 1) {
  		return
  	}
  	// Unsubscribe all subscriptions registered from blockchain
  	bc.scope.Close()
  	close(bc.quit)
  	atomic.StoreInt32(&bc.procInterrupt, 1)
  
  	bc.wg.Wait()
  
  	// Ensure the state of a recent block is also stored to disk before exiting.
  	// We're writing three different states to catch different restart scenarios:
  	//  - HEAD:     So we don't need to reprocess any blocks in the general case
  	//  - HEAD-1:   So we don't do large reorgs if our HEAD becomes an uncle
  	//  - HEAD-127: So we have a hard limit on the number of blocks reexecuted
  	if !bc.cacheConfig.TrieDirtyDisabled {
  		triedb := bc.stateCache.TrieDB()
  
  		for _, offset := range []uint64{0, 1, triesInMemory - 1} {
  			if number := bc.CurrentBlock().NumberU64(); number > offset {
  				recent := bc.GetBlockByNumber(number - offset)
  
  				log.Info("Writing cached state to disk", "block", recent.Number(), "hash", recent.Hash(), "root", recent.Root())
  				if err := triedb.Commit(recent.Root(), true); err != nil {
  					log.Error("Failed to commit recent state trie", "err", err)
  				}
  			}
  		}
  		for !bc.triegc.Empty() {
  			triedb.Dereference(bc.triegc.PopItem().(common.Hash))
  		}
  		if size, _ := triedb.Size(); size != 0 {
  			log.Error("Dangling trie nodes after full cleanup")
  		}
  	}
  	log.Info("Blockchain manager stopped")
  }
docs: // Stop stops the blockchain service. If any imports are currently in progress
  // it will abort them using the procInterrupt.