Skip to content

Commit

Permalink
[Elastic Agent] Await execution finish on windows (#27730)
Browse files Browse the repository at this point in the history
* Await execution finish on windows

* don't wait if not running as a service
  • Loading branch information
michalpristas committed Sep 3, 2021
1 parent 837d531 commit 2f897aa
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 6 deletions.
3 changes: 3 additions & 0 deletions libbeat/service/service_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,6 @@ func ProcessWindowsControlEvents(stopCallback func()) {

func notifyWindowsServiceStopped() {
}

// WaitExecutionDone is not used on non-windows platforms.
func WaitExecutionDone() {}
26 changes: 22 additions & 4 deletions libbeat/service/service_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,15 @@ import (
)

type beatService struct {
stopCallback func()
done chan struct{}
stopCallback func()
done chan struct{}
executeFinished chan struct{}
}

var serviceInstance = &beatService{
stopCallback: nil,
done: make(chan struct{}, 0),
stopCallback: nil,
done: make(chan struct{}, 0),
executeFinished: make(chan struct{}, 0),
}

// Execute runs the beat service with the arguments and manages changes that
Expand Down Expand Up @@ -85,6 +87,8 @@ const couldNotConnect syscall.Errno = 1063
// stopCallback function is called when the Stop/Shutdown
// request is received.
func ProcessWindowsControlEvents(stopCallback func()) {
defer close(serviceInstance.executeFinished)

isInteractive, err := svc.IsAnInteractiveSession()
if err != nil {
logp.Err("IsAnInteractiveSession: %v", err)
Expand Down Expand Up @@ -125,3 +129,17 @@ func ProcessWindowsControlEvents(stopCallback func()) {

logp.Err("Windows service setup failed: %+v", err)
}

// WaitExecutionDone returns only after stop was reported to service manager.
// If response is not retrieved within 500 millisecond wait is aborted.
func WaitExecutionDone() {
if isWinService, err := svc.IsWindowsService(); err != nil || !isWinService {
// not a service, don't wait
return
}

select {
case <-serviceInstance.executeFinished:
case <-time.After(500 * time.Millisecond):
}
}
8 changes: 6 additions & 2 deletions x-pack/elastic-agent/pkg/agent/cmd/run.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,14 @@ func newRunCommandWithArgs(_ []string, streams *cli.IOStreams) *cobra.Command {
}
}

func run(streams *cli.IOStreams, override cfgOverrider) error { // Windows: Mark service as stopped.
func run(streams *cli.IOStreams, override cfgOverrider) error {
// Windows: Mark service as stopped.
// After this is run, the service is considered by the OS to be stopped.
// This must be the first deferred cleanup task (last to execute).
defer service.NotifyTermination()
defer func() {
service.NotifyTermination()
service.WaitExecutionDone()
}()

locker := filelock.NewAppLocker(paths.Data(), paths.AgentLockFileName)
if err := locker.TryLock(); err != nil {
Expand Down

0 comments on commit 2f897aa

Please sign in to comment.