github.com/anth0d/nomad@v0.0.0-20221214183521-ae3a0a2cad06/drivers/shared/executor/executor_windows.go (about) 1 //go:build windows 2 3 package executor 4 5 import ( 6 "fmt" 7 "os" 8 "syscall" 9 ) 10 11 // configure new process group for child process 12 func (e *UniversalExecutor) setNewProcessGroup() error { 13 // We need to check that as build flags includes windows for this file 14 if e.childCmd.SysProcAttr == nil { 15 e.childCmd.SysProcAttr = &syscall.SysProcAttr{} 16 } 17 e.childCmd.SysProcAttr.CreationFlags = syscall.CREATE_NEW_PROCESS_GROUP 18 return nil 19 } 20 21 // Cleanup any still hanging user processes 22 func (e *UniversalExecutor) killProcessTree(proc *os.Process) error { 23 // We must first verify if the process is still running. 24 // (Windows process often lingered around after being reported as killed). 25 handle, err := syscall.OpenProcess(syscall.PROCESS_TERMINATE|syscall.SYNCHRONIZE|syscall.PROCESS_QUERY_INFORMATION, false, uint32(proc.Pid)) 26 if err != nil { 27 return os.NewSyscallError("OpenProcess", err) 28 } 29 defer syscall.CloseHandle(handle) 30 31 result, err := syscall.WaitForSingleObject(syscall.Handle(handle), 0) 32 33 switch result { 34 case syscall.WAIT_OBJECT_0: 35 return nil 36 case syscall.WAIT_TIMEOUT: 37 // Process still running. Just kill it. 38 return proc.Kill() 39 default: 40 return os.NewSyscallError("WaitForSingleObject", err) 41 } 42 } 43 44 // Send a Ctrl-Break signal for shutting down the process, 45 // like in https://golang.org/src/os/signal/signal_windows_test.go 46 func sendCtrlBreak(pid int) error { 47 dll, err := syscall.LoadDLL("kernel32.dll") 48 if err != nil { 49 return fmt.Errorf("Error loading kernel32.dll: %v", err) 50 } 51 proc, err := dll.FindProc("GenerateConsoleCtrlEvent") 52 if err != nil { 53 return fmt.Errorf("Cannot find procedure GenerateConsoleCtrlEvent: %v", err) 54 } 55 result, _, err := proc.Call(syscall.CTRL_BREAK_EVENT, uintptr(pid)) 56 if result == 0 { 57 return fmt.Errorf("Error sending ctrl-break event: %v", err) 58 } 59 return nil 60 } 61 62 // Send the process a Ctrl-Break event, allowing it to shutdown by itself 63 // before being Terminate. 64 func (e *UniversalExecutor) shutdownProcess(_ os.Signal, proc *os.Process) error { 65 if err := sendCtrlBreak(proc.Pid); err != nil { 66 return fmt.Errorf("executor shutdown error: %v", err) 67 } 68 e.logger.Debug("sent Ctrl-Break to process", "pid", proc.Pid) 69 70 return nil 71 }