Skip to content

Commit 653e2f3

Browse files
committed
multi: Allow interrupt of server startup.
This commit does two things. It starts up the server in a way that it can be interrupted and shutdown gracefully. Moreover it makes sure that subsystems clean themselves up when they fail to start. This makes sure that depending subsytems can shutdown gracefully as well and the shutdown process is not stuck.
1 parent 08b68bb commit 653e2f3

File tree

3 files changed

+68
-47
lines changed

3 files changed

+68
-47
lines changed

lnd.go

+25-3
Original file line numberDiff line numberDiff line change
@@ -674,11 +674,33 @@ func Main(cfg *Config, lisCfg ListenerCfg, implCfg *ImplementationCfg,
674674
bestHeight)
675675

676676
// With all the relevant chains initialized, we can finally start the
677-
// server itself.
678-
if err := server.Start(); err != nil {
677+
// server itself. We start the server in an asynchronous goroutine so
678+
// that we are able to interrupt and shutdown the daemon gracefully in
679+
// case the startup of the subservers do not behave as expected.
680+
errChan := make(chan error)
681+
go func() {
682+
errChan <- server.Start()
683+
}()
684+
685+
defer func() {
686+
err := server.Stop()
687+
if err != nil {
688+
ltndLog.Warnf("Stopping the server including all "+
689+
"its subsystems failed with %v", err)
690+
}
691+
}()
692+
693+
select {
694+
case err := <-errChan:
695+
if err == nil {
696+
break
697+
}
698+
679699
return mkErr("unable to start server: %v", err)
700+
701+
case <-interceptor.ShutdownChannel():
702+
return nil
680703
}
681-
defer server.Stop()
682704

683705
// We transition the server state to Active, as the server is up.
684706
interceptorChain.SetServerActive()

server.go

+43-43
Original file line numberDiff line numberDiff line change
@@ -1877,6 +1877,8 @@ func (c cleaner) run() {
18771877
// Start starts the main daemon server, all requested listeners, and any helper
18781878
// goroutines.
18791879
// NOTE: This function is safe for concurrent access.
1880+
//
1881+
//nolint:funlen
18801882
func (s *server) Start() error {
18811883
var startErr error
18821884

@@ -1886,194 +1888,189 @@ func (s *server) Start() error {
18861888
cleanup := cleaner{}
18871889

18881890
s.start.Do(func() {
1891+
cleanup = cleanup.add(s.customMessageServer.Stop)
18891892
if err := s.customMessageServer.Start(); err != nil {
18901893
startErr = err
18911894
return
18921895
}
1893-
cleanup = cleanup.add(s.customMessageServer.Stop)
18941896

18951897
if s.hostAnn != nil {
1898+
cleanup = cleanup.add(s.hostAnn.Stop)
18961899
if err := s.hostAnn.Start(); err != nil {
18971900
startErr = err
18981901
return
18991902
}
1900-
cleanup = cleanup.add(s.hostAnn.Stop)
19011903
}
19021904

19031905
if s.livenessMonitor != nil {
1906+
cleanup = cleanup.add(s.livenessMonitor.Stop)
19041907
if err := s.livenessMonitor.Start(); err != nil {
19051908
startErr = err
19061909
return
19071910
}
1908-
cleanup = cleanup.add(s.livenessMonitor.Stop)
19091911
}
19101912

19111913
// Start the notification server. This is used so channel
19121914
// management goroutines can be notified when a funding
19131915
// transaction reaches a sufficient number of confirmations, or
19141916
// when the input for the funding transaction is spent in an
19151917
// attempt at an uncooperative close by the counterparty.
1918+
cleanup = cleanup.add(s.sigPool.Stop)
19161919
if err := s.sigPool.Start(); err != nil {
19171920
startErr = err
19181921
return
19191922
}
1920-
cleanup = cleanup.add(s.sigPool.Stop)
19211923

1924+
cleanup = cleanup.add(s.writePool.Stop)
19221925
if err := s.writePool.Start(); err != nil {
19231926
startErr = err
19241927
return
19251928
}
1926-
cleanup = cleanup.add(s.writePool.Stop)
19271929

1930+
cleanup = cleanup.add(s.readPool.Stop)
19281931
if err := s.readPool.Start(); err != nil {
19291932
startErr = err
19301933
return
19311934
}
1932-
cleanup = cleanup.add(s.readPool.Stop)
19331935

1936+
cleanup = cleanup.add(s.cc.ChainNotifier.Stop)
19341937
if err := s.cc.ChainNotifier.Start(); err != nil {
19351938
startErr = err
19361939
return
19371940
}
1938-
cleanup = cleanup.add(s.cc.ChainNotifier.Stop)
19391941

1942+
cleanup = cleanup.add(s.cc.BestBlockTracker.Stop)
19401943
if err := s.cc.BestBlockTracker.Start(); err != nil {
19411944
startErr = err
19421945
return
19431946
}
1944-
cleanup = cleanup.add(s.cc.BestBlockTracker.Stop)
19451947

1948+
cleanup = cleanup.add(s.channelNotifier.Stop)
19461949
if err := s.channelNotifier.Start(); err != nil {
19471950
startErr = err
19481951
return
19491952
}
1950-
cleanup = cleanup.add(s.channelNotifier.Stop)
19511953

1954+
cleanup = cleanup.add(func() error {
1955+
return s.peerNotifier.Stop()
1956+
})
19521957
if err := s.peerNotifier.Start(); err != nil {
19531958
startErr = err
19541959
return
19551960
}
1956-
cleanup = cleanup.add(func() error {
1957-
return s.peerNotifier.Stop()
1958-
})
1961+
1962+
cleanup = cleanup.add(s.htlcNotifier.Stop)
19591963
if err := s.htlcNotifier.Start(); err != nil {
19601964
startErr = err
19611965
return
19621966
}
1963-
cleanup = cleanup.add(s.htlcNotifier.Stop)
19641967

19651968
if s.towerClientMgr != nil {
1969+
cleanup = cleanup.add(s.towerClientMgr.Stop)
19661970
if err := s.towerClientMgr.Start(); err != nil {
19671971
startErr = err
19681972
return
19691973
}
1970-
cleanup = cleanup.add(s.towerClientMgr.Stop)
19711974
}
19721975

1976+
cleanup = cleanup.add(s.txPublisher.Stop)
19731977
if err := s.txPublisher.Start(); err != nil {
19741978
startErr = err
19751979
return
19761980
}
1977-
cleanup = cleanup.add(func() error {
1978-
s.txPublisher.Stop()
1979-
return nil
1980-
})
19811981

1982+
cleanup = cleanup.add(s.sweeper.Stop)
19821983
if err := s.sweeper.Start(); err != nil {
19831984
startErr = err
19841985
return
19851986
}
1986-
cleanup = cleanup.add(s.sweeper.Stop)
19871987

1988+
cleanup = cleanup.add(s.utxoNursery.Stop)
19881989
if err := s.utxoNursery.Start(); err != nil {
19891990
startErr = err
19901991
return
19911992
}
1992-
cleanup = cleanup.add(s.utxoNursery.Stop)
19931993

1994+
cleanup = cleanup.add(s.breachArbitrator.Stop)
19941995
if err := s.breachArbitrator.Start(); err != nil {
19951996
startErr = err
19961997
return
19971998
}
1998-
cleanup = cleanup.add(s.breachArbitrator.Stop)
19991999

2000+
cleanup = cleanup.add(s.fundingMgr.Stop)
20002001
if err := s.fundingMgr.Start(); err != nil {
20012002
startErr = err
20022003
return
20032004
}
2004-
cleanup = cleanup.add(s.fundingMgr.Stop)
20052005

20062006
// htlcSwitch must be started before chainArb since the latter
20072007
// relies on htlcSwitch to deliver resolution message upon
20082008
// start.
2009+
cleanup = cleanup.add(s.htlcSwitch.Stop)
20092010
if err := s.htlcSwitch.Start(); err != nil {
20102011
startErr = err
20112012
return
20122013
}
2013-
cleanup = cleanup.add(s.htlcSwitch.Stop)
20142014

2015+
cleanup = cleanup.add(s.interceptableSwitch.Stop)
20152016
if err := s.interceptableSwitch.Start(); err != nil {
20162017
startErr = err
20172018
return
20182019
}
2019-
cleanup = cleanup.add(s.interceptableSwitch.Stop)
20202020

2021+
cleanup = cleanup.add(s.chainArb.Stop)
20212022
if err := s.chainArb.Start(); err != nil {
20222023
startErr = err
20232024
return
20242025
}
2025-
cleanup = cleanup.add(s.chainArb.Stop)
20262026

2027+
cleanup = cleanup.add(s.authGossiper.Stop)
20272028
if err := s.authGossiper.Start(); err != nil {
20282029
startErr = err
20292030
return
20302031
}
2031-
cleanup = cleanup.add(s.authGossiper.Stop)
20322032

2033+
cleanup = cleanup.add(s.graphBuilder.Stop)
20332034
if err := s.graphBuilder.Start(); err != nil {
20342035
startErr = err
20352036
return
20362037
}
2037-
cleanup = cleanup.add(s.graphBuilder.Stop)
20382038

2039+
cleanup = cleanup.add(s.chanRouter.Stop)
20392040
if err := s.chanRouter.Start(); err != nil {
20402041
startErr = err
20412042
return
20422043
}
2043-
cleanup = cleanup.add(s.chanRouter.Stop)
20442044

2045+
cleanup = cleanup.add(s.invoices.Stop)
20452046
if err := s.invoices.Start(); err != nil {
20462047
startErr = err
20472048
return
20482049
}
2049-
cleanup = cleanup.add(s.invoices.Stop)
20502050

2051+
cleanup = cleanup.add(s.sphinx.Stop)
20512052
if err := s.sphinx.Start(); err != nil {
20522053
startErr = err
20532054
return
20542055
}
2055-
cleanup = cleanup.add(s.sphinx.Stop)
20562056

2057+
cleanup = cleanup.add(s.chanStatusMgr.Stop)
20572058
if err := s.chanStatusMgr.Start(); err != nil {
20582059
startErr = err
20592060
return
20602061
}
2061-
cleanup = cleanup.add(s.chanStatusMgr.Stop)
20622062

2063+
cleanup = cleanup.add(s.chanEventStore.Stop)
20632064
if err := s.chanEventStore.Start(); err != nil {
20642065
startErr = err
20652066
return
20662067
}
2067-
cleanup = cleanup.add(func() error {
2068-
s.chanEventStore.Stop()
2069-
return nil
2070-
})
20712068

2072-
s.missionControl.RunStoreTicker()
20732069
cleanup.add(func() error {
20742070
s.missionControl.StopStoreTicker()
20752071
return nil
20762072
})
2073+
s.missionControl.RunStoreTicker()
20772074

20782075
// Before we start the connMgr, we'll check to see if we have
20792076
// any backups to recover. We do this now as we want to ensure
@@ -2107,18 +2104,18 @@ func (s *server) Start() error {
21072104
}
21082105
}
21092106

2107+
cleanup = cleanup.add(s.chanSubSwapper.Stop)
21102108
if err := s.chanSubSwapper.Start(); err != nil {
21112109
startErr = err
21122110
return
21132111
}
2114-
cleanup = cleanup.add(s.chanSubSwapper.Stop)
21152112

21162113
if s.torController != nil {
2114+
cleanup = cleanup.add(s.torController.Stop)
21172115
if err := s.createNewHiddenService(); err != nil {
21182116
startErr = err
21192117
return
21202118
}
2121-
cleanup = cleanup.add(s.torController.Stop)
21222119
}
21232120

21242121
if s.natTraversal != nil {
@@ -2127,11 +2124,11 @@ func (s *server) Start() error {
21272124
}
21282125

21292126
// Start connmgr last to prevent connections before init.
2130-
s.connMgr.Start()
21312127
cleanup = cleanup.add(func() error {
21322128
s.connMgr.Stop()
21332129
return nil
21342130
})
2131+
s.connMgr.Start()
21352132

21362133
// If peers are specified as a config option, we'll add those
21372134
// peers first.
@@ -2318,9 +2315,9 @@ func (s *server) Stop() error {
23182315
if err := s.sweeper.Stop(); err != nil {
23192316
srvrLog.Warnf("failed to stop sweeper: %v", err)
23202317
}
2321-
2322-
s.txPublisher.Stop()
2323-
2318+
if err := s.txPublisher.Stop(); err != nil {
2319+
srvrLog.Warnf("failed to stop txPublisher: %v", err)
2320+
}
23242321
if err := s.channelNotifier.Stop(); err != nil {
23252322
srvrLog.Warnf("failed to stop channelNotifier: %v", err)
23262323
}
@@ -2340,7 +2337,10 @@ func (s *server) Stop() error {
23402337
srvrLog.Warnf("Unable to stop BestBlockTracker: %v",
23412338
err)
23422339
}
2343-
s.chanEventStore.Stop()
2340+
if err := s.chanEventStore.Stop(); err != nil {
2341+
srvrLog.Warnf("Unable to stop ChannelEventStore: %v",
2342+
err)
2343+
}
23442344
s.missionControl.StopStoreTicker()
23452345

23462346
// Disconnect from each active peers to ensure that

sweep/fee_bumper.go

-1
Original file line numberDiff line numberDiff line change
@@ -701,7 +701,6 @@ func (t *TxPublisher) Stop() error {
701701
log.Debug("TxPublisher stopped")
702702

703703
return nil
704-
705704
}
706705

707706
// monitor is the main loop driven by new blocks. Whevenr a new block arrives,

0 commit comments

Comments
 (0)