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.
4270PyObject *
4371psutil_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