Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

windows self call Restart will not Start #163

Open
tommady opened this issue Feb 4, 2019 · 5 comments
Open

windows self call Restart will not Start #163

tommady opened this issue Feb 4, 2019 · 5 comments

Comments

@tommady
Copy link

tommady commented Feb 4, 2019

sorry I am facing a problem on doing the Restart in windows service,
I want to do the self-updating things.

said I have a goroutine

        go func() {
		<-p.updater.updateSignal
		s.Restart()
	}()

when the channel has been triggered, then going down to s.Restart()
everything good, the service got Stop,
but the service just stopped forever,
no Start again.

the document said

// Restart signals to the OS service manager the given service should stop then start.

so is there something I miss-understanding?

please guide me, thank!

@haroldHT
Copy link

haroldHT commented Feb 9, 2019

Can u provide more detail?
How did u restart?
Or ur code.

@yi-ge
Copy link

yi-ge commented Aug 31, 2019

I have the same problem.

Program example in windows:

func (ws *windowsService) Restart() error {
	m, err := mgr.Connect()
	if err != nil {
		return err
	}
	defer m.Disconnect()

	s, err := m.OpenService(ws.Name)
	if err != nil {
		return err
	}
	defer s.Close()

	err = ws.stopWait(s)
	if err != nil {
		return err
	}

	return s.Start()
}

You can't restart by itself.

Feasible example:

var restartCmd *exec.Cmd
restartCmd = exec.Command(YOUR PATH, "restart")
restartCmd.Start()

@joshforbes
Copy link

joshforbes commented Jul 1, 2020

I have the same problem. If I attempt to Stop the service and then sleep for a long period before calling Start (essentially what "Restart" is doing) I get:

image

From what I can tell you are unable to restart a windows service from within the service. My only thought now is that I could crash the process and allow the windows service manager to recover it.

@tommady and @yi-ge how did you end up solving this?

@JefMasereel
Copy link

Same issue here. One "quick and dirty" solution could be to run a secondary service (s1) that restarts the primary service (s2) when s1 goes down, or when s1 sends a specific command to s2. This works well, but it implies a bit more overhead when managing many instances across a fleet of machines. And when s2 requires an automatic restart it gets more complicated again...

On Unix it seems easier to build a "live reloading" mechanism that restarts the process without downtime, so another solution could be to run the program on a Unix container or VM. Containerization can be interesting for fleet management, but you have to be careful not to accumulate too much overhead again.

For a Windows compatible solution you will probably have to implement your own live reload mechanism as part of the service definition. Try using standard library "os" to identify the active process(es) (getPid, FindProcess) and start/stop them. Make sure to keep Windows quirks in mind, e.g. only using os.Interrupt or os.Kill signals with the "signal" pkg.

Or you could implement the service management from scratch... Should be possible with the windows service utilities from the "sys" package (https://pkg.go.dev/golang.org/x/[email protected]/windows/svc)

Some reference links for "hot reload" solutions in Go:

@joshforbes
Copy link

We considered implementing a second watchdog service to keep an eye on the primary service but I was worried about the extra complexity. Our current solution is two-fold:

  1. We ensure the service always exits with an exit code so that the Windows service manager restart options will take effect. Specifically, we use exit code "1467" ("The application must be restarted" - https://learn.microsoft.com/en-us/windows/win32/debug/system-error-codes--1300-1699-)
  2. The service adds a scheduled "watchdog task". This uses Window's task scheduler and runs every X minutes to see if the service is running. If the service is running, it does nothing. If the service is not running, it starts it.

Typically the service manager will keep the service running without any extra assistance but this scheduled task provides extra piece of mind. This feels a bit hacky so we may eventually go with a secondary service to be more robust but this has worked for us so far.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants