summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2020-01-18 11:22:08 -0800
committerGitHub <noreply@github.com>2020-01-18 11:22:08 -0800
commitf76582181e8d3b7c36900eededf904fc4b4f5f89 (patch)
tree3be7378c9da6ddbf8d777c746526d49d8e9c372c
parent33fea55c3e89a38e668675ed3971c923e81fafc3 (diff)
downloadpsutil-f76582181e8d3b7c36900eededf904fc4b4f5f89.tar.gz
[Windows] psutil_handle_from_pid() refactoring (#1668)
-rw-r--r--psutil/arch/windows/process_utils.c212
1 files changed, 52 insertions, 160 deletions
diff --git a/psutil/arch/windows/process_utils.c b/psutil/arch/windows/process_utils.c
index f6867ca1..dbdebd48 100644
--- a/psutil/arch/windows/process_utils.c
+++ b/psutil/arch/windows/process_utils.c
@@ -52,9 +52,8 @@ psutil_get_pids(DWORD *numberOfReturnedPIDs) {
return procArray;
}
-/*
- * Return 1 if PID exists, 0 if not, -1 on error.
- */
+
+// Return 1 if PID exists, 0 if not, -1 on error.
int
psutil_pid_in_pids(DWORD pid) {
DWORD *proclist = NULL;
@@ -75,94 +74,53 @@ psutil_pid_in_pids(DWORD pid) {
}
-/*
- * Given a process HANDLE checks whether it's actually running.
- * Returns:
- * - 1: running
- * - 0: not running
- * - -1: WindowsError
- * - -2: AssertionError
- */
-int
-psutil_is_phandle_running(HANDLE hProcess, DWORD pid) {
- DWORD processExitCode = 0;
+// Given a process handle checks whether it's actually running. If it
+// does return the handle, else return NULL with Python exception set.
+// This is needed because OpenProcess API sucks.
+HANDLE
+psutil_check_phandle(HANDLE hProcess, DWORD pid) {
+ DWORD exitCode;
if (hProcess == NULL) {
if (GetLastError() == ERROR_INVALID_PARAMETER) {
// Yeah, this is the actual error code in case of
// "no such process".
- if (! psutil_assert_pid_not_exists(
- pid, "iphr: OpenProcess() -> ERROR_INVALID_PARAMETER")) {
- return -2;
- }
- return 0;
+ NoSuchProcess("OpenProcess");
+ return NULL;
}
- return -1;
+ PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
+ return NULL;
}
- if (GetExitCodeProcess(hProcess, &processExitCode)) {
+ if (GetExitCodeProcess(hProcess, &exitCode)) {
// XXX - maybe STILL_ACTIVE is not fully reliable as per:
// http://stackoverflow.com/questions/1591342/#comment47830782_1591379
- if (processExitCode == STILL_ACTIVE) {
- if (! psutil_assert_pid_exists(
- pid, "iphr: GetExitCodeProcess() -> STILL_ACTIVE")) {
- return -2;
- }
- return 1;
+ if (exitCode == STILL_ACTIVE) {
+ return hProcess;
}
- else {
- // We can't be sure so we look into pids.
- if (psutil_pid_in_pids(pid) == 1) {
- return 1;
- }
- else {
- CloseHandle(hProcess);
- return 0;
- }
+ if (psutil_pid_in_pids(pid) == 1) {
+ return hProcess;
}
+ CloseHandle(hProcess);
+ NoSuchProcess("GetExitCodeProcess != STILL_ACTIVE");
+ return NULL;
}
- CloseHandle(hProcess);
- if (! psutil_assert_pid_not_exists( pid, "iphr: exit fun")) {
- return -2;
- }
- return -1;
-}
-
-
-/*
- * Given a process HANDLE checks whether it's actually running and if
- * it does return it, else return NULL with the proper Python exception
- * set.
- */
-HANDLE
-psutil_check_phandle(HANDLE hProcess, DWORD pid) {
- int ret = psutil_is_phandle_running(hProcess, pid);
- if (ret == 1) {
+ if (GetLastError() == ERROR_ACCESS_DENIED) {
+ psutil_debug("GetExitCodeProcess -> ERROR_ACCESS_DENIED (ignored)");
+ SetLastError(0);
return hProcess;
}
- else if (ret == 0) {
- return NoSuchProcess("psutil_is_phandle_running");
- }
- else if (ret == -1) {
- if (GetLastError() == ERROR_ACCESS_DENIED)
- return PyErr_SetFromWindowsErr(0);
- else
- return PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
- }
- else {
- return NULL;
- }
+ PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess");
+ CloseHandle(hProcess);
+ return NULL;
}
-/*
- * A wrapper around OpenProcess setting NSP exception if process
- * no longer exists.
- * "pid" is the process pid, "dwDesiredAccess" is the first argument
- * exptected by OpenProcess.
- * Return a process handle or NULL.
- */
+// A wrapper around OpenProcess setting NSP exception if process no
+// longer exists. *pid* is the process PID, *access* is the first
+// argument to OpenProcess.
+// Return a process handle or NULL with exception set.
HANDLE
psutil_handle_from_pid(DWORD pid, DWORD access) {
HANDLE hProcess;
@@ -171,113 +129,47 @@ psutil_handle_from_pid(DWORD pid, DWORD access) {
// otherwise we'd get NoSuchProcess
return AccessDenied("automatically set for PID 0");
}
- // needed for GetExitCodeProcess
- access |= PROCESS_QUERY_LIMITED_INFORMATION;
- hProcess = OpenProcess(access, FALSE, pid);
- return psutil_check_phandle(hProcess, pid);
-}
+ hProcess = OpenProcess(access, FALSE, pid);
-int
-psutil_assert_pid_exists(DWORD pid, char *err) {
- if (PSUTIL_TESTING) {
- if (psutil_pid_in_pids(pid) == 0) {
- PyErr_SetString(PyExc_AssertionError, err);
- return 0;
- }
+ if ((hProcess == NULL) && (GetLastError() == ERROR_ACCESS_DENIED)) {
+ PyErr_SetFromOSErrnoWithSyscall("OpenProcess");
+ return NULL;
}
- return 1;
-}
-
-int
-psutil_assert_pid_not_exists(DWORD pid, char *err) {
- if (PSUTIL_TESTING) {
- if (psutil_pid_in_pids(pid) == 1) {
- PyErr_SetString(PyExc_AssertionError, err);
- return 0;
- }
- }
- return 1;
+ hProcess = psutil_check_phandle(hProcess, pid);
+ return hProcess;
}
-/*
-/* Check for PID existance by using OpenProcess() + GetExitCodeProcess.
-/* Returns:
- * 1: pid exists
- * 0: it doesn't
- * -1: error
- */
+// Check for PID existance. Return 1 if pid exists, 0 if not, -1 on error.
int
psutil_pid_is_running(DWORD pid) {
HANDLE hProcess;
- DWORD exitCode;
- DWORD err;
// Special case for PID 0 System Idle Process
if (pid == 0)
return 1;
if (pid < 0)
return 0;
+ return psutil_pid_in_pids(pid);
+
hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
- if (NULL == hProcess) {
- err = GetLastError();
- // Yeah, this is the actual error code in case of "no such process".
- if (err == ERROR_INVALID_PARAMETER) {
- if (! psutil_assert_pid_not_exists(
- pid, "pir: OpenProcess() -> INVALID_PARAMETER")) {
- return -1;
- }
- return 0;
- }
- // Access denied obviously means there's a process to deny access to.
- else if (err == ERROR_ACCESS_DENIED) {
- if (! psutil_assert_pid_exists(
- pid, "pir: OpenProcess() ACCESS_DENIED")) {
- return -1;
- }
- return 1;
- }
- // Be strict and raise an exception; the caller is supposed
- // to take -1 into account.
- else {
- PyErr_SetFromOSErrnoWithSyscall("OpenProcess(PROCESS_VM_READ)");
- return -1;
- }
- }
- if (GetExitCodeProcess(hProcess, &exitCode)) {
+ // Access denied means there's a process to deny access to.
+ if ((hProcess == NULL) && (GetLastError() == ERROR_ACCESS_DENIED))
+ return 1;
+
+ hProcess = psutil_check_phandle(hProcess, pid);
+ if (hProcess != NULL) {
CloseHandle(hProcess);
- // XXX - maybe STILL_ACTIVE is not fully reliable as per:
- // http://stackoverflow.com/questions/1591342/#comment47830782_1591379
- if (exitCode == STILL_ACTIVE) {
- if (! psutil_assert_pid_exists(
- pid, "pir: GetExitCodeProcess() -> STILL_ACTIVE")) {
- return -1;
- }
- return 1;
- }
- // We can't be sure so we look into pids.
- else {
- return psutil_pid_in_pids(pid);
- }
+ return 1;
}
- else {
- err = GetLastError();
- CloseHandle(hProcess);
- // Same as for OpenProcess, assume access denied means there's
- // a process to deny access to.
- if (err == ERROR_ACCESS_DENIED) {
- if (! psutil_assert_pid_exists(
- pid, "pir: GetExitCodeProcess() -> ERROR_ACCESS_DENIED")) {
- return -1;
- }
- return 1;
- }
- else {
- PyErr_SetFromOSErrnoWithSyscall("GetExitCodeProcess");
- return -1;
- }
+
+ CloseHandle(hProcess);
+ if ((PSUTIL_TESTING) && (psutil_pid_in_pids(pid) == 1)) {
+ PyErr_SetString(PyExc_AssertionError, "NULL handle but PID exists");
+ return -1;
}
+ return 0;
}