Mercurial > repos > guerler > springsuite
comparison planemo/lib/python3.7/site-packages/psutil/_psosx.py @ 1:56ad4e20f292 draft
"planemo upload commit 6eee67778febed82ddd413c3ca40b3183a3898f1"
| author | guerler |
|---|---|
| date | Fri, 31 Jul 2020 00:32:28 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 0:d30785e31577 | 1:56ad4e20f292 |
|---|---|
| 1 # Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. | |
| 2 # Use of this source code is governed by a BSD-style license that can be | |
| 3 # found in the LICENSE file. | |
| 4 | |
| 5 """macOS platform implementation.""" | |
| 6 | |
| 7 import contextlib | |
| 8 import errno | |
| 9 import functools | |
| 10 import os | |
| 11 from collections import namedtuple | |
| 12 | |
| 13 from . import _common | |
| 14 from . import _psposix | |
| 15 from . import _psutil_osx as cext | |
| 16 from . import _psutil_posix as cext_posix | |
| 17 from ._common import AccessDenied | |
| 18 from ._common import conn_tmap | |
| 19 from ._common import conn_to_ntuple | |
| 20 from ._common import isfile_strict | |
| 21 from ._common import memoize_when_activated | |
| 22 from ._common import NoSuchProcess | |
| 23 from ._common import parse_environ_block | |
| 24 from ._common import usage_percent | |
| 25 from ._common import ZombieProcess | |
| 26 from ._compat import PermissionError | |
| 27 from ._compat import ProcessLookupError | |
| 28 | |
| 29 | |
| 30 __extra__all__ = [] | |
| 31 | |
| 32 | |
| 33 # ===================================================================== | |
| 34 # --- globals | |
| 35 # ===================================================================== | |
| 36 | |
| 37 | |
| 38 PAGESIZE = os.sysconf("SC_PAGE_SIZE") | |
| 39 AF_LINK = cext_posix.AF_LINK | |
| 40 | |
| 41 TCP_STATUSES = { | |
| 42 cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, | |
| 43 cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, | |
| 44 cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, | |
| 45 cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, | |
| 46 cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, | |
| 47 cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, | |
| 48 cext.TCPS_CLOSED: _common.CONN_CLOSE, | |
| 49 cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, | |
| 50 cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, | |
| 51 cext.TCPS_LISTEN: _common.CONN_LISTEN, | |
| 52 cext.TCPS_CLOSING: _common.CONN_CLOSING, | |
| 53 cext.PSUTIL_CONN_NONE: _common.CONN_NONE, | |
| 54 } | |
| 55 | |
| 56 PROC_STATUSES = { | |
| 57 cext.SIDL: _common.STATUS_IDLE, | |
| 58 cext.SRUN: _common.STATUS_RUNNING, | |
| 59 cext.SSLEEP: _common.STATUS_SLEEPING, | |
| 60 cext.SSTOP: _common.STATUS_STOPPED, | |
| 61 cext.SZOMB: _common.STATUS_ZOMBIE, | |
| 62 } | |
| 63 | |
| 64 kinfo_proc_map = dict( | |
| 65 ppid=0, | |
| 66 ruid=1, | |
| 67 euid=2, | |
| 68 suid=3, | |
| 69 rgid=4, | |
| 70 egid=5, | |
| 71 sgid=6, | |
| 72 ttynr=7, | |
| 73 ctime=8, | |
| 74 status=9, | |
| 75 name=10, | |
| 76 ) | |
| 77 | |
| 78 pidtaskinfo_map = dict( | |
| 79 cpuutime=0, | |
| 80 cpustime=1, | |
| 81 rss=2, | |
| 82 vms=3, | |
| 83 pfaults=4, | |
| 84 pageins=5, | |
| 85 numthreads=6, | |
| 86 volctxsw=7, | |
| 87 ) | |
| 88 | |
| 89 | |
| 90 # ===================================================================== | |
| 91 # --- named tuples | |
| 92 # ===================================================================== | |
| 93 | |
| 94 | |
| 95 # psutil.cpu_times() | |
| 96 scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) | |
| 97 # psutil.virtual_memory() | |
| 98 svmem = namedtuple( | |
| 99 'svmem', ['total', 'available', 'percent', 'used', 'free', | |
| 100 'active', 'inactive', 'wired']) | |
| 101 # psutil.Process.memory_info() | |
| 102 pmem = namedtuple('pmem', ['rss', 'vms', 'pfaults', 'pageins']) | |
| 103 # psutil.Process.memory_full_info() | |
| 104 pfullmem = namedtuple('pfullmem', pmem._fields + ('uss', )) | |
| 105 | |
| 106 | |
| 107 # ===================================================================== | |
| 108 # --- memory | |
| 109 # ===================================================================== | |
| 110 | |
| 111 | |
| 112 def virtual_memory(): | |
| 113 """System virtual memory as a namedtuple.""" | |
| 114 total, active, inactive, wired, free, speculative = cext.virtual_mem() | |
| 115 # This is how Zabbix calculate avail and used mem: | |
| 116 # https://github.com/zabbix/zabbix/blob/trunk/src/libs/zbxsysinfo/ | |
| 117 # osx/memory.c | |
| 118 # Also see: https://github.com/giampaolo/psutil/issues/1277 | |
| 119 avail = inactive + free | |
| 120 used = active + wired | |
| 121 # This is NOT how Zabbix calculates free mem but it matches "free" | |
| 122 # cmdline utility. | |
| 123 free -= speculative | |
| 124 percent = usage_percent((total - avail), total, round_=1) | |
| 125 return svmem(total, avail, percent, used, free, | |
| 126 active, inactive, wired) | |
| 127 | |
| 128 | |
| 129 def swap_memory(): | |
| 130 """Swap system memory as a (total, used, free, sin, sout) tuple.""" | |
| 131 total, used, free, sin, sout = cext.swap_mem() | |
| 132 percent = usage_percent(used, total, round_=1) | |
| 133 return _common.sswap(total, used, free, percent, sin, sout) | |
| 134 | |
| 135 | |
| 136 # ===================================================================== | |
| 137 # --- CPU | |
| 138 # ===================================================================== | |
| 139 | |
| 140 | |
| 141 def cpu_times(): | |
| 142 """Return system CPU times as a namedtuple.""" | |
| 143 user, nice, system, idle = cext.cpu_times() | |
| 144 return scputimes(user, nice, system, idle) | |
| 145 | |
| 146 | |
| 147 def per_cpu_times(): | |
| 148 """Return system CPU times as a named tuple""" | |
| 149 ret = [] | |
| 150 for cpu_t in cext.per_cpu_times(): | |
| 151 user, nice, system, idle = cpu_t | |
| 152 item = scputimes(user, nice, system, idle) | |
| 153 ret.append(item) | |
| 154 return ret | |
| 155 | |
| 156 | |
| 157 def cpu_count_logical(): | |
| 158 """Return the number of logical CPUs in the system.""" | |
| 159 return cext.cpu_count_logical() | |
| 160 | |
| 161 | |
| 162 def cpu_count_physical(): | |
| 163 """Return the number of physical CPUs in the system.""" | |
| 164 return cext.cpu_count_phys() | |
| 165 | |
| 166 | |
| 167 def cpu_stats(): | |
| 168 ctx_switches, interrupts, soft_interrupts, syscalls, traps = \ | |
| 169 cext.cpu_stats() | |
| 170 return _common.scpustats( | |
| 171 ctx_switches, interrupts, soft_interrupts, syscalls) | |
| 172 | |
| 173 | |
| 174 def cpu_freq(): | |
| 175 """Return CPU frequency. | |
| 176 On macOS per-cpu frequency is not supported. | |
| 177 Also, the returned frequency never changes, see: | |
| 178 https://arstechnica.com/civis/viewtopic.php?f=19&t=465002 | |
| 179 """ | |
| 180 curr, min_, max_ = cext.cpu_freq() | |
| 181 return [_common.scpufreq(curr, min_, max_)] | |
| 182 | |
| 183 | |
| 184 # ===================================================================== | |
| 185 # --- disks | |
| 186 # ===================================================================== | |
| 187 | |
| 188 | |
| 189 disk_usage = _psposix.disk_usage | |
| 190 disk_io_counters = cext.disk_io_counters | |
| 191 | |
| 192 | |
| 193 def disk_partitions(all=False): | |
| 194 """Return mounted disk partitions as a list of namedtuples.""" | |
| 195 retlist = [] | |
| 196 partitions = cext.disk_partitions() | |
| 197 for partition in partitions: | |
| 198 device, mountpoint, fstype, opts = partition | |
| 199 if device == 'none': | |
| 200 device = '' | |
| 201 if not all: | |
| 202 if not os.path.isabs(device) or not os.path.exists(device): | |
| 203 continue | |
| 204 ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) | |
| 205 retlist.append(ntuple) | |
| 206 return retlist | |
| 207 | |
| 208 | |
| 209 # ===================================================================== | |
| 210 # --- sensors | |
| 211 # ===================================================================== | |
| 212 | |
| 213 | |
| 214 def sensors_battery(): | |
| 215 """Return battery information.""" | |
| 216 try: | |
| 217 percent, minsleft, power_plugged = cext.sensors_battery() | |
| 218 except NotImplementedError: | |
| 219 # no power source - return None according to interface | |
| 220 return None | |
| 221 power_plugged = power_plugged == 1 | |
| 222 if power_plugged: | |
| 223 secsleft = _common.POWER_TIME_UNLIMITED | |
| 224 elif minsleft == -1: | |
| 225 secsleft = _common.POWER_TIME_UNKNOWN | |
| 226 else: | |
| 227 secsleft = minsleft * 60 | |
| 228 return _common.sbattery(percent, secsleft, power_plugged) | |
| 229 | |
| 230 | |
| 231 # ===================================================================== | |
| 232 # --- network | |
| 233 # ===================================================================== | |
| 234 | |
| 235 | |
| 236 net_io_counters = cext.net_io_counters | |
| 237 net_if_addrs = cext_posix.net_if_addrs | |
| 238 | |
| 239 | |
| 240 def net_connections(kind='inet'): | |
| 241 """System-wide network connections.""" | |
| 242 # Note: on macOS this will fail with AccessDenied unless | |
| 243 # the process is owned by root. | |
| 244 ret = [] | |
| 245 for pid in pids(): | |
| 246 try: | |
| 247 cons = Process(pid).connections(kind) | |
| 248 except NoSuchProcess: | |
| 249 continue | |
| 250 else: | |
| 251 if cons: | |
| 252 for c in cons: | |
| 253 c = list(c) + [pid] | |
| 254 ret.append(_common.sconn(*c)) | |
| 255 return ret | |
| 256 | |
| 257 | |
| 258 def net_if_stats(): | |
| 259 """Get NIC stats (isup, duplex, speed, mtu).""" | |
| 260 names = net_io_counters().keys() | |
| 261 ret = {} | |
| 262 for name in names: | |
| 263 try: | |
| 264 mtu = cext_posix.net_if_mtu(name) | |
| 265 isup = cext_posix.net_if_flags(name) | |
| 266 duplex, speed = cext_posix.net_if_duplex_speed(name) | |
| 267 except OSError as err: | |
| 268 # https://github.com/giampaolo/psutil/issues/1279 | |
| 269 if err.errno != errno.ENODEV: | |
| 270 raise | |
| 271 else: | |
| 272 if hasattr(_common, 'NicDuplex'): | |
| 273 duplex = _common.NicDuplex(duplex) | |
| 274 ret[name] = _common.snicstats(isup, duplex, speed, mtu) | |
| 275 return ret | |
| 276 | |
| 277 | |
| 278 # ===================================================================== | |
| 279 # --- other system functions | |
| 280 # ===================================================================== | |
| 281 | |
| 282 | |
| 283 def boot_time(): | |
| 284 """The system boot time expressed in seconds since the epoch.""" | |
| 285 return cext.boot_time() | |
| 286 | |
| 287 | |
| 288 def users(): | |
| 289 """Return currently connected users as a list of namedtuples.""" | |
| 290 retlist = [] | |
| 291 rawlist = cext.users() | |
| 292 for item in rawlist: | |
| 293 user, tty, hostname, tstamp, pid = item | |
| 294 if tty == '~': | |
| 295 continue # reboot or shutdown | |
| 296 if not tstamp: | |
| 297 continue | |
| 298 nt = _common.suser(user, tty or None, hostname or None, tstamp, pid) | |
| 299 retlist.append(nt) | |
| 300 return retlist | |
| 301 | |
| 302 | |
| 303 # ===================================================================== | |
| 304 # --- processes | |
| 305 # ===================================================================== | |
| 306 | |
| 307 | |
| 308 def pids(): | |
| 309 ls = cext.pids() | |
| 310 if 0 not in ls: | |
| 311 # On certain macOS versions pids() C doesn't return PID 0 but | |
| 312 # "ps" does and the process is querable via sysctl(): | |
| 313 # https://travis-ci.org/giampaolo/psutil/jobs/309619941 | |
| 314 try: | |
| 315 Process(0).create_time() | |
| 316 ls.insert(0, 0) | |
| 317 except NoSuchProcess: | |
| 318 pass | |
| 319 except AccessDenied: | |
| 320 ls.insert(0, 0) | |
| 321 return ls | |
| 322 | |
| 323 | |
| 324 pid_exists = _psposix.pid_exists | |
| 325 | |
| 326 | |
| 327 def is_zombie(pid): | |
| 328 try: | |
| 329 st = cext.proc_kinfo_oneshot(pid)[kinfo_proc_map['status']] | |
| 330 return st == cext.SZOMB | |
| 331 except Exception: | |
| 332 return False | |
| 333 | |
| 334 | |
| 335 def wrap_exceptions(fun): | |
| 336 """Decorator which translates bare OSError exceptions into | |
| 337 NoSuchProcess and AccessDenied. | |
| 338 """ | |
| 339 @functools.wraps(fun) | |
| 340 def wrapper(self, *args, **kwargs): | |
| 341 try: | |
| 342 return fun(self, *args, **kwargs) | |
| 343 except ProcessLookupError: | |
| 344 if is_zombie(self.pid): | |
| 345 raise ZombieProcess(self.pid, self._name, self._ppid) | |
| 346 else: | |
| 347 raise NoSuchProcess(self.pid, self._name) | |
| 348 except PermissionError: | |
| 349 raise AccessDenied(self.pid, self._name) | |
| 350 except cext.ZombieProcessError: | |
| 351 raise ZombieProcess(self.pid, self._name, self._ppid) | |
| 352 return wrapper | |
| 353 | |
| 354 | |
| 355 @contextlib.contextmanager | |
| 356 def catch_zombie(proc): | |
| 357 """There are some poor C APIs which incorrectly raise ESRCH when | |
| 358 the process is still alive or it's a zombie, or even RuntimeError | |
| 359 (those who don't set errno). This is here in order to solve: | |
| 360 https://github.com/giampaolo/psutil/issues/1044 | |
| 361 """ | |
| 362 try: | |
| 363 yield | |
| 364 except (OSError, RuntimeError) as err: | |
| 365 if isinstance(err, RuntimeError) or err.errno == errno.ESRCH: | |
| 366 try: | |
| 367 # status() is not supposed to lie and correctly detect | |
| 368 # zombies so if it raises ESRCH it's true. | |
| 369 status = proc.status() | |
| 370 except NoSuchProcess: | |
| 371 raise err | |
| 372 else: | |
| 373 if status == _common.STATUS_ZOMBIE: | |
| 374 raise ZombieProcess(proc.pid, proc._name, proc._ppid) | |
| 375 else: | |
| 376 raise AccessDenied(proc.pid, proc._name) | |
| 377 else: | |
| 378 raise | |
| 379 | |
| 380 | |
| 381 class Process(object): | |
| 382 """Wrapper class around underlying C implementation.""" | |
| 383 | |
| 384 __slots__ = ["pid", "_name", "_ppid", "_cache"] | |
| 385 | |
| 386 def __init__(self, pid): | |
| 387 self.pid = pid | |
| 388 self._name = None | |
| 389 self._ppid = None | |
| 390 | |
| 391 @wrap_exceptions | |
| 392 @memoize_when_activated | |
| 393 def _get_kinfo_proc(self): | |
| 394 # Note: should work with all PIDs without permission issues. | |
| 395 ret = cext.proc_kinfo_oneshot(self.pid) | |
| 396 assert len(ret) == len(kinfo_proc_map) | |
| 397 return ret | |
| 398 | |
| 399 @wrap_exceptions | |
| 400 @memoize_when_activated | |
| 401 def _get_pidtaskinfo(self): | |
| 402 # Note: should work for PIDs owned by user only. | |
| 403 with catch_zombie(self): | |
| 404 ret = cext.proc_pidtaskinfo_oneshot(self.pid) | |
| 405 assert len(ret) == len(pidtaskinfo_map) | |
| 406 return ret | |
| 407 | |
| 408 def oneshot_enter(self): | |
| 409 self._get_kinfo_proc.cache_activate(self) | |
| 410 self._get_pidtaskinfo.cache_activate(self) | |
| 411 | |
| 412 def oneshot_exit(self): | |
| 413 self._get_kinfo_proc.cache_deactivate(self) | |
| 414 self._get_pidtaskinfo.cache_deactivate(self) | |
| 415 | |
| 416 @wrap_exceptions | |
| 417 def name(self): | |
| 418 name = self._get_kinfo_proc()[kinfo_proc_map['name']] | |
| 419 return name if name is not None else cext.proc_name(self.pid) | |
| 420 | |
| 421 @wrap_exceptions | |
| 422 def exe(self): | |
| 423 with catch_zombie(self): | |
| 424 return cext.proc_exe(self.pid) | |
| 425 | |
| 426 @wrap_exceptions | |
| 427 def cmdline(self): | |
| 428 with catch_zombie(self): | |
| 429 return cext.proc_cmdline(self.pid) | |
| 430 | |
| 431 @wrap_exceptions | |
| 432 def environ(self): | |
| 433 with catch_zombie(self): | |
| 434 return parse_environ_block(cext.proc_environ(self.pid)) | |
| 435 | |
| 436 @wrap_exceptions | |
| 437 def ppid(self): | |
| 438 self._ppid = self._get_kinfo_proc()[kinfo_proc_map['ppid']] | |
| 439 return self._ppid | |
| 440 | |
| 441 @wrap_exceptions | |
| 442 def cwd(self): | |
| 443 with catch_zombie(self): | |
| 444 return cext.proc_cwd(self.pid) | |
| 445 | |
| 446 @wrap_exceptions | |
| 447 def uids(self): | |
| 448 rawtuple = self._get_kinfo_proc() | |
| 449 return _common.puids( | |
| 450 rawtuple[kinfo_proc_map['ruid']], | |
| 451 rawtuple[kinfo_proc_map['euid']], | |
| 452 rawtuple[kinfo_proc_map['suid']]) | |
| 453 | |
| 454 @wrap_exceptions | |
| 455 def gids(self): | |
| 456 rawtuple = self._get_kinfo_proc() | |
| 457 return _common.puids( | |
| 458 rawtuple[kinfo_proc_map['rgid']], | |
| 459 rawtuple[kinfo_proc_map['egid']], | |
| 460 rawtuple[kinfo_proc_map['sgid']]) | |
| 461 | |
| 462 @wrap_exceptions | |
| 463 def terminal(self): | |
| 464 tty_nr = self._get_kinfo_proc()[kinfo_proc_map['ttynr']] | |
| 465 tmap = _psposix.get_terminal_map() | |
| 466 try: | |
| 467 return tmap[tty_nr] | |
| 468 except KeyError: | |
| 469 return None | |
| 470 | |
| 471 @wrap_exceptions | |
| 472 def memory_info(self): | |
| 473 rawtuple = self._get_pidtaskinfo() | |
| 474 return pmem( | |
| 475 rawtuple[pidtaskinfo_map['rss']], | |
| 476 rawtuple[pidtaskinfo_map['vms']], | |
| 477 rawtuple[pidtaskinfo_map['pfaults']], | |
| 478 rawtuple[pidtaskinfo_map['pageins']], | |
| 479 ) | |
| 480 | |
| 481 @wrap_exceptions | |
| 482 def memory_full_info(self): | |
| 483 basic_mem = self.memory_info() | |
| 484 uss = cext.proc_memory_uss(self.pid) | |
| 485 return pfullmem(*basic_mem + (uss, )) | |
| 486 | |
| 487 @wrap_exceptions | |
| 488 def cpu_times(self): | |
| 489 rawtuple = self._get_pidtaskinfo() | |
| 490 return _common.pcputimes( | |
| 491 rawtuple[pidtaskinfo_map['cpuutime']], | |
| 492 rawtuple[pidtaskinfo_map['cpustime']], | |
| 493 # children user / system times are not retrievable (set to 0) | |
| 494 0.0, 0.0) | |
| 495 | |
| 496 @wrap_exceptions | |
| 497 def create_time(self): | |
| 498 return self._get_kinfo_proc()[kinfo_proc_map['ctime']] | |
| 499 | |
| 500 @wrap_exceptions | |
| 501 def num_ctx_switches(self): | |
| 502 # Unvoluntary value seems not to be available; | |
| 503 # getrusage() numbers seems to confirm this theory. | |
| 504 # We set it to 0. | |
| 505 vol = self._get_pidtaskinfo()[pidtaskinfo_map['volctxsw']] | |
| 506 return _common.pctxsw(vol, 0) | |
| 507 | |
| 508 @wrap_exceptions | |
| 509 def num_threads(self): | |
| 510 return self._get_pidtaskinfo()[pidtaskinfo_map['numthreads']] | |
| 511 | |
| 512 @wrap_exceptions | |
| 513 def open_files(self): | |
| 514 if self.pid == 0: | |
| 515 return [] | |
| 516 files = [] | |
| 517 with catch_zombie(self): | |
| 518 rawlist = cext.proc_open_files(self.pid) | |
| 519 for path, fd in rawlist: | |
| 520 if isfile_strict(path): | |
| 521 ntuple = _common.popenfile(path, fd) | |
| 522 files.append(ntuple) | |
| 523 return files | |
| 524 | |
| 525 @wrap_exceptions | |
| 526 def connections(self, kind='inet'): | |
| 527 if kind not in conn_tmap: | |
| 528 raise ValueError("invalid %r kind argument; choose between %s" | |
| 529 % (kind, ', '.join([repr(x) for x in conn_tmap]))) | |
| 530 families, types = conn_tmap[kind] | |
| 531 with catch_zombie(self): | |
| 532 rawlist = cext.proc_connections(self.pid, families, types) | |
| 533 ret = [] | |
| 534 for item in rawlist: | |
| 535 fd, fam, type, laddr, raddr, status = item | |
| 536 nt = conn_to_ntuple(fd, fam, type, laddr, raddr, status, | |
| 537 TCP_STATUSES) | |
| 538 ret.append(nt) | |
| 539 return ret | |
| 540 | |
| 541 @wrap_exceptions | |
| 542 def num_fds(self): | |
| 543 if self.pid == 0: | |
| 544 return 0 | |
| 545 with catch_zombie(self): | |
| 546 return cext.proc_num_fds(self.pid) | |
| 547 | |
| 548 @wrap_exceptions | |
| 549 def wait(self, timeout=None): | |
| 550 return _psposix.wait_pid(self.pid, timeout, self._name) | |
| 551 | |
| 552 @wrap_exceptions | |
| 553 def nice_get(self): | |
| 554 with catch_zombie(self): | |
| 555 return cext_posix.getpriority(self.pid) | |
| 556 | |
| 557 @wrap_exceptions | |
| 558 def nice_set(self, value): | |
| 559 with catch_zombie(self): | |
| 560 return cext_posix.setpriority(self.pid, value) | |
| 561 | |
| 562 @wrap_exceptions | |
| 563 def status(self): | |
| 564 code = self._get_kinfo_proc()[kinfo_proc_map['status']] | |
| 565 # XXX is '?' legit? (we're not supposed to return it anyway) | |
| 566 return PROC_STATUSES.get(code, '?') | |
| 567 | |
| 568 @wrap_exceptions | |
| 569 def threads(self): | |
| 570 rawlist = cext.proc_threads(self.pid) | |
| 571 retlist = [] | |
| 572 for thread_id, utime, stime in rawlist: | |
| 573 ntuple = _common.pthread(thread_id, utime, stime) | |
| 574 retlist.append(ntuple) | |
| 575 return retlist |
