From 4a95469fc9c84a9b742ce582e09a871717827e3c Mon Sep 17 00:00:00 2001 From: Lomanic Date: Sun, 7 Jul 2019 16:15:45 +0200 Subject: [PATCH] [process][windows] Fix #607 check pid existence with OpenProcess+GetExitCodeProcess Reference https://stackoverflow.com/a/600217 --- process/process_windows.go | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/process/process_windows.go b/process/process_windows.go index c091615..d47b9f4 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -181,18 +181,41 @@ func PidsWithContext(ctx context.Context) ([]int32, error) { } func PidExistsWithContext(ctx context.Context, pid int32) (bool, error) { - pids, err := Pids() - if err != nil { - return false, err + if pid == 0 { // special case for pid 0 System Idle Process + return true, nil } - - for _, i := range pids { - if i == pid { - return true, err + if pid < 0 { + return false, fmt.Errorf("invalid pid %v", pid) + } + if pid%4 != 0 { + // OpenProcess will succeed even on non-existing pid here https://devblogs.microsoft.com/oldnewthing/20080606-00/?p=22043 + // so we list every pid just to be sure and be future-proof + pids, err := PidsWithContext(ctx) + if err != nil { + return false, err + } + for _, i := range pids { + if i == pid { + return true, err + } } + return false, err } - - return false, err + const STILL_ACTIVE = 259 // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess + h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid)) + if err == windows.ERROR_ACCESS_DENIED { + return true, nil + } + if err == windows.ERROR_INVALID_PARAMETER { + return false, nil + } + if err != nil { + return false, err + } + defer syscall.CloseHandle(syscall.Handle(h)) + var exitCode uint32 + err = windows.GetExitCodeProcess(h, &exitCode) + return exitCode == STILL_ACTIVE, err } func (p *Process) Ppid() (int32, error) {