Skip to content

Commit

Permalink
[OpenBSD] Process num_fds() and open_files() may raise NSP for PI…
Browse files Browse the repository at this point in the history
…D 0 (#2460)

This is weird, because of all the sudden the tests below started failing. This is despite PID 0 exists. The syscall failing with `ESRCH` is `kinfo_getfile`:
https://github.com/giampaolo/psutil/blob/f8b929b0754a4abbdadfdcb8aae382ddee8a13f9/psutil/arch/openbsd/proc.c#L57
We therefore return "null" fallback values instead of raising `NoSuchProcess`. 

```
=================================== FAILURES ===================================
___________________________ TestProcess.test_as_dict ___________________________
psutil/_psbsd.py:604: in wrapper
    return fun(self, *args, **kwargs)
psutil/_psbsd.py:914: in open_files
    rawlist = cext.proc_open_files(self.pid)
E   ProcessLookupError: [Errno 3] No such process (originated from sysctl(kinfo_file) (1/2))

During handling of the above exception, another exception occurred:
psutil/tests/test_process.py:1309: in test_as_dict
    d = p.as_dict()
psutil/__init__.py:558: in as_dict
    ret = meth()
psutil/__init__.py:1199: in open_files
    return self._proc.open_files()
psutil/_psbsd.py:609: in wrapper
    raise NoSuchProcess(self.pid, self._name)
E   psutil.NoSuchProcess: process no longer exists (pid=0)
____________________________ TestProcess.test_pid_0 ____________________________
psutil/_psbsd.py:604: in wrapper
    return fun(self, *args, **kwargs)
psutil/_psbsd.py:914: in open_files
    rawlist = cext.proc_open_files(self.pid)
E   ProcessLookupError: [Errno 3] No such process (originated from sysctl(kinfo_file) (1/2))

During handling of the above exception, another exception occurred:
psutil/tests/test_process.py:1513: in test_pid_0
    ret = fun()
psutil/__init__.py:1199: in open_files
    return self._proc.open_files()
psutil/_psbsd.py:609: in wrapper
    raise NoSuchProcess(self.pid, self._name)
E   psutil.NoSuchProcess: process no longer exists (pid=0)
________________________ TestFetchAllProcesses.test_all ________________________
psutil/_psbsd.py:604: in wrapper
    return fun(self, *args, **kwargs)
psutil/_psbsd.py:914: in open_files
    rawlist = cext.proc_open_files(self.pid)
E   ProcessLookupError: [Errno 3] No such process (originated from sysctl(kinfo_file) (1/2))

During handling of the above exception, another exception occurred:
psutil/tests/test_process_all.py:93: in proc_info
    info[fun_name] = fun()
psutil/__init__.py:1199: in open_files
    return self._proc.open_files()
psutil/_psbsd.py:609: in wrapper
    raise NoSuchProcess(self.pid, self._name)
E   psutil.NoSuchProcess: process no longer exists (pid=0, name='swapper')

During handling of the above exception, another exception occurred:
psutil/tests/test_process_all.py:135: in test_all
    for info in self.iter_proc_info():
psutil/tests/test_process_all.py:130: in iter_proc_info
    ls.append(proc_info(pid))
psutil/tests/test_process_all.py:95: in proc_info
    check_exception(exc, proc, name, ppid)
psutil/tests/test_process_all.py:65: in check_exception
    tcase.assertProcessGone(proc)
psutil/tests/__init__.py:1069: in assertProcessGone
    self.assertPidGone(proc.pid)
psutil/tests/__init__.py:1057: in assertPidGone
    with pytest.raises(psutil.NoSuchProcess) as cm:
E   Failed: DID NOT RAISE <class 'psutil.NoSuchProcess'>
```
  • Loading branch information
giampaolo authored Oct 14, 2024
1 parent 0a71d0e commit f65fe44
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 7 deletions.
3 changes: 3 additions & 0 deletions HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ XXXX-XX-XX
Python 3.13. (patch by Sam Gross)
- 2455_, [Linux]: ``IndexError`` may occur when reading /proc/pid/stat and
field 40 (blkio_ticks) is missing.
- 2460_, [OpenBSD]: `Process.num_fds()`_ and `Process.open_files()`_ may fail
with `NoSuchProcess`_ for PID 0. Instead, we now return "null" values (0 and
[] respectively).

6.0.0
======
Expand Down
4 changes: 2 additions & 2 deletions INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ OpenBSD

::

export PKG_PATH=http://ftp.eu.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/
export PKG_PATH=https://cdn.openbsd.org/pub/OpenBSD/`uname -r`/packages/`uname -m`/
pkg_add -v python3 gcc
pip install psutil

Expand All @@ -93,7 +93,7 @@ Assuming Python 3.11 (the most recent at the time of writing):

::

export PKG_PATH="http://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
export PKG_PATH="https://ftp.netbsd.org/pub/pkgsrc/packages/NetBSD/`uname -m`/`uname -r`/All"
pkg_add -v pkgin
pkgin install python311-* gcc12-* py311-setuptools-* py311-pip-*
python3.11 -m pip install psutil
Expand Down
11 changes: 10 additions & 1 deletion psutil/arch/bsd/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,8 +442,17 @@ psutil_proc_open_files(PyObject *self, PyObject *args) {

errno = 0;
freep = kinfo_getfile(pid, &cnt);

if (freep == NULL) {
#if !defined(PSUTIL_OPENBSD)
#if defined(PSUTIL_OPENBSD)
if ((pid == 0) && (errno == ESRCH)) {
psutil_debug(
"open_files() returned ESRCH for PID 0; forcing `return []`"
);
PyErr_Clear();
return py_retlist;
}
#else
psutil_raise_for_pid(pid, "kinfo_getfile()");
#endif
goto error;
Expand Down
19 changes: 15 additions & 4 deletions psutil/arch/openbsd/proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ psutil_kinfo_proc(pid_t pid, struct kinfo_proc *proc) {

ret = sysctl((int*)mib, 6, proc, &size, NULL, 0);
if (ret == -1) {
PyErr_SetFromErrno(PyExc_OSError);
psutil_PyErr_SetFromOSErrnoWithSyscall("sysctl(kinfo_proc)");
return -1;
}
// sysctl stores 0 in the size if we can't find the process information.
Expand Down Expand Up @@ -69,7 +69,7 @@ kinfo_getfile(pid_t pid, int* cnt) {

/* get the size of what would be returned */
if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) {
PyErr_SetFromErrno(PyExc_OSError);
psutil_PyErr_SetFromOSErrnoWithSyscall("sysctl(kinfo_file) (1/2)");
return NULL;
}
if ((kf = malloc(len)) == NULL) {
Expand All @@ -79,7 +79,7 @@ kinfo_getfile(pid_t pid, int* cnt) {
mib[5] = (int)(len / sizeof(struct kinfo_file));
if (sysctl(mib, 6, kf, &len, NULL, 0) < 0) {
free(kf);
PyErr_SetFromErrno(PyExc_OSError);
psutil_PyErr_SetFromOSErrnoWithSyscall("sysctl(kinfo_file) (2/2)");
return NULL;
}

Expand Down Expand Up @@ -288,8 +288,19 @@ psutil_proc_num_fds(PyObject *self, PyObject *args) {
return NULL;

freep = kinfo_getfile(pid, &cnt);
if (freep == NULL)

if (freep == NULL) {
#if defined(PSUTIL_OPENBSD)
if ((pid == 0) && (errno == ESRCH)) {
psutil_debug(
"num_fds() returned ESRCH for PID 0; forcing `return 0`"
);
PyErr_Clear();
return Py_BuildValue("i", 0);
}
#endif
return NULL;
}

free(freep);
return Py_BuildValue("i", cnt);
Expand Down

0 comments on commit f65fe44

Please sign in to comment.