From ef7a9ad69a6937f9db7cda31d6a148f0fcec1547 Mon Sep 17 00:00:00 2001 From: Tom Kirkpatrick Date: Thu, 23 Aug 2018 18:47:29 +0200 Subject: [PATCH] fix(lnd): ensure graceful shutdown Lnd doesn't currently do a graceful shutdown when a `SIGTERM` is issued. To ensure a graceful shutdown, call `stopDaemon` on the gRPC interface prior to terminating lnd. See - https://github.com/lightningnetwork/lnd/issues/1028 - https://api.lightning.community/#stopdaemon --- app/lib/lnd/lightning.js | 15 ++++++++++++++ app/lib/zap/controller.js | 41 ++++++++++++++++++--------------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/app/lib/lnd/lightning.js b/app/lib/lnd/lightning.js index 81e466e3..e21fa345 100644 --- a/app/lib/lnd/lightning.js +++ b/app/lib/lnd/lightning.js @@ -94,6 +94,21 @@ class Lightning { } } + /** + * Gracegfully shutdown the gRPC service. + */ + shutdown() { + this.unsubscribe() + return new Promise((resolve, reject) => { + this.lnd.stopDaemon({}, (err, data) => { + if (err) { + reject(err) + } + resolve(data) + }) + }) + } + /** * Hook up lnd restful methods. */ diff --git a/app/lib/zap/controller.js b/app/lib/zap/controller.js index 25e12bc7..1bb21108 100644 --- a/app/lib/zap/controller.js +++ b/app/lib/zap/controller.js @@ -127,7 +127,7 @@ class ZapController { // FSM Callbacks // ------------------------------------ - onOnboarding() { + async onOnboarding() { mainLog.debug('[FSM] onOnboarding...') // Remove any existing IPC listeners so that we can start fresh. @@ -136,13 +136,8 @@ class ZapController { // Register IPC listeners so that we can react to instructions coming from the app. this._registerIpcListeners() - // Ensure wallet is disconnected. - this.disconnectLightningWallet() - - // If Neutrino is running, kill it. - if (this.neutrino) { - this.neutrino.stop() - } + // Disconnect from any existing connection. + await this.disconnectLightningWallet() // Give the grpc connections a chance to be properly closed out. return new Promise(resolve => setTimeout(resolve, 200)) @@ -209,16 +204,9 @@ class ZapController { }) } - onTerminated() { + async onTerminated() { mainLog.debug('[FSM] onTerminated...') - // Unsubscribe the gRPC streams before thhe window closes. This ensures that we can properly reestablish a fresh - // connection when a new window is opened. - this.disconnectLightningWallet() - - // If Neutrino is running, kill it. - if (this.neutrino) { - this.neutrino.stop() - } + await this.disconnectLightningWallet() } onTerminate() { @@ -275,10 +263,10 @@ class ZapController { * Create and subscribe to the Lightning service. */ async startLightningWallet() { + mainLog.info('Starting lightning wallet...') if (this.lightningGrpcConnected) { return } - mainLog.info('Starting lightning wallet...') this.lightning = new Lightning() // Connect to the Lightning interface. @@ -300,14 +288,23 @@ class ZapController { /** * Unsubscribe from the Lightning service. */ - disconnectLightningWallet() { + async disconnectLightningWallet() { + mainLog.info('Shutting down lightning Wallet...') if (!this.lightningGrpcConnected) { return } - mainLog.info('Disconnecting lightning Wallet...') - // Disconnect streams. - this.lightning.disconnect() + // Shutdown / disconnect from the lnd instance. + try { + if (this.neutrino) { + await this.lightning.shutdown() + this.neutrino.stop() + } else if (this.lightning) { + this.lightning.disconnect() + } + } catch (e) { + mainLog.error('There was a problem when trying to shutdown lnd', e) + } // Update our internal state. this.lightningGrpcConnected = false