Skip to content
This repository has been archived by the owner on Aug 7, 2023. It is now read-only.

Commit

Permalink
dcrd: Simplify shutdown signal handling logic sync.
Browse files Browse the repository at this point in the history
Upstream commit 044a11c.
  • Loading branch information
davecgh committed Nov 18, 2016
2 parents 60c812e + 044a11c commit 9d4ac11
Show file tree
Hide file tree
Showing 3 changed files with 43 additions and 27 deletions.
26 changes: 14 additions & 12 deletions dcrd.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,14 @@ func dcrdMain(serverChan chan<- *server) error {
cfg = tcfg
defer backendLog.Flush()

interrupted := interruptListener()
// Get a channel that will be closed when a shutdown signal has been
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
// another subsystem such as the RPC server.
interruptedChan := interruptListener()
defer dcrdLog.Info("Shutdown complete")

// Show version at startup.
// Show version and home dir at startup.
dcrdLog.Infof("Version %s", version())
// Show dcrd home dir location
dcrdLog.Infof("Home dir: %s", cfg.HomeDir)

// Enable http profiling server if requested.
Expand Down Expand Up @@ -106,11 +108,8 @@ func dcrdMain(serverChan chan<- *server) error {
go drainOutgoingPipeMessages()
}

if interruptRequested(interrupted) {
return nil
}

if interruptRequested(interrupted) {
// Return now if an interrupt signal was triggered.
if interruptRequested(interruptedChan) {
return nil
}

Expand All @@ -122,12 +121,14 @@ func dcrdMain(serverChan chan<- *server) error {
return err
}
defer func() {
// Ensure the database is sync'd and closed on shutdown.
lifetimeNotifier.notifyShutdownEvent(lifetimeEventDBOpen)
dcrdLog.Infof("Gracefully shutting down the database...")
db.Close()
}()

if interruptRequested(interrupted) {
// Return now if an interrupt signal was triggered.
if interruptRequested(interruptedChan) {
return nil
}

Expand Down Expand Up @@ -182,15 +183,16 @@ func dcrdMain(serverChan chan<- *server) error {
serverChan <- server
}

if interruptRequested(interrupted) {
if interruptRequested(interruptedChan) {
return nil
}

lifetimeNotifier.notifyStartupComplete()

// Wait until the interrupt signal is received from an OS signal or
// shutdown is requested through the RPC server.
<-interrupted
// shutdown is requested through one of the subsystems such as the RPC
// server.
<-interruptedChan
return nil
}

Expand Down
10 changes: 3 additions & 7 deletions service_windows.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
Expand Down Expand Up @@ -86,12 +86,8 @@ loop:
// more commands while pending.
changes <- svc.Status{State: svc.StopPending}

// Signal the main function to exit if shutdown
// was not already requested.
select {
case shutdownRequestChannel <- struct{}{}:
default:
}
// Signal the main function to exit.
shutdownRequestChannel <- struct{}{}

default:
elog.Error(1, fmt.Sprintf("Unexpected control "+
Expand Down
34 changes: 26 additions & 8 deletions signal.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2013-2014 The btcsuite developers
// Copyright (c) 2013-2016 The btcsuite developers
// Copyright (c) 2015-2016 The Decred developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
Expand All @@ -18,24 +18,41 @@ var shutdownRequestChannel = make(chan struct{})
// shutdown. This may be modified during init depending on the platform.
var interruptSignals = []os.Signal{os.Interrupt}

// interruptListener listens for SIGINT (Ctrl+C) signals and shutdown requests
// from shutdownRequestChannel. It returns a channel that is closed when either
// signal is received.
// interruptListener listens for OS Signals such as SIGINT (Ctrl+C) and shutdown
// requests from shutdownRequestChannel. It returns a channel that is closed
// when either signal is received.
func interruptListener() <-chan struct{} {
c := make(chan struct{})

go func() {
interruptChannel := make(chan os.Signal, 1)
signal.Notify(interruptChannel, interruptSignals...)

// Listen for initial shutdown signal and close the returned
// channel to notify the caller.
select {
case sig := <-interruptChannel:
dcrdLog.Infof("Received signal (%s). Shutting down...", sig)
dcrdLog.Infof("Received signal (%s). Shutting down...",
sig)

case <-shutdownRequestChannel:
dcrdLog.Infof("Shutdown requested. Shutting down...")
}

close(c)

// Listen for repeated signals and display a message so the user
// knows the shutdown is in progress and the process is not
// hung.
for {
select {
case sig := <-interruptChannel:
dcrdLog.Infof("Received signal (%s). Already "+
"shutting down...", sig)

case <-shutdownRequestChannel:
dcrdLog.Info("Shutdown requested. Already " +
"shutting down...")
}
}
}()

return c
Expand All @@ -49,6 +66,7 @@ func interruptRequested(interrupted <-chan struct{}) bool {
case <-interrupted:
return true
default:
return false
}

return false
}

0 comments on commit 9d4ac11

Please sign in to comment.