agent/app/agent_windows.go
func (h *handler) Execute(args []string, requests <-chan svc.ChangeRequest, responses chan<- svc.Status) (bool, uint32) {
	defer seelog.Flush()
	// channels for communication between goroutines
	ctx, cancel := context.WithCancel(context.Background())
	agentDone := make(chan struct{})
	windowsDone := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		defer close(windowsDone)
		defer wg.Done()
		h.handleWindowsRequests(ctx, requests, responses)
	}()

	var agentExitCode uint32
	go func() {
		defer close(agentDone)
		defer wg.Done()
		agentExitCode = h.runAgent(ctx)
	}()

	// Wait until one of the goroutines is either told to stop or fails spectacularly.  Under normal conditions we will
	// be waiting here for a long time.
	select {
	case <-windowsDone:
		// Service was told to stop by the Windows API.  This happens either through manual intervention (i.e.,
		// "Stop-Service AmazonECS") or through system shutdown.  Regardless, this is a normal exit event and not an
		// error.
		seelog.Info("Received normal signal from Windows to exit")
	case <-agentDone:
		// This means that the agent stopped on its own.  This is where it's appropriate to light the event log on fire
		// and set off all the alarms.
		seelog.Errorf("Exiting %d", agentExitCode)
	}
	cancel()
	wg.Wait()
	seelog.Infof("Bye Bye! Exiting with %d", agentExitCode)
	return true, agentExitCode
}
func (h *handler) Execute(args []string, requests <-chan svc.ChangeRequest, responses chan<- svc.Status) (bool, uint32) {
	defer seelog.Flush()
	// channels for communication between goroutines
	ctx, cancel := context.WithCancel(context.Background())
	agentDone := make(chan struct{})
	windowsDone := make(chan struct{})
	wg := sync.WaitGroup{}
	wg.Add(2)

	go func() {
		defer close(windowsDone)
		defer wg.Done()
		h.handleWindowsRequests(ctx, requests, responses)
	}()

	var agentExitCode uint32
	go func() {
		defer close(agentDone)
		defer wg.Done()
		agentExitCode = h.runAgent(ctx)
	}()

	// Wait until one of the goroutines is either told to stop or fails spectacularly.  Under normal conditions we will
	// be waiting here for a long time.
	select {
	case <-windowsDone:
		// Service was told to stop by the Windows API.  This happens either through manual intervention (i.e.,
		// "Stop-Service AmazonECS") or through system shutdown.  Regardless, this is a normal exit event and not an
		// error.
		seelog.Info("Received normal signal from Windows to exit")
	case <-agentDone:
		// This means that the agent stopped on its own.  This is where it's appropriate to light the event log on fire
		// and set off all the alarms.
		seelog.Errorf("Exiting %d", agentExitCode)
	}
	cancel()
	wg.Wait()
	seelog.Infof("Bye Bye! Exiting with %d", agentExitCode)
	return true, agentExitCode
}
// Execute implements https://godoc.org/golang.org/x/sys/windows/svc#Handler
// The basic way that this implementation works is through two channels (representing the requests from Windows and the
// responses we're sending to Windows) and two goroutines (one for message processing with Windows and the other to
// actually run the agent).  Once we've set everything up and started both goroutines, we wait for either one to exit
// (the Windows goroutine will exit based on messages from Windows while the agent goroutine exits if the agent exits)
// and then cancel the other.  Once everything has stopped running, this function returns and the process exits.