From 733b3588d630f88a4d5742e7010f0cca07d577a8 Mon Sep 17 00:00:00 2001 From: Dave Collins Date: Sat, 30 Mar 2019 17:58:29 -0500 Subject: [PATCH] main: Rework windows service sod notification. The way that shutdown is handled was modified long ago, but it appears that the windows service code was not updated fully for the changes. In particular, the server instance is no longer used by the service at all. Rather the only information needed is the parsed configuration in order to log the start of day details. Consequently, this reworks the windows service start of day code to read a buffered channel that receives the parsed configuration instead of the server and modifies the dcrdMain function to no longer require the channel to be specified in order to simplify it for eventual context handling. --- dcrd.go | 21 ++++++++++++--------- service_windows.go | 14 +++++--------- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/dcrd.go b/dcrd.go index c25e2686..cf74b938 100644 --- a/dcrd.go +++ b/dcrd.go @@ -25,12 +25,15 @@ var cfg *config // as a service and reacts accordingly. var winServiceMain func() (bool, error) +// serviceStartOfDayChan is only used by Windows when the code is running as a +// service. It signals the service code that startup has completed. Notice +// that it uses a buffered channel so the caller will not be blocked when the +// service is not running. +var serviceStartOfDayChan = make(chan *config, 1) + // dcrdMain is the real main function for dcrd. It is necessary to work around -// the fact that deferred functions do not run when os.Exit() is called. The -// optional serverChan parameter is mainly used by the service code to be -// notified with the server once it is setup so it can gracefully stop it when -// requested from the service control manager. -func dcrdMain(serverChan chan<- *server) error { +// the fact that deferred functions do not run when os.Exit() is called. +func dcrdMain() error { // Load configuration and parse command line. This function also // initializes logging and configures it accordingly. tcfg, _, err := loadConfig() @@ -191,9 +194,6 @@ func dcrdMain(serverChan chan<- *server) error { }() server.Start() - if serverChan != nil { - serverChan <- server - } if interruptRequested(interrupt) { return nil @@ -201,6 +201,9 @@ func dcrdMain(serverChan chan<- *server) error { lifetimeNotifier.notifyStartupComplete() + // Signal the Windows service (if running) that startup has completed. + serviceStartOfDayChan <- cfg + // Wait until the interrupt signal is received from an OS signal or // shutdown is requested through one of the subsystems such as the RPC // server. @@ -239,7 +242,7 @@ func main() { } // Work around defer not working after os.Exit() - if err := dcrdMain(nil); err != nil { + if err := dcrdMain(); err != nil { os.Exit(1) } } diff --git a/service_windows.go b/service_windows.go index 801baa0c..7623534e 100644 --- a/service_windows.go +++ b/service_windows.go @@ -36,7 +36,7 @@ var elog *eventlog.Log // logServiceStartOfDay logs information about dcrd when the main server has // been started to the Windows event log. -func logServiceStartOfDay(srvr *server) { +func logServiceStartOfDay(cfg *config) { var message string message += fmt.Sprintf("Version %s\n", version.String()) message += fmt.Sprintf("Configuration directory: %s\n", cfg.HomeDir) @@ -61,19 +61,16 @@ func (s *dcrdService) Execute(args []string, r <-chan svc.ChangeRequest, changes // Start dcrdMain in a separate goroutine so the service can start // quickly. Shutdown (along with a potential error) is reported via - // doneChan. serverChan is notified with the main server instance once - // it is started so it can be gracefully stopped. + // doneChan. doneChan := make(chan error) - serverChan := make(chan *server) go func() { - err := dcrdMain(serverChan) + err := dcrdMain() doneChan <- err }() // Service is now started. changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} - var mainServer *server loop: for { select { @@ -95,9 +92,8 @@ loop: "request #%d.", c)) } - case srvr := <-serverChan: - mainServer = srvr - logServiceStartOfDay(mainServer) + case cfg := <-serviceStartOfDayChan: + logServiceStartOfDay(cfg) case err := <-doneChan: if err != nil {