cmd/cli: handle stop signal from service manager

So using "ctrld stop" or service manager to stop ctrld will end up with
the same result, stopped ctrld with a working DNS, and deactivation pin
code will always have effects if set.
This commit is contained in:
Cuong Manh Le
2025-03-20 22:26:35 +07:00
committed by Cuong Manh Le
parent dacc67e50f
commit c6365e6b74
7 changed files with 60 additions and 42 deletions
+30 -9
View File
@@ -87,6 +87,7 @@ type prog struct {
mu sync.Mutex
waitCh chan struct{}
stopCh chan struct{}
pinCodeValidCh chan struct{}
reloadCh chan struct{} // For Windows.
reloadDoneCh chan struct{}
apiReloadCh chan *ctrld.Config
@@ -268,13 +269,6 @@ func (p *prog) preRun() {
p.requiredMultiNICsConfig = requiredMultiNICsConfig()
}
p.runningIface = iface
if runtime.GOOS == "darwin" {
p.onStopped = append(p.onStopped, func() {
if !service.Interactive() {
p.resetDNS(false, true)
}
})
}
}
func (p *prog) postRun() {
@@ -622,14 +616,41 @@ func (p *prog) metricsEnabled() bool {
func (p *prog) Stop(s service.Service) error {
p.stopDnsWatchers()
mainLog.Load().Debug().Msg("dns watchers stopped")
for _, f := range p.onStopped {
f()
}
mainLog.Load().Debug().Msg("finish running onStopped functions")
defer func() {
mainLog.Load().Info().Msg("Service stopped")
}()
close(p.stopCh)
if err := p.deAllocateIP(); err != nil {
mainLog.Load().Error().Err(err).Msg("de-allocate ip failed")
return err
}
if deactivationPinSet() {
select {
case <-p.pinCodeValidCh:
// Allow stopping the service, pinCodeValidCh is only filled
// after control server did validate the pin code.
case <-time.After(time.Millisecond * 100):
// No valid pin code was checked, that mean we are stopping
// because of OS signal sent directly from someone else.
// In this case, restarting ctrld service by ourselves.
mainLog.Load().Debug().Msgf("receiving stopping signal without valid pin code")
mainLog.Load().Debug().Msgf("self restarting ctrld service")
if exe, err := os.Executable(); err == nil {
cmd := exec.Command(exe, "restart")
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
if err := cmd.Start(); err != nil {
mainLog.Load().Error().Err(err).Msg("failed to run self restart command")
}
} else {
mainLog.Load().Error().Err(err).Msg("failed to self restart ctrld service")
}
os.Exit(deactivationPinInvalidExitCode)
}
}
close(p.stopCh)
return nil
}
@@ -1471,7 +1492,7 @@ func selfUpgradeCheck(vt string, cv *semver.Version, logger *zerolog.Logger) {
return
}
cmd := exec.Command(exe, "upgrade", "prod", "-vv")
cmd.SysProcAttr = sysProcAttrForSelfUpgrade()
cmd.SysProcAttr = sysProcAttrForDetachedChildProcess()
if err := cmd.Start(); err != nil {
mainLog.Load().Error().Err(err).Msg("failed to start self-upgrade")
return