Files
wehub-resource-sync 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
chore: import upstream snapshot with attribution
2026-07-13 12:33:42 +08:00

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,
}
}