a06f331eb8
CI / benchmark (push) Has been skipped
install-script / posix-syntax (push) Successful in 6m1s
CI / build-onnx (push) Failing after 6m43s
init-smoke / dry-run (push) Failing after 15m57s
security / govulncheck (push) Has been cancelled
security / trivy-fs (push) Has been cancelled
CI / test (1.26, ubuntu-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
CI / test (1.26, macos-latest) (push) Has been cancelled
CI / build-windows (push) Has been cancelled
CI / lint (push) Has been cancelled
install-script / powershell-syntax (push) Has been cancelled
install-script / install (macos-14) (push) Has been cancelled
install-script / install (ubuntu-latest) (push) Has been cancelled
72 lines
2.1 KiB
Go
72 lines
2.1 KiB
Go
//go:build windows
|
|
|
|
package platform
|
|
|
|
import (
|
|
"os"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/windows"
|
|
)
|
|
|
|
// stillActive is the exit code GetExitCodeProcess reports while a
|
|
// process is still running (Win32 STILL_ACTIVE / STATUS_PENDING).
|
|
const stillActive = 259
|
|
|
|
// ShutdownSignals returns the signals a long-running process should trap
|
|
// to begin a graceful shutdown. Windows has no SIGTERM; os.Interrupt —
|
|
// delivered for Ctrl-C and Ctrl-Break — is the only portable trigger.
|
|
func ShutdownSignals() []os.Signal {
|
|
return []os.Signal{os.Interrupt}
|
|
}
|
|
|
|
// ProcessAlive reports whether a process with the given PID currently
|
|
// exists and has not yet exited. It opens a query handle and inspects
|
|
// the exit code: only a still-running process reports STILL_ACTIVE.
|
|
func ProcessAlive(pid int) bool {
|
|
if pid <= 0 {
|
|
return false
|
|
}
|
|
h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
|
|
if err != nil {
|
|
return false
|
|
}
|
|
defer windows.CloseHandle(h) //nolint:errcheck // best-effort handle close
|
|
var code uint32
|
|
if err := windows.GetExitCodeProcess(h, &code); err != nil {
|
|
return false
|
|
}
|
|
return code == stillActive
|
|
}
|
|
|
|
// TerminateProcess asks the process to exit. Windows offers no graceful
|
|
// signal a console-less detached process can receive, so this is a hard
|
|
// TerminateProcess — the same as KillProcess. The daemon's preferred
|
|
// stop path is the control-socket RPC; this is only the fallback for a
|
|
// daemon that no longer answers the socket.
|
|
func TerminateProcess(pid int) error {
|
|
return KillProcess(pid)
|
|
}
|
|
|
|
// KillProcess forcibly terminates the process.
|
|
func KillProcess(pid int) error {
|
|
if pid <= 0 {
|
|
return nil
|
|
}
|
|
p, err := os.FindProcess(pid)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return p.Kill()
|
|
}
|
|
|
|
// DetachSysProcAttr returns the SysProcAttr that fully detaches a
|
|
// spawned child: a new process group, so a Ctrl-C in the parent console
|
|
// isn't forwarded, plus DETACHED_PROCESS so the child runs with no
|
|
// inherited console.
|
|
func DetachSysProcAttr() *syscall.SysProcAttr {
|
|
return &syscall.SysProcAttr{
|
|
CreationFlags: windows.CREATE_NEW_PROCESS_GROUP | windows.DETACHED_PROCESS,
|
|
}
|
|
}
|