mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-08-29 07:00:55 +02:00
chanbackup: fix shutdown issue when backuper has not started yet
This commit is contained in:
committed by
Olaoluwa Osuntokun
parent
2d985c89d6
commit
370d254ba2
@@ -6,6 +6,7 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
@@ -93,7 +94,12 @@ type ChannelNotifier interface {
|
|||||||
// be used to implement a system that always keeps the multi-chan backup file
|
// be used to implement a system that always keeps the multi-chan backup file
|
||||||
// on disk in a consistent state for safety purposes.
|
// on disk in a consistent state for safety purposes.
|
||||||
type SubSwapper struct {
|
type SubSwapper struct {
|
||||||
|
// started tracks whether the SubSwapper has been started and ensures
|
||||||
|
// it can only be started once.
|
||||||
started sync.Once
|
started sync.Once
|
||||||
|
|
||||||
|
// stopped tracks whether the SubSwapper has been stopped and ensures
|
||||||
|
// it can only be stopped once.
|
||||||
stopped sync.Once
|
stopped sync.Once
|
||||||
|
|
||||||
// backupState are the set of SCBs for all open channels we know of.
|
// backupState are the set of SCBs for all open channels we know of.
|
||||||
@@ -113,6 +119,11 @@ type SubSwapper struct {
|
|||||||
|
|
||||||
quit chan struct{}
|
quit chan struct{}
|
||||||
wg sync.WaitGroup
|
wg sync.WaitGroup
|
||||||
|
|
||||||
|
// isActive tracks whether the SubSwapper is active and ready to receive
|
||||||
|
// messages. It is used to prevent manual updates from being sent to the
|
||||||
|
// SubSwapper after it has been stopped or not yet started.
|
||||||
|
isActive atomic.Bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSubSwapper creates a new instance of the SubSwapper given the starting
|
// NewSubSwapper creates a new instance of the SubSwapper given the starting
|
||||||
@@ -162,6 +173,7 @@ func (s *SubSwapper) Start() error {
|
|||||||
if err := s.updateBackupFile(); err != nil {
|
if err := s.updateBackupFile(); err != nil {
|
||||||
startErr = fmt.Errorf("unable to refresh backup "+
|
startErr = fmt.Errorf("unable to refresh backup "+
|
||||||
"file: %v", err)
|
"file: %v", err)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -178,9 +190,13 @@ func (s *SubSwapper) Stop() error {
|
|||||||
log.Infof("chanbackup.SubSwapper shutting down...")
|
log.Infof("chanbackup.SubSwapper shutting down...")
|
||||||
defer log.Debug("chanbackup.SubSwapper shutdown complete")
|
defer log.Debug("chanbackup.SubSwapper shutdown complete")
|
||||||
|
|
||||||
|
// Mark the SubSwapper as not running.
|
||||||
|
s.isActive.Store(false)
|
||||||
|
|
||||||
close(s.quit)
|
close(s.quit)
|
||||||
s.wg.Wait()
|
s.wg.Wait()
|
||||||
})
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,6 +204,11 @@ func (s *SubSwapper) Stop() error {
|
|||||||
// are processed in another goroutine. The method waits for the updates to be
|
// are processed in another goroutine. The method waits for the updates to be
|
||||||
// fully processed and the file to be updated on-disk before returning.
|
// fully processed and the file to be updated on-disk before returning.
|
||||||
func (s *SubSwapper) ManualUpdate(singles []Single) error {
|
func (s *SubSwapper) ManualUpdate(singles []Single) error {
|
||||||
|
if !s.isActive.Load() {
|
||||||
|
return fmt.Errorf("swapper is not active, cannot perform " +
|
||||||
|
"manual update")
|
||||||
|
}
|
||||||
|
|
||||||
// Create the channel to send an error back. If the update handling
|
// Create the channel to send an error back. If the update handling
|
||||||
// and the subsequent file updating succeeds, nil is sent.
|
// and the subsequent file updating succeeds, nil is sent.
|
||||||
// The channel must have capacity of 1 to prevent Swapper blocking.
|
// The channel must have capacity of 1 to prevent Swapper blocking.
|
||||||
@@ -297,7 +318,8 @@ func (s *SubSwapper) updateBackupFile(closedChans ...wire.OutPoint) error {
|
|||||||
// backupFileUpdater is the primary goroutine of the SubSwapper which is
|
// backupFileUpdater is the primary goroutine of the SubSwapper which is
|
||||||
// responsible for listening for changes to the channel, and updating the
|
// responsible for listening for changes to the channel, and updating the
|
||||||
// persistent multi backup state with a new packed multi of the latest channel
|
// persistent multi backup state with a new packed multi of the latest channel
|
||||||
// state.
|
// state. Once active, it will process subscription updates and manual updates
|
||||||
|
// until the SubSwapper is stopped.
|
||||||
func (s *SubSwapper) backupUpdater() {
|
func (s *SubSwapper) backupUpdater() {
|
||||||
// Ensure that once we exit, we'll cancel our active channel
|
// Ensure that once we exit, we'll cancel our active channel
|
||||||
// subscription.
|
// subscription.
|
||||||
@@ -306,6 +328,9 @@ func (s *SubSwapper) backupUpdater() {
|
|||||||
|
|
||||||
log.Debugf("SubSwapper's backupUpdater is active!")
|
log.Debugf("SubSwapper's backupUpdater is active!")
|
||||||
|
|
||||||
|
// Mark the SubSwapper as active.
|
||||||
|
s.isActive.Store(true)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
// The channel state has been modified! We'll evaluate all
|
// The channel state has been modified! We'll evaluate all
|
||||||
|
Reference in New Issue
Block a user