Skip to content

Commit a79ceda

Browse files
committed
Windows: kill the whole process-tree when terminating a process
1 parent 5d076fd commit a79ceda

File tree

3 files changed

+50
-3
lines changed

3 files changed

+50
-3
lines changed

go.mod

+7-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
module github.com/arduino/go-paths-helper
22

3-
go 1.21
3+
go 1.23.0
44

5-
require github.com/stretchr/testify v1.8.4
5+
toolchain go1.23.2
6+
7+
require (
8+
github.com/stretchr/testify v1.8.4
9+
golang.org/x/sys v0.32.0
10+
)
611

712
require (
813
github.com/davecgh/go-spew v1.1.1 // indirect

go.sum

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
44
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
55
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
66
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
7+
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
8+
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
79
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
810
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
911
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

process_windows.go

+41-1
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,12 @@
3030
package paths
3131

3232
import (
33+
"fmt"
3334
"os/exec"
3435
"syscall"
36+
"unsafe"
37+
38+
"golang.org/x/sys/windows"
3539
)
3640

3741
func tellCommandNotToSpawnShell(oscmd *exec.Cmd) {
@@ -46,5 +50,41 @@ func tellCommandToStartOnNewProcessGroup(_ *exec.Cmd) {
4650
}
4751

4852
func kill(oscmd *exec.Cmd) error {
49-
return oscmd.Process.Kill()
53+
return killProcessTree(uint32(oscmd.Process.Pid))
54+
}
55+
56+
func killProcessTree(pid uint32) error {
57+
// Inspired by: https://stackoverflow.com/a/36089871/1655275
58+
59+
// Make a snapshot of the current running processes
60+
snapshot, err := windows.CreateToolhelp32Snapshot(windows.TH32CS_SNAPPROCESS, 0)
61+
if err != nil {
62+
return fmt.Errorf("getting running processes snapshot: %w", err)
63+
}
64+
65+
// Iterate and filter child processes of the current process
66+
var processEntry windows.ProcessEntry32
67+
processEntry.Size = uint32(unsafe.Sizeof(processEntry))
68+
if windows.Process32First(snapshot, &processEntry) == nil {
69+
for {
70+
if processEntry.ParentProcessID == pid {
71+
// Recurse on the childrens
72+
if err := killProcessTree(processEntry.ProcessID); err != nil {
73+
return fmt.Errorf("error killing child process: %w", err)
74+
}
75+
}
76+
77+
if windows.Process32Next(snapshot, &processEntry) != nil {
78+
break
79+
}
80+
}
81+
}
82+
83+
// And finally, kill the parent
84+
process, err := windows.OpenProcess(windows.PROCESS_ALL_ACCESS, false, pid)
85+
if err != nil {
86+
return fmt.Errorf("opening process for kill: %w", err)
87+
}
88+
defer windows.CloseHandle(process)
89+
return windows.TerminateProcess(process, 128)
5090
}

0 commit comments

Comments
 (0)