• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 12986279612

27 Jan 2025 09:51AM UTC coverage: 57.652% (-1.1%) from 58.788%
12986279612

Pull #9447

github

yyforyongyu
sweep: rename methods for clarity

We now rename "third party" to "unknown" as the inputs can be spent via
an older sweeping tx, a third party (anchor), or a remote party (pin).
In fee bumper we don't have the info to distinguish the above cases, and
leave them to be further handled by the sweeper as it has more context.
Pull Request #9447: sweep: start tracking input spending status in the fee bumper

83 of 87 new or added lines in 2 files covered. (95.4%)

19578 existing lines in 256 files now uncovered.

103448 of 179434 relevant lines covered (57.65%)

24884.58 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/signal/signal.go
1
// Copyright (c) 2013-2017 The btcsuite developers
2
// Copyright (c) 2015-2016 The Decred developers
3
// Heavily inspired by https://github.com/btcsuite/btcd/blob/master/signal.go
4
// Copyright (C) 2015-2022 The Lightning Network Developers
5

6
package signal
7

8
import (
9
        "errors"
10
        "fmt"
11
        "os"
12
        "os/signal"
13
        "sync/atomic"
14
        "syscall"
15

16
        "github.com/coreos/go-systemd/daemon"
17
)
18

19
var (
20
        // started indicates whether we have started our main interrupt handler.
21
        // This field should be used atomically.
22
        started int32
23
)
24

25
// systemdNotifyReady notifies systemd about LND being ready, logs the result of
26
// the operation or possible error. Besides logging, systemd being unavailable
27
// is ignored.
UNCOV
28
func systemdNotifyReady() error {
×
UNCOV
29
        notified, err := daemon.SdNotify(false, daemon.SdNotifyReady)
×
UNCOV
30
        if err != nil {
×
31
                err := fmt.Errorf("failed to notify systemd %v (if you aren't "+
×
32
                        "running systemd clear the environment variable "+
×
33
                        "NOTIFY_SOCKET)", err)
×
34
                log.Error(err)
×
35

×
36
                // The SdNotify doc says it's common to ignore the
×
37
                // error. We don't want to ignore it because if someone
×
38
                // set up systemd to wait for initialization other
×
39
                // processes would get stuck.
×
40
                return err
×
41
        }
×
UNCOV
42
        if notified {
×
43
                log.Info("Systemd was notified about our readiness")
×
UNCOV
44
        } else {
×
UNCOV
45
                log.Info("We're not running within systemd or the service " +
×
UNCOV
46
                        "type is not 'notify'")
×
UNCOV
47
        }
×
UNCOV
48
        return nil
×
49
}
50

51
// systemdNotifyStop notifies systemd that LND is stopping and logs error if
52
// the notification failed. It also logs if the notification was actually sent.
53
// Systemd being unavailable is intentionally ignored.
UNCOV
54
func systemdNotifyStop() {
×
UNCOV
55
        notified, err := daemon.SdNotify(false, daemon.SdNotifyStopping)
×
UNCOV
56

×
UNCOV
57
        // Just log - we're stopping anyway.
×
UNCOV
58
        if err != nil {
×
59
                log.Errorf("Failed to notify systemd: %v", err)
×
60
        }
×
UNCOV
61
        if notified {
×
62
                log.Infof("Systemd was notified about stopping")
×
63
        }
×
64
}
65

66
// Notifier handles notifications about status of LND.
67
type Notifier struct {
68
        // notifiedReady remembers whether Ready was sent to avoid sending it
69
        // multiple times.
70
        notifiedReady bool
71
}
72

73
// NotifyReady notifies other applications that RPC is ready.
UNCOV
74
func (notifier *Notifier) NotifyReady(walletUnlocked bool) error {
×
UNCOV
75
        if !notifier.notifiedReady {
×
UNCOV
76
                err := systemdNotifyReady()
×
UNCOV
77
                if err != nil {
×
78
                        return err
×
79
                }
×
UNCOV
80
                notifier.notifiedReady = true
×
81
        }
UNCOV
82
        if walletUnlocked {
×
UNCOV
83
                _, _ = daemon.SdNotify(false, "STATUS=Wallet unlocked")
×
UNCOV
84
        } else {
×
UNCOV
85
                _, _ = daemon.SdNotify(false, "STATUS=Wallet locked")
×
UNCOV
86
        }
×
87

UNCOV
88
        return nil
×
89
}
90

91
// notifyStop notifies other applications that LND is stopping.
UNCOV
92
func (notifier *Notifier) notifyStop() {
×
UNCOV
93
        systemdNotifyStop()
×
UNCOV
94
}
×
95

96
// Interceptor contains channels and methods regarding application shutdown
97
// and interrupt signals.
98
type Interceptor struct {
99
        // interruptChannel is used to receive SIGINT (Ctrl+C) signals.
100
        interruptChannel chan os.Signal
101

102
        // shutdownChannel is closed once the main interrupt handler exits.
103
        shutdownChannel chan struct{}
104

105
        // shutdownRequestChannel is used to request the daemon to shutdown
106
        // gracefully, similar to when receiving SIGINT.
107
        shutdownRequestChannel chan struct{}
108

109
        // quit is closed when instructing the main interrupt handler to exit.
110
        // Note that to avoid losing notifications, only shutdown func may
111
        // close this channel.
112
        quit chan struct{}
113

114
        // Notifier handles sending shutdown notifications.
115
        Notifier Notifier
116
}
117

118
// Intercept starts the interception of interrupt signals and returns an `Interceptor` instance.
119
// Note that any previous active interceptor must be stopped before a new one can be created.
UNCOV
120
func Intercept() (Interceptor, error) {
×
UNCOV
121
        if !atomic.CompareAndSwapInt32(&started, 0, 1) {
×
122
                return Interceptor{}, errors.New("intercept already started")
×
123
        }
×
124

UNCOV
125
        channels := Interceptor{
×
UNCOV
126
                interruptChannel:       make(chan os.Signal, 1),
×
UNCOV
127
                shutdownChannel:        make(chan struct{}),
×
UNCOV
128
                shutdownRequestChannel: make(chan struct{}),
×
UNCOV
129
                quit:                   make(chan struct{}),
×
UNCOV
130
        }
×
UNCOV
131

×
UNCOV
132
        signalsToCatch := []os.Signal{
×
UNCOV
133
                os.Interrupt,
×
UNCOV
134
                os.Kill,
×
UNCOV
135
                syscall.SIGTERM,
×
UNCOV
136
                syscall.SIGQUIT,
×
UNCOV
137
        }
×
UNCOV
138
        signal.Notify(channels.interruptChannel, signalsToCatch...)
×
UNCOV
139
        go channels.mainInterruptHandler()
×
UNCOV
140

×
UNCOV
141
        return channels, nil
×
142
}
143

144
// mainInterruptHandler listens for SIGINT (Ctrl+C) signals on the
145
// interruptChannel and shutdown requests on the shutdownRequestChannel, and
146
// invokes the registered interruptCallbacks accordingly. It also listens for
147
// callback registration.
148
// It must be run as a goroutine.
UNCOV
149
func (c *Interceptor) mainInterruptHandler() {
×
UNCOV
150
        defer atomic.StoreInt32(&started, 0)
×
UNCOV
151
        // isShutdown is a flag which is used to indicate whether or not
×
UNCOV
152
        // the shutdown signal has already been received and hence any future
×
UNCOV
153
        // attempts to add a new interrupt handler should invoke them
×
UNCOV
154
        // immediately.
×
UNCOV
155
        var isShutdown bool
×
UNCOV
156

×
UNCOV
157
        // shutdown invokes the registered interrupt handlers, then signals the
×
UNCOV
158
        // shutdownChannel.
×
UNCOV
159
        shutdown := func() {
×
UNCOV
160
                // Ignore more than one shutdown signal.
×
UNCOV
161
                if isShutdown {
×
162
                        log.Infof("Already shutting down...")
×
163
                        return
×
164
                }
×
UNCOV
165
                isShutdown = true
×
UNCOV
166
                log.Infof("Shutting down...")
×
UNCOV
167
                c.Notifier.notifyStop()
×
UNCOV
168

×
UNCOV
169
                // Signal the main interrupt handler to exit, and stop accept
×
UNCOV
170
                // post-facto requests.
×
UNCOV
171
                close(c.quit)
×
172
        }
173

UNCOV
174
        for {
×
UNCOV
175
                select {
×
176
                case signal := <-c.interruptChannel:
×
177
                        log.Infof("Received %v", signal)
×
178
                        shutdown()
×
179

UNCOV
180
                case <-c.shutdownRequestChannel:
×
UNCOV
181
                        log.Infof("Received shutdown request.")
×
UNCOV
182
                        shutdown()
×
183

UNCOV
184
                case <-c.quit:
×
UNCOV
185
                        log.Infof("Gracefully shutting down.")
×
UNCOV
186
                        close(c.shutdownChannel)
×
UNCOV
187
                        signal.Stop(c.interruptChannel)
×
UNCOV
188
                        return
×
189
                }
190
        }
191
}
192

193
// Listening returns true if the main interrupt handler has been started, and
194
// has not been killed.
195
func (c *Interceptor) Listening() bool {
×
196
        // If our started field is not set, we are not yet listening for
×
197
        // interrupts.
×
198
        if atomic.LoadInt32(&started) != 1 {
×
199
                return false
×
200
        }
×
201

202
        // If we have started our main goroutine, we check whether we have
203
        // stopped it yet.
204
        return c.Alive()
×
205
}
206

207
// Alive returns true if the main interrupt handler has not been killed.
208
func (c *Interceptor) Alive() bool {
×
209
        select {
×
210
        case <-c.quit:
×
211
                return false
×
212
        default:
×
213
                return true
×
214
        }
215
}
216

217
// RequestShutdown initiates a graceful shutdown from the application.
UNCOV
218
func (c *Interceptor) RequestShutdown() {
×
UNCOV
219
        select {
×
UNCOV
220
        case c.shutdownRequestChannel <- struct{}{}:
×
221
        case <-c.quit:
×
222
        }
223
}
224

225
// ShutdownChannel returns the channel that will be closed once the main
226
// interrupt handler has exited.
UNCOV
227
func (c *Interceptor) ShutdownChannel() <-chan struct{} {
×
UNCOV
228
        return c.shutdownChannel
×
UNCOV
229
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc