From 514c3f06ada69f5c6ae6395f84bfcc95a0a0882b Mon Sep 17 00:00:00 2001 From: Slyghtning Date: Fri, 31 Jul 2026 21:16:37 +0200 Subject: [PATCH] loopd: close tapd client connections Close the TapdClient when daemon initialization fails, during normal shutdown, and after the view command completes. This prevents gRPC transport resources from leaking across embedded daemon lifecycles and error paths. --- loopd/daemon.go | 21 +++++++++++++++++---- loopd/view.go | 1 + 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/loopd/daemon.go b/loopd/daemon.go index f625aa27..319709d8 100644 --- a/loopd/daemon.go +++ b/loopd/daemon.go @@ -158,6 +158,15 @@ func (d *Daemon) Start() error { if err != nil { return err } + + defer func() { + if err == nil || d.assetClient == nil { + return + } + + d.assetClient.Close() + d.assetClient = nil + }() } // With lnd connected, initialize everything else, such as the swap @@ -178,15 +187,15 @@ func (d *Daemon) Start() error { // If we get here, we already have started several goroutines. So if // anything goes wrong now, we need to cleanly shut down again. - startErr := d.startWebServers() - if startErr != nil { - errorf("Error while starting daemon: %v", startErr) + err = d.startWebServers() + if err != nil { + errorf("Error while starting daemon: %v", err) d.Stop() stopErr := <-d.ErrChan if stopErr != nil { errorf("Error while stopping daemon: %v", stopErr) } - return startErr + return err } return nil @@ -1145,6 +1154,10 @@ func (d *Daemon) stop() { if d.clientCleanup != nil { d.clientCleanup() } + if d.assetClient != nil { + d.assetClient.Close() + d.assetClient = nil + } // Everything should be shutting down now, wait for completion. d.wg.Wait() diff --git a/loopd/view.go b/loopd/view.go index 73b401d8..86b9604a 100644 --- a/loopd/view.go +++ b/loopd/view.go @@ -44,6 +44,7 @@ func view(config *Config, lisCfg *ListenerCfg) error { if err != nil { return err } + defer assetClient.Close() } swapClient, cleanup, err := getClient(