mirror of https://github.com/golang/go.git
cmd/go/internal/script: retry ETXTBSY errors in scripts
Fixes #58019. Change-Id: Ib25d668bfede6e87a3786f44bdc0db1027e3ebec Reviewed-on: https://go-review.googlesource.com/c/go/+/463748 TryBot-Result: Gopher Robot <gobot@golang.org> Auto-Submit: Bryan Mills <bcmills@google.com> Run-TryBot: Bryan Mills <bcmills@google.com> Reviewed-by: Ian Lance Taylor <iant@google.com>
This commit is contained in:
parent
356647409d
commit
23c0121e4e
|
|
@ -432,21 +432,37 @@ func Exec(cancel func(*exec.Cmd) error, waitDelay time.Duration) Cmd {
|
|||
}
|
||||
|
||||
func startCommand(s *State, name, path string, args []string, cancel func(*exec.Cmd) error, waitDelay time.Duration) (WaitFunc, error) {
|
||||
var stdoutBuf, stderrBuf strings.Builder
|
||||
cmd := exec.CommandContext(s.Context(), path, args...)
|
||||
if cancel == nil {
|
||||
cmd.Cancel = nil
|
||||
} else {
|
||||
cmd.Cancel = func() error { return cancel(cmd) }
|
||||
}
|
||||
cmd.WaitDelay = waitDelay
|
||||
cmd.Args[0] = name
|
||||
cmd.Dir = s.Getwd()
|
||||
cmd.Env = s.env
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stderr = &stderrBuf
|
||||
if err := cmd.Start(); err != nil {
|
||||
return nil, err
|
||||
var (
|
||||
cmd *exec.Cmd
|
||||
stdoutBuf, stderrBuf strings.Builder
|
||||
)
|
||||
for {
|
||||
cmd = exec.CommandContext(s.Context(), path, args...)
|
||||
if cancel == nil {
|
||||
cmd.Cancel = nil
|
||||
} else {
|
||||
cmd.Cancel = func() error { return cancel(cmd) }
|
||||
}
|
||||
cmd.WaitDelay = waitDelay
|
||||
cmd.Args[0] = name
|
||||
cmd.Dir = s.Getwd()
|
||||
cmd.Env = s.env
|
||||
cmd.Stdout = &stdoutBuf
|
||||
cmd.Stderr = &stderrBuf
|
||||
err := cmd.Start()
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if isETXTBSY(err) {
|
||||
// If the script (or its host process) just wrote the executable we're
|
||||
// trying to run, a fork+exec in another thread may be holding open the FD
|
||||
// that we used to write the executable (see https://go.dev/issue/22315).
|
||||
// Since the descriptor should have CLOEXEC set, the problem should
|
||||
// resolve as soon as the forked child reaches its exec call.
|
||||
// Keep retrying until that happens.
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
wait := func(s *State) (stdout, stderr string, err error) {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build !(unix || windows)
|
||||
|
||||
package script
|
||||
|
||||
func isETXTBSY(err error) bool {
|
||||
return false
|
||||
}
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
// Copyright 2023 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
//go:build unix || windows
|
||||
|
||||
package script
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func isETXTBSY(err error) bool {
|
||||
return errors.Is(err, syscall.ETXTBSY)
|
||||
}
|
||||
Loading…
Reference in New Issue