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 {