Ctrl+C now stops the BN when waiting for genesis (#1761)
* Ctrl+C now stops the BN when waiting for genesis * proper shutdown when waiting for genesis if Ctrl+C is used
This commit is contained in:
parent
a2270a5f27
commit
2e6fd8976a
|
@ -26,7 +26,7 @@ import
|
|||
spec/state_transition,
|
||||
conf, time, beacon_chain_db, validator_pool, extras,
|
||||
attestation_pool, exit_pool, eth2_network, eth2_discovery,
|
||||
beacon_node_common, beacon_node_types,
|
||||
beacon_node_common, beacon_node_types, beacon_node_status,
|
||||
block_pools/[spec_cache, chain_dag, quarantine, clearance, block_pools_types],
|
||||
nimbus_binary_common, network_metadata,
|
||||
mainchain_monitor, version, ssz/[merkleization], merkle_minimal,
|
||||
|
@ -42,13 +42,6 @@ const
|
|||
type
|
||||
RpcServer* = RpcHttpServer
|
||||
|
||||
# "state" is already taken by BeaconState
|
||||
BeaconNodeStatus* = enum
|
||||
Starting, Running, Stopping
|
||||
|
||||
# this needs to be global, so it can be set in the Ctrl+C signal handler
|
||||
var status = BeaconNodeStatus.Starting
|
||||
|
||||
template init(T: type RpcHttpServer, ip: ValidIpAddress, port: Port): T =
|
||||
newRpcHttpServer([initTAddress(ip, port)])
|
||||
|
||||
|
@ -190,6 +183,8 @@ proc init*(T: type BeaconNode,
|
|||
mainchainMonitor.start()
|
||||
|
||||
genesisState = await mainchainMonitor.waitGenesis()
|
||||
if bnStatus == BeaconNodeStatus.Stopping:
|
||||
return nil
|
||||
|
||||
info "Eth2 genesis state detected",
|
||||
genesisTime = genesisState.genesisTime,
|
||||
|
@ -849,7 +844,7 @@ proc installMessageValidators(node: BeaconNode) =
|
|||
node.processor[].voluntaryExitValidator(signedVoluntaryExit))
|
||||
|
||||
proc stop*(node: BeaconNode) =
|
||||
status = BeaconNodeStatus.Stopping
|
||||
bnStatus = BeaconNodeStatus.Stopping
|
||||
info "Graceful shutdown"
|
||||
if not node.config.inProcessValidators:
|
||||
node.vcProcess.close()
|
||||
|
@ -858,9 +853,9 @@ proc stop*(node: BeaconNode) =
|
|||
info "Database closed"
|
||||
|
||||
proc run*(node: BeaconNode) =
|
||||
if status == BeaconNodeStatus.Starting:
|
||||
if bnStatus == BeaconNodeStatus.Starting:
|
||||
# it might have been set to "Stopping" with Ctrl+C
|
||||
status = BeaconNodeStatus.Running
|
||||
bnStatus = BeaconNodeStatus.Running
|
||||
|
||||
if node.rpcServer != nil:
|
||||
node.rpcServer.installRpcHandlers(node)
|
||||
|
@ -888,7 +883,7 @@ proc run*(node: BeaconNode) =
|
|||
node.startSyncManager()
|
||||
|
||||
# main event loop
|
||||
while status == BeaconNodeStatus.Running:
|
||||
while bnStatus == BeaconNodeStatus.Running:
|
||||
try:
|
||||
poll()
|
||||
except CatchableError as e:
|
||||
|
@ -1208,7 +1203,7 @@ programMain:
|
|||
# workaround for https://github.com/nim-lang/Nim/issues/4057
|
||||
setupForeignThreadGc()
|
||||
info "Shutting down after having received SIGINT"
|
||||
status = BeaconNodeStatus.Stopping
|
||||
bnStatus = BeaconNodeStatus.Stopping
|
||||
setControlCHook(controlCHandler)
|
||||
|
||||
when useInsecureFeatures:
|
||||
|
@ -1219,6 +1214,8 @@ programMain:
|
|||
metrics.startHttpServer($metricsAddress, config.metricsPort)
|
||||
|
||||
var node = waitFor BeaconNode.init(rng, config, stateSnapshotContents)
|
||||
if bnStatus == BeaconNodeStatus.Stopping:
|
||||
return
|
||||
|
||||
when hasPrompt:
|
||||
initPrompt(node)
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
# beacon_chain
|
||||
# Copyright (c) 2018-2020 Status Research & Development GmbH
|
||||
# Licensed and distributed under either of
|
||||
# * MIT license (license terms in the root directory or at https://opensource.org/licenses/MIT).
|
||||
# * Apache v2 license (license terms in the root directory or at https://www.apache.org/licenses/LICENSE-2.0).
|
||||
# at your option. This file may not be copied, modified, or distributed except according to those terms.
|
||||
|
||||
type
|
||||
# "state" is already taken by BeaconState
|
||||
BeaconNodeStatus* = enum
|
||||
Starting
|
||||
Running
|
||||
Stopping
|
||||
|
||||
# this needs to be global, so it can be set in the Ctrl+C signal handler
|
||||
var bnStatus* = BeaconNodeStatus.Starting
|
|
@ -3,7 +3,8 @@ import
|
|||
chronos, web3, web3/ethtypes as web3Types, json, chronicles,
|
||||
eth/common/eth_types, eth/async_utils,
|
||||
spec/[datatypes, digest, crypto, beaconstate, helpers, validator],
|
||||
network_metadata, merkle_minimal
|
||||
network_metadata, merkle_minimal,
|
||||
beacon_node_status
|
||||
|
||||
from times import epochTime
|
||||
|
||||
|
@ -564,8 +565,27 @@ proc findGenesisBlockInRange(m: MainchainMonitor,
|
|||
|
||||
return endBlock
|
||||
|
||||
proc safeCancel(fut: var Future[void]) =
|
||||
if not fut.isNil and not fut.finished:
|
||||
fut.cancel()
|
||||
fut = nil
|
||||
|
||||
proc stop*(m: MainchainMonitor) =
|
||||
safeCancel m.runFut
|
||||
safeCancel m.genesisMonitoringFut
|
||||
|
||||
template checkIfShouldStopMainchainMonitor(m: MainchainMonitor) =
|
||||
if bnStatus == BeaconNodeStatus.Stopping:
|
||||
if not m.genesisStateFut.isNil:
|
||||
m.genesisStateFut.complete()
|
||||
m.genesisStateFut = nil
|
||||
m.stop
|
||||
return
|
||||
|
||||
proc checkForGenesisLoop(m: MainchainMonitor) {.async.} =
|
||||
while true:
|
||||
m.checkIfShouldStopMainchainMonitor()
|
||||
|
||||
if not m.genesisState.isNil:
|
||||
return
|
||||
|
||||
|
@ -636,6 +656,9 @@ proc waitGenesis*(m: MainchainMonitor): Future[BeaconStateRef] {.async.} =
|
|||
await m.genesisStateFut
|
||||
m.genesisStateFut = nil
|
||||
|
||||
if bnStatus == BeaconNodeStatus.Stopping:
|
||||
return new BeaconStateRef # cannot return nil...
|
||||
|
||||
if m.genesisState != nil:
|
||||
return m.genesisState
|
||||
else:
|
||||
|
@ -677,6 +700,8 @@ proc processDeposits(m: MainchainMonitor,
|
|||
# it could easily re-order the steps due to the intruptable
|
||||
# interleaved execution of async code.
|
||||
while true:
|
||||
m.checkIfShouldStopMainchainMonitor()
|
||||
|
||||
let blk = await m.depositQueue.popFirst()
|
||||
m.eth1Chain.trimHeight(Eth1BlockNumber(blk.number) - 1)
|
||||
|
||||
|
@ -776,15 +801,6 @@ proc run(m: MainchainMonitor, delayBeforeStart: Duration) {.async.} =
|
|||
finally:
|
||||
await close(dataProvider)
|
||||
|
||||
proc safeCancel(fut: var Future[void]) =
|
||||
if not fut.isNil and not fut.finished:
|
||||
fut.cancel()
|
||||
fut = nil
|
||||
|
||||
proc stop*(m: MainchainMonitor) =
|
||||
safeCancel m.runFut
|
||||
safeCancel m.genesisMonitoringFut
|
||||
|
||||
proc start(m: MainchainMonitor, delayBeforeStart: Duration) =
|
||||
if m.runFut.isNil:
|
||||
let runFut = m.run(delayBeforeStart)
|
||||
|
|
Loading…
Reference in New Issue