Skip to content

Commit

Permalink
Add error handling for async errors (#2984)
Browse files Browse the repository at this point in the history
  • Loading branch information
acolytec3 authored Aug 24, 2023
1 parent 66e79cc commit 490b7a1
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
19 changes: 18 additions & 1 deletion packages/client/bin/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,14 @@ function generateAccount(): Account {
const stopClient = async (config: Config, clientStartPromise: any) => {
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)')
let timeoutHandle
if (clientStartPromise.toString().includes('Promise') === true)
// Client hasn't finished starting up so setting timeout to terminate process if not already shutdown gracefully
timeoutHandle = setTimeout(() => {
config.logger.warn('Client has become unresponsive while starting up.')
config.logger.warn('Check logging output for potential errors. Exiting...')
process.exit(1)
}, 30000)
const clientHandle = await clientStartPromise
if (clientHandle !== null) {
config.logger.info('Shutting down the client and the servers...')
Expand All @@ -682,7 +690,7 @@ const stopClient = async (config: Config, clientStartPromise: any) => {
} else {
config.logger.info('Client did not start properly, exiting ...')
}

clearTimeout(timeoutHandle)
process.exit()
}

Expand Down Expand Up @@ -861,6 +869,15 @@ async function run() {
process.on('SIGTERM', async () => {
await stopClient(config, clientStartPromise)
})

process.on('uncaughtException', (err) => {
// Handles uncaught exceptions that are thrown in async events/functions and aren't caught in
// main client process
config.logger.error(`Uncaught error: ${err.message}`)
config.logger.error(err)

void stopClient(config, clientStartPromise)
})
}

run().catch((err) => {
Expand Down
7 changes: 6 additions & 1 deletion packages/client/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,12 @@ export class EthereumClient {

await Promise.all(this.services.map((s) => s.start()))
await Promise.all(this.config.servers.map((s) => s.start()))
await Promise.all(this.config.servers.map((s) => s.bootstrap()))
await Promise.all(
this.config.servers.map(async (s) => {
// Only call bootstrap if servers are actually started
if (s.started) await s.bootstrap()
})
)
this.started = true
}

Expand Down
12 changes: 10 additions & 2 deletions packages/client/src/net/server/rlpxserver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,11 @@ export class RlpxServer extends Server {
dnsAddr: this.config.dnsAddr,
})

this.dpt.events.on('error', (e: Error) => this.error(e))
this.dpt.events.on('error', (e: Error) => {
this.error(e)
// If DPT can't bind to port, resolve anyway so client startup doesn't hang
if (e.message.includes('EADDRINUSE')) resolve()
})

this.dpt.events.on('listening', () => {
resolve()
Expand Down Expand Up @@ -292,7 +296,11 @@ export class RlpxServer extends Server {
this.error(error)
)

this.rlpx.events.on('error', (e: Error) => this.error(e))
this.rlpx.events.on('error', (e: Error) => {
this.error(e)
// If DPT can't bind to port, resolve anyway so client startup doesn't hang
if (e.message.includes('EADDRINUSE')) resolve()
})

this.rlpx.events.on('listening', () => {
this.config.events.emit(Event.SERVER_LISTENING, {
Expand Down

0 comments on commit 490b7a1

Please sign in to comment.