golang.org/x/build@v0.0.0-20240506185731-218518f32b70/cmd/buildlet/buildlet_windows.go (about) 1 // Copyright 2015 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 package main 6 7 import ( 8 "log" 9 "os" 10 "syscall" 11 "unsafe" 12 13 "github.com/tarm/serial" 14 ) 15 16 func init() { 17 killProcessTree = killProcessTreeWindows 18 configureSerialLogOutput = configureSerialLogOutputWindows 19 } 20 21 func configureSerialLogOutputWindows() { 22 c := &serial.Config{Name: "COM1", Baud: 9600} 23 s, err := serial.OpenPort(c) 24 if err != nil { 25 // Oh well, we tried. This empirically works 26 // on Windows on GCE. 27 // We can log here anyway and hope somebody sees it 28 // in a GUI console: 29 log.Printf("serial.OpenPort: %v", err) 30 return 31 } 32 log.SetOutput(s) 33 } 34 35 // the system process tree 36 type psTree map[int]int // pid -> parent pid 37 38 // findDescendants searches process tree t for pid process children. 39 // It returns children pids. 40 func (t psTree) findDescendants(pid int) []int { 41 var children []int 42 for child, parent := range t { 43 if parent == pid { 44 children = append(children, child) 45 children = append(children, t.findDescendants(child)...) 46 } 47 } 48 return children 49 } 50 51 func snapshotSysProcesses() (psTree, error) { 52 ss, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPPROCESS, 0) 53 if err != nil { 54 return nil, err 55 } 56 defer syscall.CloseHandle(ss) 57 58 ps := make(psTree) 59 60 var pe syscall.ProcessEntry32 61 pe.Size = uint32(unsafe.Sizeof(pe)) 62 if err = syscall.Process32First(ss, &pe); err != nil { 63 return nil, err 64 } 65 for { 66 ps[int(pe.ProcessID)] = int(pe.ParentProcessID) 67 err = syscall.Process32Next(ss, &pe) 68 if err == syscall.ERROR_NO_MORE_FILES { 69 return ps, nil 70 } 71 if err != nil { 72 return nil, err 73 } 74 } 75 } 76 77 func killProcesses(ps []int) { 78 for _, pid := range ps { 79 p, err := os.FindProcess(pid) 80 if err != nil { 81 continue 82 } 83 p.Kill() 84 p.Release() 85 } 86 } 87 88 func killProcessTreeWindows(p *os.Process) error { 89 ps, err := snapshotSysProcesses() 90 if err != nil { 91 return err 92 } 93 toKill := ps.findDescendants(p.Pid) 94 toKill = append(toKill, p.Pid) 95 killProcesses(toKill) 96 return nil 97 }