From 65ab3dbfc8a083119dacd4ccc17aff799b285679 Mon Sep 17 00:00:00 2001 From: Roei Erez Date: Thu, 8 Apr 2021 12:58:32 +0300 Subject: [PATCH] server: better way to clean chainControl resources In this commit the location of where chain control services are stopped is shifted to be closer to the point they are started. Stopping of two services: "wallet" and "feeEstimator" that are started inside the "newChainControlFromConfig" was shifted from server.go to the cleanup function. In addition the chainView.Stop was also removed from the server.Stop as it is already handled by the router, where it is being started. --- chainreg/chainregistry.go | 69 +++++++++++++++++++++++---------------- lnd.go | 5 ++- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 30025ad1..d746f4eb 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -226,7 +226,7 @@ type ChainControl struct { // full-node, another backed by a running bitcoind full-node, and the other // backed by a running neutrino light client instance. When running with a // neutrino light client instance, `neutrinoCS` must be non-nil. -func NewChainControl(cfg *Config) (*ChainControl, error) { +func NewChainControl(cfg *Config) (*ChainControl, func(), error) { // Set the RPC config from the "home" chain. Multi-chain isn't yet // active, so we'll restrict usage to a particular chain for now. @@ -264,7 +264,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { DefaultLitecoinStaticFeePerKW, 0, ) default: - return nil, fmt.Errorf("default routing policy for chain %v is "+ + return nil, nil, fmt.Errorf("default routing policy for chain %v is "+ "unknown", cfg.PrimaryChain()) } @@ -294,7 +294,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { heightHintCacheConfig, cfg.LocalChanDB, ) if err != nil { - return nil, fmt.Errorf("unable to initialize height hint "+ + return nil, nil, fmt.Errorf("unable to initialize height hint "+ "cache: %v", err) } @@ -311,14 +311,14 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { ) cc.ChainView, err = chainview.NewCfFilteredChainView(cfg.NeutrinoCS) if err != nil { - return nil, err + return nil, nil, err } // Map the deprecated neutrino feeurl flag to the general fee // url. if cfg.NeutrinoMode.FeeURL != "" { if cfg.FeeURL != "" { - return nil, errors.New("feeurl and " + + return nil, nil, errors.New("feeurl and " + "neutrino.feeurl are mutually exclusive") } @@ -358,7 +358,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { // this back to the btcwallet/bitcoind port. rpcPort, err := strconv.Atoi(cfg.ActiveNetParams.RPCPort) if err != nil { - return nil, err + return nil, nil, err } rpcPort -= 2 bitcoindHost = fmt.Sprintf("%v:%d", @@ -390,11 +390,11 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { 5*time.Second, ) if err != nil { - return nil, err + return nil, nil, err } if err := bitcoindConn.Start(); err != nil { - return nil, fmt.Errorf("unable to connect to bitcoind: "+ + return nil, nil, fmt.Errorf("unable to connect to bitcoind: "+ "%v", err) } @@ -429,7 +429,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } else if cfg.Litecoin.Active && !cfg.Litecoin.RegTest { log.Infof("Initializing litecoind backed fee estimator in "+ @@ -445,7 +445,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } @@ -454,14 +454,14 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { // connection. chainConn, err := rpcclient.New(rpcConfig, nil) if err != nil { - return nil, err + return nil, nil, err } // The api we will use for our health check depends on the // bitcoind version. cmd, err := getBitcoindHealthCheckCmd(chainConn) if err != nil { - return nil, err + return nil, nil, err } cc.HealthCheck = func() error { @@ -487,19 +487,19 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { if btcdMode.RawRPCCert != "" { rpcCert, err = hex.DecodeString(btcdMode.RawRPCCert) if err != nil { - return nil, err + return nil, nil, err } } else { certFile, err := os.Open(btcdMode.RPCCert) if err != nil { - return nil, err + return nil, nil, err } rpcCert, err = ioutil.ReadAll(certFile) if err != nil { - return nil, err + return nil, nil, err } if err := certFile.Close(); err != nil { - return nil, err + return nil, nil, err } } @@ -531,7 +531,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { rpcConfig, cfg.ActiveNetParams.Params, hintCache, hintCache, ) if err != nil { - return nil, err + return nil, nil, err } // Finally, we'll create an instance of the default chain view to be @@ -539,7 +539,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { cc.ChainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig) if err != nil { log.Errorf("unable to create chain view: %v", err) - return nil, err + return nil, nil, err } // Create a special websockets rpc client for btcd which will be used @@ -547,7 +547,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { chainRPC, err := chain.NewRPCClient(cfg.ActiveNetParams.Params, btcdHost, btcdUser, btcdPass, rpcCert, false, 20) if err != nil { - return nil, err + return nil, nil, err } walletConfig.ChainSource = chainRPC @@ -574,11 +574,11 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { *rpcConfig, fallBackFeeRate.FeePerKWeight(), ) if err != nil { - return nil, err + return nil, nil, err } } default: - return nil, fmt.Errorf("unknown node type: %s", + return nil, nil, fmt.Errorf("unknown node type: %s", homeChainConfig.Node) } @@ -589,7 +589,7 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { case cfg.FeeURL == "" && cfg.Bitcoin.MainNet && homeChainConfig.Node == "neutrino": - return nil, fmt.Errorf("--feeurl parameter required when " + + return nil, nil, fmt.Errorf("--feeurl parameter required when " + "running neutrino on mainnet") // Override default fee estimator if an external service is specified. @@ -609,15 +609,29 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { ) } + ccCleanup := func() { + if cc.Wallet != nil { + if err := cc.Wallet.Shutdown(); err != nil { + log.Errorf("Failed to shutdown wallet: %v", err) + } + } + + if cc.FeeEstimator != nil { + if err := cc.FeeEstimator.Stop(); err != nil { + log.Errorf("Failed to stop feeEstimator: %v", err) + } + } + } + // Start fee estimator. if err := cc.FeeEstimator.Start(); err != nil { - return nil, err + return nil, nil, err } wc, err := btcwallet.New(*walletConfig) if err != nil { fmt.Printf("unable to create wallet controller: %v\n", err) - return nil, err + return nil, ccCleanup, err } cc.MsgSigner = wc @@ -652,18 +666,17 @@ func NewChainControl(cfg *Config) (*ChainControl, error) { lnWallet, err := lnwallet.NewLightningWallet(walletCfg) if err != nil { fmt.Printf("unable to create wallet: %v\n", err) - return nil, err + return nil, ccCleanup, err } if err := lnWallet.Startup(); err != nil { fmt.Printf("unable to start wallet: %v\n", err) - return nil, err + return nil, ccCleanup, err } log.Info("LightningWallet opened") - cc.Wallet = lnWallet - return cc, nil + return cc, ccCleanup, nil } // getBitcoindHealthCheckCmd queries bitcoind for its version to decide which diff --git a/lnd.go b/lnd.go index d3edde16..0fb866e0 100644 --- a/lnd.go +++ b/lnd.go @@ -545,7 +545,10 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error FeeURL: cfg.FeeURL, } - activeChainControl, err := chainreg.NewChainControl(chainControlCfg) + activeChainControl, cleanup, err := chainreg.NewChainControl(chainControlCfg) + if cleanup != nil { + defer cleanup() + } if err != nil { err := fmt.Errorf("unable to create chain control: %v", err) ltndLog.Error(err)