Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@
transitions during startup, avoiding lost unlocks during slow database
initialization.

* [Ensure that the interceptor is properly closed on failure paths in `lnd.Start`](https://github.com/lightningnetwork/lnd/pull/10587).
This is mostly relevant for mobile and lnd-as-a-lib use-cases where subsequent
attempts to start lnd would otherwise fail with "intercept already started"
errors as the state stays in-process.

# New Features

- Basic Support for [onion messaging forwarding](https://github.com/lightningnetwork/lnd/pull/9868)
Expand Down Expand Up @@ -191,6 +196,7 @@
* Boris Nagaev
* Elle Mouton
* Erick Cestari
* Hampus Sjöberg
* hieblmi
* Matt Morehouse
* Mohamed Awnallah
Expand Down
13 changes: 12 additions & 1 deletion lnd.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ var errStreamIsolationWithProxySkip = errors.New(
// This function starts all main system components then blocks until a signal
// is received on the shutdownChan at which point everything is shut down again.
func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
interceptor signal.Interceptor) error {
interceptor signal.Interceptor) (mainErr error) {

defer func() {
ltndLog.Info("Shutdown complete")
Expand All @@ -156,6 +156,17 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
}
}()

// Make sure the signal interceptor is always fully stopped on any
// startup/runtime error so callers can safely retry startup.
defer func() {
if mainErr == nil {
return
}

interceptor.RequestShutdown()
<-interceptor.ShutdownChannel()
}()

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

Expand Down
33 changes: 33 additions & 0 deletions lnd_main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package lnd

import (
"net"
"testing"
"time"

"github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/signal"
"github.com/stretchr/testify/require"
)

// TestMainErrorShutsDownInterceptor asserts that Main error paths always close
// the signal interceptor so startup can be retried in-process.
func TestMainErrorShutsDownInterceptor(t *testing.T) {
interceptor, err := signal.Intercept()
require.NoError(t, err)

cfg := DefaultConfig()
cfg.Pprof = &lncfg.Pprof{}
cfg.RPCListeners = []net.Addr{
&net.UnixAddr{Net: "invalid-network"},
}
mainErr := Main(&cfg, ListenerCfg{}, nil, interceptor)
require.Error(t, mainErr)

select {
case <-interceptor.ShutdownChannel():
case <-time.After(5 * time.Second):
t.Fatalf("interceptor wasn't shut down after Main returned " +
"error")
}
}
Loading