Skip to content

Commit f0894a0

Browse files
committed
os: remove 5ms sleep on Windows in (*Process).Wait
The 5ms sleep in (*Process).Wait was added to mitigate errors while removing executable files using os.RemoveAll. Windows 10 1903 implements POSIX semantics for DeleteFile, making the implementation of os.RemoveAll on Windows much more robust. Older Windows 10 versions also made internal improvements to avoid errors when removing files, making it less likely that the 5ms sleep is necessary. Windows 10 is the oldest version that Go supports (see #57004), so it makes sense to unconditionally remove the 5ms sleep now. We have all the Go 1.22 development cycle to see if this causes any regression. Fixes #25965 Change-Id: Ie0bbe6dc3e8389fd51a32484d5d20cf59b019451 Reviewed-on: https://go-review.googlesource.com/c/go/+/509335 Reviewed-by: Brad Fitzpatrick <[email protected]> Reviewed-by: Alex Brainman <[email protected]> Reviewed-by: Bryan Mills <[email protected]> Run-TryBot: Quim Muntal <[email protected]> Reviewed-by: Dmitri Shuralyov <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 4918490 commit f0894a0

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

src/os/exec_windows.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,6 @@ func (p *Process) wait() (ps *ProcessState, err error) {
3535
return nil, NewSyscallError("GetProcessTimes", e)
3636
}
3737
p.setDone()
38-
// NOTE(brainman): It seems that sometimes process is not dead
39-
// when WaitForSingleObject returns. But we do not know any
40-
// other way to wait for it. Sleeping for a while seems to do
41-
// the trick sometimes.
42-
// See https://golang.org/issue/25965 for details.
43-
defer time.Sleep(5 * time.Millisecond)
4438
defer p.Release()
4539
return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil
4640
}

src/os/exec_windows_test.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// Copyright 2023 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
//go:build windows
6+
7+
package os_test
8+
9+
import (
10+
"internal/testenv"
11+
"io"
12+
. "os"
13+
"path/filepath"
14+
"sync"
15+
"testing"
16+
)
17+
18+
func TestRemoveAllWithExecutedProcess(t *testing.T) {
19+
// Regression test for golang.org/issue/25965.
20+
if testing.Short() {
21+
t.Skip("slow test; skipping")
22+
}
23+
testenv.MustHaveExec(t)
24+
25+
name, err := Executable()
26+
if err != nil {
27+
t.Fatal(err)
28+
}
29+
r, err := Open(name)
30+
if err != nil {
31+
t.Fatal(err)
32+
}
33+
defer r.Close()
34+
const n = 100
35+
var execs [n]string
36+
// First create n executables.
37+
for i := 0; i < n; i++ {
38+
// Rewind r.
39+
if _, err := r.Seek(0, io.SeekStart); err != nil {
40+
t.Fatal(err)
41+
}
42+
name := filepath.Join(t.TempDir(), "test.exe")
43+
execs[i] = name
44+
w, err := Create(name)
45+
if err != nil {
46+
t.Fatal(err)
47+
}
48+
if _, err = io.Copy(w, r); err != nil {
49+
w.Close()
50+
t.Fatal(err)
51+
}
52+
if err := w.Sync(); err != nil {
53+
w.Close()
54+
t.Fatal(err)
55+
}
56+
if err = w.Close(); err != nil {
57+
t.Fatal(err)
58+
}
59+
}
60+
// Then run each executable and remove its directory.
61+
// Run each executable in a separate goroutine to add some load
62+
// and increase the chance of triggering the bug.
63+
var wg sync.WaitGroup
64+
wg.Add(n)
65+
for i := 0; i < n; i++ {
66+
go func(i int) {
67+
defer wg.Done()
68+
name := execs[i]
69+
dir := filepath.Dir(name)
70+
// Run test.exe without executing any test, just to make it do something.
71+
cmd := testenv.Command(t, name, "-test.run=^$")
72+
if err := cmd.Run(); err != nil {
73+
t.Errorf("exec failed: %v", err)
74+
}
75+
// Remove dir and check that it doesn't return `ERROR_ACCESS_DENIED`.
76+
err = RemoveAll(dir)
77+
if err != nil {
78+
t.Errorf("RemoveAll failed: %v", err)
79+
}
80+
}(i)
81+
}
82+
wg.Wait()
83+
}

0 commit comments

Comments
 (0)