Correct and improve SIGINT (Ctrl+C) handling.
Since the main SIGINT handler is running as a goroutine, the main goroutine must be kept active long enough for it to finish or it will be nuked when the main goroutine exits. This commit makes that happen by slightly modifying how it waits for shutdown. Rather than having the main goroutine only wait for the server to shutdown, there is now a shutdown channel that is used to signal the main goroutine to shutdown for all cases such as a graceful shutdown, a scheduled shutdown, an RPC stop, or a SIGINT. While here, also add a few prints to indicate a SIGINT was received and the shutdown progress.
This commit is contained in:
parent
36bd4b8994
commit
1aa65e6863
2 changed files with 22 additions and 3 deletions
20
btcd.go
20
btcd.go
|
@ -13,7 +13,8 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
cfg *config
|
||||
cfg *config
|
||||
shutdownChannel = make(chan bool)
|
||||
)
|
||||
|
||||
// btcdMain is the real main function for btcd. It is necessary to work around
|
||||
|
@ -71,6 +72,7 @@ func btcdMain() error {
|
|||
|
||||
// Ensure the database is sync'd and closed on Ctrl+C.
|
||||
addInterruptHandler(func() {
|
||||
log.Infof("Gracefully shutting down the database...")
|
||||
db.RollbackClose()
|
||||
})
|
||||
|
||||
|
@ -83,7 +85,21 @@ func btcdMain() error {
|
|||
}
|
||||
server.Start()
|
||||
|
||||
server.WaitForShutdown()
|
||||
// Monitor for graceful server shutdown and signal the main goroutine
|
||||
// when done. This is done in a separate goroutine rather than waiting
|
||||
// directly so the main goroutine can be signaled for shutdown by either
|
||||
// a graceful shutdown or from the main interrupt handler. This is
|
||||
// necessary since the main goroutine must be kept running long enough
|
||||
// for the interrupt handler goroutine to finish.
|
||||
go func() {
|
||||
server.WaitForShutdown()
|
||||
shutdownChannel <- true
|
||||
}()
|
||||
|
||||
// Wait for shutdown signal from either a graceful server stop or from
|
||||
// the interrupt handler.
|
||||
<-shutdownChannel
|
||||
log.Info("Shutdown complete")
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
@ -27,10 +27,13 @@ func mainInterruptHandler() {
|
|||
for {
|
||||
select {
|
||||
case <-interruptChannel:
|
||||
log.Infof("Received SIGINT (Ctrl+C). Shutting down...")
|
||||
for _, callback := range interruptCallbacks {
|
||||
callback()
|
||||
}
|
||||
os.Exit(0)
|
||||
|
||||
// Signal the main goroutine to shutdown.
|
||||
shutdownChannel <- true
|
||||
|
||||
case handler := <-addHandlerChannel:
|
||||
interruptCallbacks = append(interruptCallbacks, handler)
|
||||
|
|
Loading…
Add table
Reference in a new issue