diff --git a/psutil/__init__.py b/psutil/__init__.py index 006d5f57f..aef3f45ff 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -911,13 +911,15 @@ def num_threads(self): """Return the number of threads used by this process.""" return self._proc.num_threads() - def threads(self): - """Return threads opened by process as a list of - (id, user_time, system_time) namedtuples representing - thread id and thread CPU times (user/system). - On OpenBSD this method requires root access. - """ - return self._proc.threads() + if hasattr(_psplatform.Process, "threads"): + + def threads(self): + """Return threads opened by process as a list of + (id, user_time, system_time) namedtuples representing + thread id and thread CPU times (user/system). + On OpenBSD this method requires root access. + """ + return self._proc.threads() @_assert_pid_not_reused def children(self, recursive=False): diff --git a/psutil/_psaix.py b/psutil/_psaix.py index 663748bb8..d06dc9c27 100644 --- a/psutil/_psaix.py +++ b/psutil/_psaix.py @@ -38,6 +38,8 @@ # ===================================================================== +HAS_THREADS = hasattr(cext, "proc_threads") + PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') AF_LINK = cext_posix.AF_LINK @@ -427,22 +429,23 @@ def create_time(self): def num_threads(self): return self._proc_basic_info()[proc_info_map['num_threads']] - @wrap_exceptions - def threads(self): - rawlist = cext.proc_threads(self.pid) - retlist = [] - for thread_id, utime, stime in rawlist: - ntuple = _common.pthread(thread_id, utime, stime) - retlist.append(ntuple) - # The underlying C implementation retrieves all OS threads - # and filters them by PID. At this point we can't tell whether - # an empty list means there were no connections for process or - # process is no longer active so we force NSP in case the PID - # is no longer there. - if not retlist: - # will raise NSP if process is gone - os.stat('%s/%s' % (self._procfs_path, self.pid)) - return retlist + if HAS_THREADS: + @wrap_exceptions + def threads(self): + rawlist = cext.proc_threads(self.pid) + retlist = [] + for thread_id, utime, stime in rawlist: + ntuple = _common.pthread(thread_id, utime, stime) + retlist.append(ntuple) + # The underlying C implementation retrieves all OS threads + # and filters them by PID. At this point we can't tell whether + # an empty list means there were no connections for process or + # process is no longer active so we force NSP in case the PID + # is no longer there. + if not retlist: + # will raise NSP if process is gone + os.stat('%s/%s' % (self._procfs_path, self.pid)) + return retlist @wrap_exceptions def connections(self, kind='inet'): diff --git a/psutil/_psutil_aix.c b/psutil/_psutil_aix.c index 52a14feb6..76ed736b2 100644 --- a/psutil/_psutil_aix.c +++ b/psutil/_psutil_aix.c @@ -157,6 +157,7 @@ psutil_proc_name_and_args(PyObject *self, PyObject *args) { } +#ifdef CURR_VERSION_THREAD /* * Retrieves all threads used by process returning a list of tuples * including thread id, user time and system time. @@ -222,6 +223,7 @@ psutil_proc_threads(PyObject *self, PyObject *args) { free(threadt); return NULL; } +#endif static PyObject * @@ -813,8 +815,10 @@ PsutilMethods[] = "Return process user and system CPU times."}, {"proc_cred", psutil_proc_cred, METH_VARARGS, "Return process uids/gids."}, +#ifdef CURR_VERSION_THREAD {"proc_threads", psutil_proc_threads, METH_VARARGS, "Return process threads"}, +#endif {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, "Get process I/O counters."}, diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index 86930100e..1d109af0e 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -160,6 +160,7 @@ HAS_NUM_CTX_SWITCHES = hasattr(psutil.Process, "num_ctx_switches") HAS_PROC_CPU_NUM = hasattr(psutil.Process, "cpu_num") HAS_RLIMIT = hasattr(psutil.Process, "rlimit") +HAS_THREADS = hasattr(psutil.Process, "threads") HAS_SENSORS_BATTERY = hasattr(psutil, "sensors_battery") HAS_BATTERY = HAS_SENSORS_BATTERY and psutil.sensors_battery() HAS_SENSORS_FANS = hasattr(psutil, "sensors_fans") diff --git a/psutil/tests/test_process.py b/psutil/tests/test_process.py index fa07f5a92..3eeaa7c3e 100755 --- a/psutil/tests/test_process.py +++ b/psutil/tests/test_process.py @@ -49,6 +49,7 @@ from psutil.tests import HAS_PROC_CPU_NUM from psutil.tests import HAS_PROC_IO_COUNTERS from psutil.tests import HAS_RLIMIT +from psutil.tests import HAS_THREADS from psutil.tests import mock from psutil.tests import PYPY from psutil.tests import PYTHON @@ -528,6 +529,7 @@ def test_num_handles(self): p = psutil.Process() self.assertGreater(p.num_handles(), 0) + @unittest.skipIf(not HAS_THREADS, 'not supported') def test_threads(self): p = psutil.Process() if OPENBSD: @@ -552,6 +554,7 @@ def test_threads(self): @retry_before_failing() @skip_on_access_denied(only_if=OSX) + @unittest.skipIf(not HAS_THREADS, 'not supported') def test_threads_2(self): sproc = get_test_subprocess() p = psutil.Process(sproc.pid)