svc_windows.go 1.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. // Copyright 2015 Daniel Theophanes.
  2. // Use of this source code is governed by a zlib-style
  3. // license that can be found in the LICENSE file.package service
  4. //+build windows
  5. package minwinsvc
  6. import (
  7. "os"
  8. "sync"
  9. "golang.org/x/sys/windows/svc"
  10. )
  11. var (
  12. onExit func()
  13. guard sync.Mutex
  14. )
  15. func init() {
  16. interactive, err := svc.IsAnInteractiveSession()
  17. if err != nil {
  18. panic(err)
  19. }
  20. // While run as Windows service, it is not an interactive session,
  21. // but we don't want hook execute to be treated as service, e.g. gogs.exe hook pre-receive.
  22. if interactive || len(os.Getenv("SSH_ORIGINAL_COMMAND")) > 0 {
  23. return
  24. }
  25. go func() {
  26. _ = svc.Run("", runner{})
  27. guard.Lock()
  28. f := onExit
  29. guard.Unlock()
  30. // Don't hold this lock in user code.
  31. if f != nil {
  32. f()
  33. }
  34. // Make sure we exit.
  35. os.Exit(0)
  36. }()
  37. }
  38. func setOnExit(f func()) {
  39. guard.Lock()
  40. onExit = f
  41. guard.Unlock()
  42. }
  43. type runner struct{}
  44. func (runner) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
  45. const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
  46. changes <- svc.Status{State: svc.StartPending}
  47. changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
  48. for {
  49. c := <-r
  50. switch c.Cmd {
  51. case svc.Interrogate:
  52. changes <- c.CurrentStatus
  53. case svc.Stop, svc.Shutdown:
  54. changes <- svc.Status{State: svc.StopPending}
  55. return false, 0
  56. }
  57. }
  58. return false, 0
  59. }