Update shutdown signalling. (#293)

Bring in some updates from the signal handling code in other projects:

- Rename `signals` to more descriptive `interruptSignals`.
- Add SIGHUP to unix shutdown signals. Rename `signalsigterm.go` to `signal_unix.go` accordingly.
- Include extra detail in "Already shutting down..." messages log lines.
- Pass a shutdown func into `webapi.go` rather than a channel. It's more obvious how to invoke a func, whereas a channel can be used in multiple ways.
This commit is contained in:
Jamie Holdstock 2021-08-26 15:28:51 +01:00 committed by GitHub
parent 9ef8834187
commit b97609cd2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 20 additions and 13 deletions

View File

@ -1,4 +1,5 @@
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -19,9 +20,9 @@ var shutdownRequestChannel = make(chan struct{})
// withShutdownChannel are cancelled when this is closed.
var shutdownSignaled = make(chan struct{})
// signals defines the signals that are handled to do a clean shutdown.
// Conditional compilation is used to also include SIGTERM on Unix.
var signals = []os.Signal{os.Interrupt}
// interruptSignals defines the signals that are handled to do a clean shutdown.
// Conditional compilation is used to also include SIGTERM and SIGHUP on Unix.
var interruptSignals = []os.Signal{os.Interrupt}
// withShutdownCancel creates a copy of a context that is cancelled whenever
// shutdown is invoked through an interrupt signal or from an JSON-RPC stop
@ -36,7 +37,7 @@ func withShutdownCancel(ctx context.Context) context.Context {
}
// requestShutdown signals for starting the clean shutdown of the process
// through an internal component (such as through the JSON-RPC stop request).
// through an internal component.
func requestShutdown() {
shutdownRequestChannel <- struct{}{}
}
@ -46,14 +47,14 @@ func requestShutdown() {
// to be spawned in a new goroutine.
func shutdownListener() {
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, signals...)
signal.Notify(interruptChannel, interruptSignals...)
// Listen for the initial shutdown signal
select {
case sig := <-interruptChannel:
log.Infof("Received signal (%s). Shutting down...", sig)
log.Infof("Received signal (%s). Shutting down...", sig)
case <-shutdownRequestChannel:
log.Info("Shutdown requested. Shutting down...")
log.Info("Shutdown requested. Shutting down...")
}
// Cancel all contexts created from withShutdownCancel.
@ -63,9 +64,10 @@ func shutdownListener() {
// been signaled.
for {
select {
case <-interruptChannel:
case sig := <-interruptChannel:
log.Infof("Received signal (%s). Already shutting down...", sig)
case <-shutdownRequestChannel:
log.Info("Shutdown requested. Already shutting down...")
}
log.Info("Shutdown signaled. Already shutting down...")
}
}

View File

@ -1,4 +1,5 @@
// Copyright (c) 2016 The btcsuite developers
// Copyright (c) 2021 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
@ -12,5 +13,9 @@ import (
)
func init() {
signals = []os.Signal{os.Interrupt, syscall.SIGTERM}
interruptSignals = []os.Signal{
os.Interrupt,
syscall.SIGTERM,
syscall.SIGHUP,
}
}

View File

@ -104,7 +104,7 @@ func run(ctx context.Context) error {
MaxVoteChangeRecords: maxVoteChangeRecords,
VspdVersion: version.String(),
}
err = webapi.Start(ctx, shutdownRequestChannel, &shutdownWg, cfg.Listen, db,
err = webapi.Start(ctx, requestShutdown, &shutdownWg, cfg.Listen, db,
dcrd, wallets, apiCfg)
if err != nil {
log.Errorf("Failed to initialize webapi: %v", err)

View File

@ -55,7 +55,7 @@ var addrGen *addressGenerator
var signPrivKey ed25519.PrivateKey
var signPubKey ed25519.PublicKey
func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *sync.WaitGroup,
func Start(ctx context.Context, requestShutdown func(), shutdownWg *sync.WaitGroup,
listen string, vdb *database.VspDatabase, dcrd rpc.DcrdConnect, wallets rpc.WalletConnect, config Config) error {
cfg = config
@ -137,7 +137,7 @@ func Start(ctx context.Context, requestShutdownChan chan struct{}, shutdownWg *s
// shutdown.
if err != nil && !errors.Is(err, http.ErrServerClosed) {
log.Errorf("Unexpected webserver error: %v", err)
requestShutdownChan <- struct{}{}
requestShutdown()
}
}()