func (h *handler) runAgent(ctx context.Context) uint32 {
	agentCtx, cancel := context.WithCancel(ctx)
	indicator := newTermHandlerIndicator()

	terminationHandler := func(saver statemanager.Saver, taskEngine engine.TaskEngine) {
		// We're using a custom indicator to record that the handler is scheduled to be executed (has been invoked) and
		// to determine whether it should run (we skip when the agent engine has already exited).  After recording to
		// the indicator that the handler has been invoked, we wait on the context.  When we wake up, we determine
		// whether to execute or not based on whether the agent is still running.
		defer indicator.finish()
		indicator.setInvoked()
		<-agentCtx.Done()
		if !indicator.isAgentRunning() {
			return
		}

		seelog.Info("Termination handler received signal to stop")
		err := sighandlers.FinalSave(saver, taskEngine)
		if err != nil {
			seelog.Criticalf("Error saving state before final shutdown: %v", err)
		}
	}
	h.ecsAgent.setTerminationHandler(terminationHandler)

	go func() {
		defer cancel()
		exitCode := h.ecsAgent.start() // should block forever, unless there is an error

		if exitCode == exitcodes.ExitTerminal {
			seelog.Critical("Terminal exit code received from agent.  Windows SCM will not restart the AmazonECS service.")
			// We override the exit code to 0 here so that Windows does not treat this as a restartable failure even
			// when "sc.exe failureflag" is set.
			exitCode = 0
		}

		indicator.agentStopped(exitCode)
	}()

	sleepCtx(agentCtx, time.Minute) // give the agent a minute to start and invoke terminationHandler

	// wait for the termination handler to run.  Once the termination handler runs, we can safely exit.  If the agent
	// exits by itself, the termination handler doesn't need to do anything and skips.  If the agent exits before the
	// termination handler is invoked, we can exit immediately.
	return indicator.wait()
}
func (h *handler) runAgent(ctx context.Context) uint32 {
	agentCtx, cancel := context.WithCancel(ctx)
	indicator := newTermHandlerIndicator()

	terminationHandler := func(saver statemanager.Saver, taskEngine engine.TaskEngine) {
		
		
		
		
		defer indicator.finish()
		indicator.setInvoked()
		<-agentCtx.Done()
		if !indicator.isAgentRunning() {
			return
		}

		seelog.Info("Termination handler received signal to stop")
		err := sighandlers.FinalSave(saver, taskEngine)
		if err != nil {
			seelog.Criticalf("Error saving state before final shutdown: %v", err)
		}
	}
	h.ecsAgent.setTerminationHandler(terminationHandler)

	go func() {
		defer cancel()
		exitCode := h.ecsAgent.start() 

		if exitCode == exitcodes.ExitTerminal {
			seelog.Critical("Terminal exit code received from agent.  Windows SCM will not restart the AmazonECS service.")
			
			
			exitCode = 0
		}

		indicator.agentStopped(exitCode)
	}()

	sleepCtx(agentCtx, time.Minute) 

	
	
	
	return indicator.wait()
}
func ( h * handler ) runAgent ( ctx context . Context ) uint32 { agentCtx , cancel := context . WithCancel ( ctx ) indicator := newTermHandlerIndicator ( ) terminationHandler := func ( saver statemanager . Saver , taskEngine engine . TaskEngine ) { // We're using a custom indicator to record that the handler is scheduled to be executed (has been invoked) and // to determine whether it should run (we skip when the agent engine has already exited).  After recording to // the indicator that the handler has been invoked, we wait on the context.  When we wake up, we determine // whether to execute or not based on whether the agent is still running. defer indicator . finish ( ) indicator . setInvoked ( ) <- agentCtx . Done ( ) if ! indicator . isAgentRunning ( ) { return } seelog . Info ( " " ) err := sighandlers . FinalSave ( saver , taskEngine ) if err != nil { seelog . Criticalf ( " " , err ) } } h . ecsAgent . setTerminationHandler ( terminationHandler ) go func ( ) { defer cancel ( ) exitCode := h . ecsAgent . start ( ) // should block forever, unless there is an error if exitCode == exitcodes . ExitTerminal { seelog . Critical ( " " ) // We override the exit code to 0 here so that Windows does not treat this as a restartable failure even // when "sc.exe failureflag" is set. exitCode = 0 } indicator . agentStopped ( exitCode ) } ( ) sleepCtx ( agentCtx , time . Minute ) // give the agent a minute to start and invoke terminationHandler // wait for the termination handler to run.  Once the termination handler runs, we can safely exit.  If the agent // exits by itself, the termination handler doesn't need to do anything and skips.  If the agent exits before the // termination handler is invoked, we can exit immediately. return indicator . wait ( ) }
// runAgent runs the ECS agent inside a goroutine and waits to be told to exit.
runAgent runs the ECS agent inside a goroutine and waits to be told to exit .