Skip to content

Commit 1ba3cf5

Browse files
committed
Fix #2675 / macOS: convert process status() to a meaningful value
1 parent df607b1 commit 1ba3cf5

File tree

2 files changed

+34
-1
lines changed

2 files changed

+34
-1
lines changed

HISTORY.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ XXXX-XX-XX
1717
- 2674_, [Windows]: `disk_usage()`_ could truncate values on 32-bit platforms,
1818
potentially reporting incorrect total/free/used space for drives larger than
1919
4GB.
20+
- 2675_, [macOS]: `Process.status()`_ incorrectly returns "running" for 99%
21+
of the processes.
2022

2123
7.1.2
2224
=====

psutil/arch/osx/proc.c

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,34 @@
3131
#include "../../arch/all/init.h"
3232

3333

34+
// macOS is apparently the only UNIX where the process "base" status
35+
// (running, idle, etc.) is unreliable and must be guessed from flags:
36+
// https://github.com/giampaolo/psutil/issues/2675
37+
static int
38+
convert_status(struct extern_proc *p, struct eproc *e) {
39+
int flag = p->p_flag;
40+
int eflag = e->e_flag;
41+
42+
// zombies and stopped
43+
if (p->p_stat == SZOMB)
44+
return SZOMB;
45+
if (p->p_stat == SSTOP)
46+
return SSTOP;
47+
48+
if (flag & P_SYSTEM)
49+
return SIDL; // system idle
50+
if (flag & P_WEXIT)
51+
return SIDL; // waiting to exit
52+
if (flag & P_PPWAIT)
53+
return SIDL; // parent waiting
54+
if (eflag & EPROC_SLEADER)
55+
return SSLEEP; // session leader treated as sleeping
56+
57+
// Default: 99% is SRUN (running)
58+
return p->p_stat;
59+
}
60+
61+
3462
/*
3563
* Return multiple process info as a Python tuple in one shot by
3664
* using sysctl() and filling up a kinfo_proc struct.
@@ -42,6 +70,7 @@
4270
PyObject *
4371
psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
4472
pid_t pid;
73+
int status;
4574
struct kinfo_proc kp;
4675
PyObject *py_name = NULL;
4776
PyObject *py_retlist = NULL;
@@ -60,6 +89,8 @@ psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
6089
py_name = Py_None;
6190
}
6291

92+
status = convert_status(&kp.kp_proc, &kp.kp_eproc);
93+
6394
py_retlist = Py_BuildValue(
6495
_Py_PARSE_PID "llllllldiO",
6596
kp.kp_eproc.e_ppid, // (pid_t) ppid
@@ -71,7 +102,7 @@ psutil_proc_kinfo_oneshot(PyObject *self, PyObject *args) {
71102
(long)kp.kp_eproc.e_pcred.p_svgid, // (long) saved gid
72103
(long long)kp.kp_eproc.e_tdev, // (long long) tty nr
73104
PSUTIL_TV2DOUBLE(kp.kp_proc.p_starttime), // (double) create time
74-
(int)kp.kp_proc.p_stat, // (int) status
105+
status, // (int) status
75106
py_name // (pystr) name
76107
);
77108

0 commit comments

Comments
 (0)