Skip to content

Commit

Permalink
Win: fix OpenProcess not recognizing when proc is gone.
Browse files Browse the repository at this point in the history
This is due to ExitCodeProcess needing
PROCESS_QUERY_INFORMATION access rights.
  • Loading branch information
giampaolo committed Oct 1, 2023
1 parent a5c8428 commit 0c0840a
Show file tree
Hide file tree
Showing 4 changed files with 15 additions and 10 deletions.
1 change: 1 addition & 0 deletions make.bat
Original file line number Diff line number Diff line change
Expand Up @@ -31,5 +31,6 @@ if "%TSCRIPT%" == "" (

rem Needed to locate the .pypirc file and upload exes on PyPI.
set HOME=%USERPROFILE%
set PSUTIL_DEBUG=1

%PYTHON% scripts\internal\winmake.py %1 %2 %3 %4 %5 %6
3 changes: 3 additions & 0 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1227,6 +1227,9 @@ def send_signal(self, sig):
self._send_signal(sig)
else: # pragma: no cover
self._raise_if_pid_reused()
if sig != signal.SIGTERM and not self.is_running():
msg = "process no longer exists"
raise NoSuchProcess(self.pid, self._name, msg=msg)
self._proc.send_signal(sig)

def suspend(self):
Expand Down
16 changes: 11 additions & 5 deletions psutil/arch/windows/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,14 @@ PyObject *
psutil_proc_kill(PyObject *self, PyObject *args) {
HANDLE hProcess;
DWORD pid;
DWORD access = PROCESS_TERMINATE | PROCESS_QUERY_LIMITED_INFORMATION;

if (! PyArg_ParseTuple(args, _Py_PARSE_PID, &pid))
return NULL;
if (pid == 0)
return AccessDenied("automatically set for PID 0");

hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid);
hProcess = psutil_check_phandle(hProcess, pid, 0);
hProcess = psutil_handle_from_pid(pid, access);
if (hProcess == NULL) {
return NULL;
}
Expand Down Expand Up @@ -272,6 +272,11 @@ psutil_proc_exe(PyObject *self, PyObject *args) {
if (pid == 0)
return AccessDenied("automatically set for PID 0");

// ...because NtQuerySystemInformation can succeed for terminated
// processes.
if (psutil_pid_is_running(pid) == 0)
return NoSuchProcess("psutil_pid_is_running -> 0");

buffer = MALLOC_ZERO(bufferSize);
if (! buffer) {
PyErr_NoMemory();
Expand Down Expand Up @@ -535,12 +540,13 @@ psutil_proc_suspend_or_resume(PyObject *self, PyObject *args) {
DWORD pid;
NTSTATUS status;
HANDLE hProcess;
DWORD access = PROCESS_SUSPEND_RESUME | PROCESS_QUERY_LIMITED_INFORMATION;
PyObject* suspend;

if (! PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &suspend))
return NULL;
if (! PyArg_ParseTuple(args, _Py_PARSE_PID "O", &pid, &suspend))
return NULL;

hProcess = psutil_handle_from_pid(pid, PROCESS_SUSPEND_RESUME);
hProcess = psutil_handle_from_pid(pid, access);
if (hProcess == NULL)
return NULL;

Expand Down
5 changes: 0 additions & 5 deletions psutil/tests/test_process.py
Original file line number Diff line number Diff line change
Expand Up @@ -1301,11 +1301,6 @@ def assert_raises_nsp(fun, fun_name):
for fun, name in ns.iter(ns.all):
assert_raises_nsp(fun, name)

# NtQuerySystemInformation succeeds even if process is gone.
if WINDOWS and not GITHUB_ACTIONS:
normcase = os.path.normcase
self.assertEqual(normcase(p.exe()), normcase(PYTHON_EXE))

@unittest.skipIf(not POSIX, 'POSIX only')
def test_zombie_process(self):
parent, zombie = self.spawn_zombie()
Expand Down

0 comments on commit 0c0840a

Please sign in to comment.