Skip to content

Commit

Permalink
Add wait logic directly in the janitor.
Browse files Browse the repository at this point in the history
The janitor already maintains the channel used for service termination
notifications. Exposing a wait() function simplifies the waiting without
having to let the caller worry about handling channels correctly.
  • Loading branch information
Tuxdude committed Feb 18, 2022
1 parent 18b7e31 commit 61e5e64
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 20 deletions.
23 changes: 14 additions & 9 deletions janitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ type serviceJanitor struct {
// True if shutting down, false otherwise.
shuttingDown bool
// Service termination notification channel.
termNotificationCh chan<- *terminatedService
termNotificationCh chan *terminatedService
}

// janitorRepo is the repository interface used by the janitor to remove
Expand All @@ -36,15 +36,13 @@ type terminatedService struct {
}

// newServiceJanitor instantiates a new janitor.
func newServiceJanitor(log zzzlogi.Logger, repo janitorRepo, multiServiceMode bool) (*serviceJanitor, <-chan *terminatedService) {
sj := &serviceJanitor{
log: log,
repo: repo,
multiServiceMode: multiServiceMode,
func newServiceJanitor(log zzzlogi.Logger, repo janitorRepo, multiServiceMode bool) *serviceJanitor {
return &serviceJanitor{
log: log,
repo: repo,
multiServiceMode: multiServiceMode,
termNotificationCh: make(chan *terminatedService, 1),
}
ch := make(chan *terminatedService, 1)
sj.termNotificationCh = ch
return sj, ch
}

// handleProcTermination handles the termination of the specified processes.
Expand All @@ -61,6 +59,13 @@ func (s *serviceJanitor) handleProcTermination(procs []*reapedProcInfo) {
}
}

// wait waits till the first service terminates and returns the terminated
// service information along with its exit status.
func (s *serviceJanitor) wait() (*launchedService, int) {
t := <-s.termNotificationCh
return t.service, t.exitStatus
}

// handleServiceTermination handles the termination of the specified service.
func (s *serviceJanitor) handleServiceTermination(serv *launchedService, exitStatus int) {
s.log.Infof("Service: %v exited, exit status: %d", serv, exitStatus)
Expand Down
15 changes: 4 additions & 11 deletions service_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,6 @@ import (
type serviceManagerImpl struct {
// Logger used by the service manager.
log zzzlogi.Logger

// The channel used to receive notification about the first service
// that gets terminated.
serviceTermNotificationCh <-chan *terminatedService

// Service repository.
repo *serviceRepo
// Service janitor.
Expand All @@ -39,7 +34,7 @@ func NewServiceManager(log zzzlogi.Logger, services ...*ServiceInfo) (InitServic
log: log,
}
sm.repo = newServiceRepo(log)
sm.janitor, sm.serviceTermNotificationCh = newServiceJanitor(log, sm.repo, multiServiceMode)
sm.janitor = newServiceJanitor(log, sm.repo, multiServiceMode)
sm.signals = newSignalManager(log, sm.repo, newZombieReaper(log), sm.janitor)

err := launchServices(log, sm.repo, services...)
Expand All @@ -60,13 +55,11 @@ func NewServiceManager(log zzzlogi.Logger, services ...*ServiceInfo) (InitServic
// service which exited. In multi service mode, the exit status is the
// same as the first service which exited if non-zero, 77 otherwise.
func (s *serviceManagerImpl) Wait() int {
// Wait for the first service termination.
t := <-s.serviceTermNotificationCh

s.log.Infof("Shutting down since service: %v terminated", t.service)
serv, exitStatus := s.janitor.wait()
s.log.Infof("Shutting down since service: %v terminated", serv)

s.shutDown()
return t.exitStatus
return exitStatus
}

// shutDown terminates any running services launched by InitServiceManager,
Expand Down

0 comments on commit 61e5e64

Please sign in to comment.