From e4075b5241caf94d6fce705afd34c12de38ae9f3 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 4 May 2023 13:11:02 +0530 Subject: [PATCH] client: Fix unclean shutdown scenario where SIGINT may come before client fully started (#2677) --- packages/client/bin/cli.ts | 48 +++++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 14 deletions(-) diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 00648129ff..1133c0f351 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -785,22 +785,42 @@ async function run() { config.logger.info(`Reading custom genesis state accounts=${numAccounts}`) } - const client = await startClient(config, customGenesisState) - const servers = - args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] - if ( - client.config.chainCommon.gteHardfork(Hardfork.Paris) === true && - (args.rpcEngine === false || args.rpcEngine === undefined) - ) { - config.logger.warn(`Engine RPC endpoint not activated on a post-Merge HF setup.`) - } + // Do not wait for client to be fully started so that we can hookup SIGINT handling + // else a SIGINT before may kill the process in unclean manner + const clientStartPromise = startClient(config, customGenesisState) + .then((client) => { + const servers = + args.rpc === true || args.rpcEngine === true ? startRPCServers(client, args as RPCArgs) : [] + if ( + client.config.chainCommon.gteHardfork(Hardfork.Paris) === true && + (args.rpcEngine === false || args.rpcEngine === undefined) + ) { + config.logger.warn(`Engine RPC endpoint not activated on a post-Merge HF setup.`) + } + config.logger.info('Client started successfully') + return { client, servers } + }) + .catch((e) => { + config.logger.error('Error starting client', e) + return null + }) + process.on('SIGINT', async () => { - config.logger.info('Caught interrupt signal. Shutting down...') - for (const s of servers) { - s.http().close() + config.logger.info('Caught interrupt signal. Obtaining client handle for clean shutdown...') + config.logger.info('(This might take a little longer if client not yet fully started)') + const clientHandle = await clientStartPromise + if (clientHandle !== null) { + config.logger.info('Shutting down the client and the servers...') + const { client, servers } = clientHandle + for (const s of servers) { + s.http().close() + } + await client.stop() + config.logger.info('Exiting.') + } else { + config.logger.info('Client did not start properly, exiting ...') } - await client.stop() - config.logger.info('Exiting.') + process.exit() }) }