Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[main](backport #3356) Revert changes to RemovePath #3358

Merged
merged 1 commit into from
Sep 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 13 additions & 33 deletions internal/pkg/agent/install/uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import (
"github.com/elastic/elastic-agent/internal/pkg/config"
"github.com/elastic/elastic-agent/internal/pkg/config/operations"
"github.com/elastic/elastic-agent/pkg/component"
compruntime "github.com/elastic/elastic-agent/pkg/component/runtime"
comprt "github.com/elastic/elastic-agent/pkg/component/runtime"
"github.com/elastic/elastic-agent/pkg/core/logger"
"github.com/elastic/elastic-agent/pkg/features"
)
Expand Down Expand Up @@ -97,51 +97,31 @@ func Uninstall(cfgFile, topPath, uninstallToken string) error {
// to an ERROR_SHARING_VIOLATION. RemovePath will retry up to 2
// seconds if it keeps getting that error.
func RemovePath(path string) error {
if err := removePath(path); err != nil &&
!isRetryableError(err) {
return fmt.Errorf("could not remove %q, unretriable error: %w", path, err)
}

const arbitraryTimeout = 7 * time.Second
const nextSleep = 100 * time.Millisecond
t := time.NewTicker(nextSleep)
defer t.Stop()
const arbitraryTimeout = 5 * time.Second
start := time.Now()

var count int
nextSleep := 1 * time.Millisecond
for {
count++
err := removePath(path)
err := os.RemoveAll(path)
if err == nil {
return nil
}
if isBlockingOnExe(err) {
// try to remove the blocking exe
err = removeBlockingExe(err)
}
if err == nil {
return nil
}
if !isRetryableError(err) {
return err
}

<-t.C
if d := time.Since(start) + nextSleep; d >= arbitraryTimeout {
return fmt.Errorf("could not remove path, "+
"timeout exeeded after %d tries during %s. Last error: %v",
count, arbitraryTimeout, err)
return err
}
}
}

func removePath(path string) error {
err := os.RemoveAll(path)
if err == nil {
return nil
}

if isAccessDeniedError(err) {
// might be blocking on exe, then try to remove the blocking exe
err = removeBlockingExe(err)
}

return err
}

func RemoveBut(path string, bestEffort bool, exceptions ...string) error {
if len(exceptions) == 0 {
return RemovePath(path)
Expand Down Expand Up @@ -252,7 +232,7 @@ func uninstallServiceComponent(ctx context.Context, log *logp.Logger, comp compo
// Do not use infinite retries when uninstalling from the command line. If the uninstall needs to be
// retried the entire uninstall command can be retried. Retries may complete asynchronously with the
// execution of the uninstall command, leading to bugs like https://github.com/elastic/elastic-agent/issues/3060.
return compruntime.UninstallService(ctx, log, comp, uninstallToken)
return comprt.UninstallService(ctx, log, comp, uninstallToken)
}

func serviceComponentsFromConfig(specs component.RuntimeSpecs, cfg *config.Config) ([]component.Component, error) {
Expand Down
2 changes: 1 addition & 1 deletion internal/pkg/agent/install/uninstall_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

package install

func isAccessDeniedError(_ error) bool {
func isBlockingOnExe(_ error) bool {
return false
}

Expand Down
33 changes: 11 additions & 22 deletions internal/pkg/agent/install/uninstall_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,31 +16,26 @@ import (
"golang.org/x/sys/windows"
)

func isAccessDeniedError(err error) bool {
func isBlockingOnExe(err error) bool {
if err == nil {
return false
}

var errno syscall.Errno
if errors.As(err, &errno) {
return errno == syscall.ERROR_ACCESS_DENIED
path, errno := getPathFromError(err)
if path == "" {
return false
}

return false
return errno == syscall.ERROR_ACCESS_DENIED
}

func isRetryableError(err error) bool {
if err == nil {
return false
}

var errno syscall.Errno
if errors.As(err, &errno) {
return errno == syscall.ERROR_ACCESS_DENIED ||
errno == windows.ERROR_SHARING_VIOLATION
path, errno := getPathFromError(err)
if path == "" {
return false
}

return false
return errno == syscall.ERROR_ACCESS_DENIED || errno == windows.ERROR_SHARING_VIOLATION
}

func removeBlockingExe(blockingErr error) error {
Expand Down Expand Up @@ -77,20 +72,14 @@ func removeBlockingExe(blockingErr error) error {
return nil
}

func getPathFromError(err error) (string, syscall.Errno) {
func getPathFromError(blockingErr error) (string, syscall.Errno) {
var perr *fs.PathError
if errors.As(err, &perr) {
if errors.As(blockingErr, &perr) {
var errno syscall.Errno
if errors.As(perr.Err, &errno) {
return perr.Path, errno
}
}

var errno syscall.Errno
if errors.As(err, &errno) {
return "", errno
}

return "", 0
}

Expand Down