From e6bf56b9afff24f487f9aa9a23196135451d283b Mon Sep 17 00:00:00 2001 From: wwqgtxx Date: Mon, 5 Jan 2026 20:26:19 +0800 Subject: [PATCH] fix: os.(*Process).Wait not working on Windows7 --- .github/patch/go1.25.patch | 43 ++++++++++++++++++++++++++++++++++++- .github/patch/go1.26.patch | 43 ++++++++++++++++++++++++++++++++++++- .github/workflows/build.yml | 1 + 3 files changed, 85 insertions(+), 2 deletions(-) diff --git a/.github/patch/go1.25.patch b/.github/patch/go1.25.patch index a7f724ff..a8317b65 100644 --- a/.github/patch/go1.25.patch +++ b/.github/patch/go1.25.patch @@ -1,4 +1,5 @@ -Subject: [PATCH] Fix os.RemoveAll not working on Windows7 +Subject: [PATCH] Revert "os: remove 5ms sleep on Windows in (*Process).Wait" +Fix os.RemoveAll not working on Windows7 Revert "runtime: always use LoadLibraryEx to load system libraries" Revert "syscall: remove Windows 7 console handle workaround" Revert "net: remove sysSocket fallback for Windows 7" @@ -841,3 +842,43 @@ diff --git a/src/os/root_windows.go b/src/os/root_windows.go +func checkPathEscapesLstat(r *Root, name string) error { + return checkPathEscapes(r, name) +} +Index: src/os/exec_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/exec_windows.go b/src/os/exec_windows.go +--- a/src/os/exec_windows.go (revision 0a52622d2331ff975fb0442617ec19bc352bb2ed) ++++ b/src/os/exec_windows.go (revision fb3d09a67fe97008ad76fea97ae88170072cbdbb) +@@ -10,6 +10,7 @@ + "runtime" + "syscall" + "time" ++ _ "unsafe" + ) + + // Note that Process.handle is never nil because Windows always requires +@@ -49,9 +50,23 @@ + // than statusDone. + p.doRelease(statusReleased) + ++ var maj, min, build uint32 ++ rtlGetNtVersionNumbers(&maj, &min, &build) ++ if maj < 10 { ++ // NOTE(brainman): It seems that sometimes process is not dead ++ // when WaitForSingleObject returns. But we do not know any ++ // other way to wait for it. Sleeping for a while seems to do ++ // the trick sometimes. ++ // See https://golang.org/issue/25965 for details. ++ time.Sleep(5 * time.Millisecond) ++ } ++ + return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil + } + ++//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers ++func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) ++ + func (p *Process) signal(sig Signal) error { + handle, status := p.handleTransientAcquire() + switch status { diff --git a/.github/patch/go1.26.patch b/.github/patch/go1.26.patch index 29dab4d0..4f7ca14e 100644 --- a/.github/patch/go1.26.patch +++ b/.github/patch/go1.26.patch @@ -1,4 +1,5 @@ -Subject: [PATCH] Fix os.RemoveAll not working on Windows7 +Subject: [PATCH] Revert "os: remove 5ms sleep on Windows in (*Process).Wait" +Fix os.RemoveAll not working on Windows7 Revert "runtime: always use LoadLibraryEx to load system libraries" Revert "syscall: remove Windows 7 console handle workaround" Revert "net: remove sysSocket fallback for Windows 7" @@ -840,3 +841,43 @@ diff --git a/src/os/root_windows.go b/src/os/root_windows.go +func checkPathEscapesLstat(r *Root, name string) error { + return checkPathEscapes(r, name) +} +Index: src/os/exec_windows.go +IDEA additional info: +Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP +<+>UTF-8 +=================================================================== +diff --git a/src/os/exec_windows.go b/src/os/exec_windows.go +--- a/src/os/exec_windows.go (revision d47e0d22130d597dcf9daa6b41fd9501274f0cb2) ++++ b/src/os/exec_windows.go (revision 00e8daec9a4d88f44a8dc55d3bdb71878e525b41) +@@ -10,6 +10,7 @@ + "runtime" + "syscall" + "time" ++ _ "unsafe" + ) + + // Note that Process.handle is never nil because Windows always requires +@@ -49,9 +50,23 @@ + // than statusDone. + p.doRelease(statusReleased) + ++ var maj, min, build uint32 ++ rtlGetNtVersionNumbers(&maj, &min, &build) ++ if maj < 10 { ++ // NOTE(brainman): It seems that sometimes process is not dead ++ // when WaitForSingleObject returns. But we do not know any ++ // other way to wait for it. Sleeping for a while seems to do ++ // the trick sometimes. ++ // See https://golang.org/issue/25965 for details. ++ time.Sleep(5 * time.Millisecond) ++ } ++ + return &ProcessState{p.Pid, syscall.WaitStatus{ExitCode: ec}, &u}, nil + } + ++//go:linkname rtlGetNtVersionNumbers syscall.rtlGetNtVersionNumbers ++func rtlGetNtVersionNumbers(majorVersion *uint32, minorVersion *uint32, buildNumber *uint32) ++ + func (p *Process) signal(sig Signal) error { + handle, status := p.handleTransientAcquire() + switch status { diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3fe99a6b..9b213785 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -178,6 +178,7 @@ jobs: # 7c1157f9544922e96945196b47b95664b1e39108: "net: remove sysSocket fallback for Windows 7" # 48042aa09c2f878c4faa576948b07fe625c4707a: "syscall: remove Windows 7 console handle workaround" # a17d959debdb04cd550016a3501dd09d50cd62e7: "runtime: always use LoadLibraryEx to load system libraries" + # f0894a00f4b756d4b9b4078af2e686b359493583: "os: remove 5ms sleep on Windows in (*Process).Wait" # sepical fix: # - os.RemoveAll not working on Windows7 - name: Revert Golang1.25 commit for Windows7/8