Execute is called by the service manager when service starts, the state of the service will be set to Stopped when this function returns.
(serviceArgs []string, r <-chan svc.ChangeRequest, statusChan chan<- svc.Status)
| 104 | // Execute is called by the service manager when service starts, the state |
| 105 | // of the service will be set to Stopped when this function returns. |
| 106 | func (s *windowsService) Execute(serviceArgs []string, r <-chan svc.ChangeRequest, statusChan chan<- svc.Status) (ssec bool, errno uint32) { |
| 107 | log := logger.Create(nil) |
| 108 | elog, err := eventlog.Open(windowsServiceName) |
| 109 | if err != nil { |
| 110 | log.Err(err).Msgf("Cannot open event log for %s", windowsServiceName) |
| 111 | return |
| 112 | } |
| 113 | defer elog.Close() |
| 114 | |
| 115 | elog.Info(1, fmt.Sprintf("%s service starting", windowsServiceName)) |
| 116 | defer func() { |
| 117 | elog.Info(1, fmt.Sprintf("%s service stopped", windowsServiceName)) |
| 118 | }() |
| 119 | |
| 120 | // the arguments passed here are only meaningful if they were manually |
| 121 | // specified by the user, e.g. using the Services console or `sc start`. |
| 122 | // https://docs.microsoft.com/en-us/windows/desktop/services/service-entry-point |
| 123 | // https://stackoverflow.com/a/6235139 |
| 124 | var args []string |
| 125 | if len(serviceArgs) > 1 { |
| 126 | args = serviceArgs |
| 127 | } else { |
| 128 | // fall back to the arguments from ImagePath (or, as sc calls it, binPath) |
| 129 | args = os.Args |
| 130 | } |
| 131 | elog.Info(1, fmt.Sprintf("%s service arguments: %v", windowsServiceName, args)) |
| 132 | |
| 133 | statusChan <- svc.Status{State: svc.StartPending} |
| 134 | errC := make(chan error) |
| 135 | go func() { |
| 136 | errC <- s.app.Run(args) |
| 137 | }() |
| 138 | statusChan <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown} |
| 139 | |
| 140 | for { |
| 141 | select { |
| 142 | case c := <-r: |
| 143 | switch c.Cmd { |
| 144 | case svc.Interrogate: |
| 145 | statusChan <- c.CurrentStatus |
| 146 | case svc.Stop, svc.Shutdown: |
| 147 | if s.graceShutdownC != nil { |
| 148 | // start graceful shutdown |
| 149 | elog.Info(1, "cloudflared starting graceful shutdown") |
| 150 | close(s.graceShutdownC) |
| 151 | s.graceShutdownC = nil |
| 152 | statusChan <- svc.Status{State: svc.StopPending} |
| 153 | continue |
| 154 | } |
| 155 | // repeated attempts at graceful shutdown forces immediate stop |
| 156 | elog.Info(1, "cloudflared terminating immediately") |
| 157 | statusChan <- svc.Status{State: svc.StopPending} |
| 158 | return false, 0 |
| 159 | default: |
| 160 | elog.Error(1, fmt.Sprintf("unexpected control request #%d", c)) |
| 161 | } |
| 162 | case err := <-errC: |
| 163 | if err != nil { |
no test coverage detected