os/exec: retry ETXTBSY errors in TestFindExecutableVsNoexec

I made this test parallel in CL 439196, which exposed it to the
fork/exec race condition described in #22315. The ETXTBSY errors from
that race should resolve on their own, so we can simply retry the call
to get past them.

Fixes #56811.
Updates #22315.

Change-Id: I2c6aa405bf3a1769d69cf08bf661a9e7f86440b4
Reviewed-on: https://go-review.googlesource.com/c/go/+/458016
Reviewed-by: Ian Lance Taylor <iant@google.com>
Run-TryBot: Bryan Mills <bcmills@google.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
Bryan C. Mills 2022-12-15 17:09:00 -05:00 committed by Gopher Robot
parent 628a1e7d3a
commit 3323dab1f4
1 changed files with 15 additions and 2 deletions

View File

@ -5,6 +5,7 @@
package exec package exec
import ( import (
"errors"
"internal/syscall/unix" "internal/syscall/unix"
"os" "os"
"path/filepath" "path/filepath"
@ -48,8 +49,20 @@ func TestFindExecutableVsNoexec(t *testing.T) {
t.Fatalf("findExecutable: got %v, want nil", err) t.Fatalf("findExecutable: got %v, want nil", err)
} }
if err := Command(path).Run(); err != nil { for {
t.Fatalf("exec: got %v, want nil", err) err = Command(path).Run()
if err == nil {
break
}
if errors.Is(err, syscall.ETXTBSY) {
// A fork+exec in another process 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 {
t.Fatalf("exec: got %v, want nil", err)
}
} }
// Remount with noexec flag. // Remount with noexec flag.