diff options
author | Thomas Groman <tgroman@nuegia.net> | 2020-08-18 18:34:50 -0700 |
---|---|---|
committer | Thomas Groman <tgroman@nuegia.net> | 2020-08-18 18:34:50 -0700 |
commit | aaeaf52308b698084c978636b4f56f87d0603f49 (patch) | |
tree | 8826aa80c51640a1fa2725e33cfc6df8cd742ffb /python/psutil | |
parent | aa24b8998bee5b3fe1f49f0edebedf92a0ae7af8 (diff) | |
download | UXP-aaeaf52308b698084c978636b4f56f87d0603f49.tar UXP-aaeaf52308b698084c978636b4f56f87d0603f49.tar.gz UXP-aaeaf52308b698084c978636b4f56f87d0603f49.tar.lz UXP-aaeaf52308b698084c978636b4f56f87d0603f49.tar.xz UXP-aaeaf52308b698084c978636b4f56f87d0603f49.zip |
replace psutil with git submodule and bring it up to date
Diffstat (limited to 'python/psutil')
91 files changed, 0 insertions, 30418 deletions
diff --git a/python/psutil b/python/psutil new file mode 160000 +Subproject a0967043b5819b2edc61d9a12306289d5e7f98c diff --git a/python/psutil/CREDITS b/python/psutil/CREDITS deleted file mode 100644 index 170751b0a..000000000 --- a/python/psutil/CREDITS +++ /dev/null @@ -1,310 +0,0 @@ -Intro -===== - -I would like to recognize some of the people who have been instrumental in the -development of psutil. -I'm sure I'm forgetting some people (feel free to email me), but here is a -short list. -It's modeled after the Linux CREDITS file where the fields are: -name (N), e-mail (E), web-address (W), country (C), description (D), (I) issues -(issue tracker is at https://github.com/giampaolo/psutil/issues). -Really thanks to all of you. - -- Giampaolo - -Author -====== - -N: Giampaolo Rodola' -C: Italy -E: g.rodola@gmail.com -W: http://grodola.blogspot.com/ - -Contributors -============ - -N: Jay Loden -C: NJ, USA -E: jloden@gmail.com -D: original co-author, initial design/bootstrap and occasional bug fixes -W: http://www.jayloden.com - -N: Jeremy Whitlock -E: jcscoobyrs@gmail.com -D: great help with OSX C development. -I: 125, 150, 174, 206 - -N: wj32 -E: wj32.64@gmail.com -D: process username() and get_connections() on Windows -I: 114, 115 - -N: Yan Raber -C: Bologna, Italy -E: yanraber@gmail.com -D: help on Windows development (initial version of Process.username()) - -N: Justin Venus -E: justin.venus@gmail.com -D: Solaris support -I: 18 - -N: Dave Daeschler -C: USA -E: david.daeschler@gmail.com -W: http://daviddaeschler.com -D: some contributions to initial design/bootstrap plus occasional bug fixing -I: 522, 536 - -N: cjgohlke -E: cjgohlke@gmail.com -D: Windows 64 bit support -I: 107 - -N: Jeffery Kline -E: jeffery.kline@gmail.com -I: 130 - -N: Grabriel Monnerat -E: gabrielmonnerat@gmail.com -I: 146 - -N: Philip Roberts -E: philip.roberts@gmail.com -I: 168 - -N: jcscoobyrs -E: jcscoobyrs@gmail.com -I: 125 - -N: Sandro Tosi -E: sandro.tosi@gmail.com -I: 200, 201 - -N: Andrew Colin -E: andrew.colin@gmail.com -I: 248 - -N: Amoser -E: amoser@google.com -I: 266, 267, 340 - -N: Matthew Grant -E: matthewgrant5@gmail.com -I: 271 - -N: oweidner -E: oweidner@cct.lsu.edu -I: 275 - -N: Tarek Ziade -E: ziade.tarek -I: 281 - -N: Luca Cipriani -C: Turin, Italy -E: luca.opensource@gmail.com -I: 278 - -N: Maciej Lach, -E: maciej.lach@gmail.com -I: 294 - -N: James Pye -E: james.pye@gmail.com -I: 305, 306 - -N: Stanchev Emil -E: stanchev.emil -I: 314 - -N: Kim Gräsman -E: kim.grasman@gmail.com -D: ...also kindly donated some money. -I: 316 - -N: Riccardo Murri -C: Italy -I: 318 - -N: Florent Xicluna -E: florent.xicluna@gmail.com -I: 319 - -N: Michal Spondr -E: michal.spondr -I: 313 - -N: Jean Sebastien -E: dumbboules@gmail.com -I: 344 - -N: Rob Smith -W: http://www.kormoc.com/ -I: 341 - -N: Youngsik Kim -W: https://plus.google.com/101320747613749824490/ -I: 317 - -N: Gregory Szorc -W: https://plus.google.com/116873264322260110710/posts -I: 323 - -N: André Oriani -E: aoriani@gmail.com -I: 361 - -N: clackwell -E: clackwell@gmail.com -I: 356 - -N: m.malycha -E: m.malycha@gmail.com -I: 351 - -N: John Baldwin -E: jhb@FreeBSD.org -I: 370 - -N: Jan Beich -E: jbeich@tormail.org -I: 325 - -N: floppymaster -E: floppymaster@gmail.com -I: 380 - -N: Arfrever.FTA -E: Arfrever.FTA@gmail.com -I: 369, 404 - -N: danudey -E: danudey@gmail.com -I: 386 - -N: Adrien Fallou -I: 224 - -N: Gisle Vanem -E: gisle.vanem@gmail.com -I: 411 - -N: thepyr0 -E: thepyr0@gmail.com -I: 414 - -N: John Pankov -E: john.pankov@gmail.com -I: 435 - -N: Matt Good -W: http://matt-good.net/ -I: 438 - -N: Ulrich Klank -E: ulrich.klank@scitics.de -I: 448 - -N: Josiah Carlson -E: josiah.carlson@gmail.com -I: 451, 452 - -N: Raymond Hettinger -D: namedtuple and lru_cache backward compatible implementations. - -N: Jason Kirtland -D: backward compatible implementation of collections.defaultdict. - -M: Ken Seeho -D: @cached_property decorator - -N: crusaderky -E: crusaderky@gmail.com -I: 470, 477 - -E: alex@mroja.net -I: 471 - -N: Gautam Singh -E: gautam.singh@gmail.com -I: 466 - -E: lhn@hupfeldtit.dk -I: 476, 479 - -N: Francois Charron -E: francois.charron.1@gmail.com -I: 474 - -N: Naveed Roudsari -E: naveed.roudsari@gmail.com -I: 421 - -N: Alexander Grothe -E: Alexander.Grothe@gmail.com -I: 497 - -N: Szigeti Gabor Niif -E: szigeti.gabor.niif@gmail.com -I: 446 - -N: msabramo -E: msabramo@gmail.com -I: 492 - -N: Jeff Tang -W: https://github.com/mrjefftang -I: 340, 529, 616, 653, 654 - -N: Yaolong Huang -E: airekans@gmail.com -W: http://airekans.github.io/ -I: 530 - -N: Anders Chrigström -W: https://github.com/anders-chrigstrom -I: 496 - -N: spacewander -E: spacewanderlzx@gmail.com -I: 561 - -N: Sylvain Mouquet -E: sylvain.mouquet@gmail.com -I: 565 - -N: karthikrev -I: 568 - -N: Bruno Binet -E: bruno.binet@gmail.com -I: 572 - -N: Gabi Davar -C: Israel -W: https://github.com/mindw -I: 578, 581, 587 - -N: spacewanderlzx -C: Guangzhou,China -E: spacewanderlzx@gmail.com -I: 555 - -N: Fabian Groffen -I: 611, 618 - -N: desbma -W: https://github.com/desbma -C: France -I: 628 - -N: John Burnett -W: http://www.johnburnett.com/ -C: Irvine, CA, US -I: 614 - -N: Árni Már Jónsson -E: Reykjavik, Iceland -E: https://github.com/arnimarj -I: 634 diff --git a/python/psutil/HISTORY.rst b/python/psutil/HISTORY.rst deleted file mode 100644 index 12b985d1e..000000000 --- a/python/psutil/HISTORY.rst +++ /dev/null @@ -1,1018 +0,0 @@ -Bug tracker at https://github.com/giampaolo/psutil/issues - -3.1.1 - 2015-07-15 -================== - -**Bug fixes** - -- #645: [Linux] psutil.cpu_times_percent() may produce negative results. -- #656: 'from psutil import *' does not work. - - -3.1.0 - 2015-07-15 -================== - -**Enhancements** - -- #534: [Linux] disk_partitions() added support for ZFS filesystems. -- #646: continuous tests integration for Windows with - https://ci.appveyor.com/project/giampaolo/psutil. -- #647: new dev guide: - https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst -- #651: continuous code quality test integration with - https://scrutinizer-ci.com/g/giampaolo/psutil/ - -**Bug fixes** - -- #340: [Windows] Process.open_files() no longer hangs. Instead it uses a - thred which times out and skips the file handle in case it's taking too long - to be retrieved. (patch by Jeff Tang, PR #597) -- #627: [Windows] Process.name() no longer raises AccessDenied for pids owned - by another user. -- #636: [Windows] Process.memory_info() raise AccessDenied. -- #637: [UNIX] raise exception if trying to send signal to Process PID 0 as it - will affect os.getpid()'s process group instead of PID 0. -- #639: [Linux] Process.cmdline() can be truncated. -- #640: [Linux] *connections functions may swallow errors and return an - incomplete list of connnections. -- #642: repr() of exceptions is incorrect. -- #653: [Windows] Add inet_ntop function for Windows XP to support IPv6. -- #641: [Windows] Replace deprecated string functions with safe equivalents. - - -3.0.1 - 2015-06-18 -================== - -**Bug fixes** - -- #632: [Linux] better error message if cannot parse process UNIX connections. -- #634: [Linux] Proces.cmdline() does not include empty string arguments. -- #635: [UNIX] crash on module import if 'enum' package is installed on python - < 3.4. - - -3.0.0 - 2015-06-13 -================== - -**Enhancements** - -- #250: new psutil.net_if_stats() returning NIC statistics (isup, duplex, - speed, MTU). -- #376: new psutil.net_if_addrs() returning all NIC addresses a-la ifconfig. -- #469: on Python >= 3.4 ``IOPRIO_CLASS_*`` and ``*_PRIORITY_CLASS`` constants - returned by psutil.Process' ionice() and nice() methods are enums instead of - plain integers. -- #581: add .gitignore. (patch by Gabi Davar) -- #582: connection constants returned by psutil.net_connections() and - psutil.Process.connections() were turned from int to enums on Python > 3.4. -- #587: Move native extension into the package. -- #589: Process.cpu_affinity() accepts any kind of iterable (set, tuple, ...), - not only lists. -- #594: all deprecated APIs were removed. -- #599: [Windows] process name() can now be determined for all processes even - when running as a limited user. -- #602: pre-commit GIT hook. -- #629: enhanced support for py.test and nose test discovery and tests run. -- #616: [Windows] Add inet_ntop function for Windows XP. - -**Bug fixes** - -- #428: [all UNIXes except Linux] correct handling of zombie processes; - introduced new ZombieProcess exception class. -- #512: [BSD] fix segfault in net_connections(). -- #555: [Linux] psutil.users() correctly handles ":0" as an alias for - "localhost" -- #579: [Windows] Fixed open_files() for PID>64K. -- #579: [Windows] fixed many compiler warnings. -- #585: [FreeBSD] net_connections() may raise KeyError. -- #586: [FreeBSD] cpu_affinity() segfaults on set in case an invalid CPU - number is provided. -- #593: [FreeBSD] Process().memory_maps() segfaults. -- #606: Process.parent() may swallow NoSuchProcess exceptions. -- #611: [SunOS] net_io_counters has send and received swapped -- #614: [Linux]: cpu_count(logical=False) return the number of physical CPUs - instead of physical cores. -- #618: [SunOS] swap tests fail on Solaris when run as normal user -- #628: [Linux] Process.name() truncates process name in case it contains - spaces or parentheses. - - -2.2.1 - 2015-02-02 -================== - -**Bug fixes** - -- #496: [Linux] fix "ValueError: ambiguos inode with multiple PIDs references" - (patch by Bruno Binet) - - -2.2.0 - 2015-01-06 -================== - -**Enhancements** - -- #521: drop support for Python 2.4 and 2.5. -- #553: new examples/pstree.py script. -- #564: C extension version mismatch in case the user messed up with psutil - installation or with sys.path is now detected at import time. -- #568: New examples/pidof.py script. -- #569: [FreeBSD] add support for process CPU affinity. - -**Bug fixes** - -- #496: [Solaris] can't import psutil. -- #547: [UNIX] Process.username() may raise KeyError if UID can't be resolved. -- #551: [Windows] get rid of the unicode hack for net_io_counters() NIC names. -- #556: [Linux] lots of file handles were left open. -- #561: [Linux] net_connections() might skip some legitimate UNIX sockets. - (patch by spacewander) -- #565: [Windows] use proper encoding for psutil.Process.username() and - psutil.users(). (patch by Sylvain Mouquet) -- #567: [Linux] in the alternative implementation of CPU affinity PyList_Append - and Py_BuildValue return values are not checked. -- #569: [FreeBSD] fix memory leak in psutil.cpu_count(logical=False). -- #571: [Linux] Process.open_files() might swallow AccessDenied exceptions and - return an incomplete list of open files. - - -2.1.3 - 2014-09-26 -================== - -- #536: [Linux]: fix "undefined symbol: CPU_ALLOC" compilation error. - - -2.1.2 - 2014-09-21 -================== - -**Enhancements** - -- #407: project moved from Google Code to Github; code moved from Mercurial - to Git. -- #492: use tox to run tests on multiple python versions. (patch by msabramo) -- #505: [Windows] distribution as wheel packages. -- #511: new examples/ps.py sample code. - -**Bug fixes** - -- #340: [Windows] Process.get_open_files() no longer hangs. (patch by - Jeff Tang) -- #501: [Windows] disk_io_counters() may return negative values. -- #503: [Linux] in rare conditions Process exe(), open_files() and - connections() methods can raise OSError(ESRCH) instead of NoSuchProcess. -- #504: [Linux] can't build RPM packages via setup.py -- #506: [Linux] python 2.4 support was broken. -- #522: [Linux] Process.cpu_affinity() might return EINVAL. (patch by David - Daeschler) -- #529: [Windows] Process.exe() may raise unhandled WindowsError exception - for PIDs 0 and 4. (patch by Jeff Tang) -- #530: [Linux] psutil.disk_io_counters() may crash on old Linux distros - (< 2.6.5) (patch by Yaolong Huang) -- #533: [Linux] Process.memory_maps() may raise TypeError on old Linux distros. - - -2.1.1 - 2014-04-30 -================== - -**Bug fixes** - -- #446: [Windows] fix encoding error when using net_io_counters() on Python 3. - (patch by Szigeti Gabor Niif) -- #460: [Windows] net_io_counters() wraps after 4G. -- #491: [Linux] psutil.net_connections() exceptions. (patch by Alexander Grothe) - - -2.1.0 - 2014-04-08 -================== - -**Enhancements** - -- #387: system-wide open connections a-la netstat. - -**Bug fixes** - -- #421: [Solaris] psutil does not compile on SunOS 5.10 (patch by Naveed - Roudsari) -- #489: [Linux] psutil.disk_partitions() return an empty list. - - -2.0.0 - 2014-03-10 -================== - -**Enhancements** - -- #424: [Windows] installer for Python 3.X 64 bit. -- #427: number of logical and physical CPUs (psutil.cpu_count()). -- #447: psutil.wait_procs() timeout parameter is now optional. -- #452: make Process instances hashable and usable with set()s. -- #453: tests on Python < 2.7 require unittest2 module. -- #459: add a make file for running tests and other repetitive tasks (also - on Windows). -- #463: make timeout parameter of cpu_percent* functions default to 0.0 'cause - it's a common trap to introduce slowdowns. -- #468: move documentation to readthedocs.com. -- #477: process cpu_percent() is about 30% faster. (suggested by crusaderky) -- #478: [Linux] almost all APIs are about 30% faster on Python 3.X. -- #479: long deprecated psutil.error module is gone; exception classes now - live in "psutil" namespace only. - -**Bug fixes** - -- #193: psutil.Popen constructor can throw an exception if the spawned process - terminates quickly. -- #340: [Windows] process get_open_files() no longer hangs. (patch by - jtang@vahna.net) -- #443: [Linux] fix a potential overflow issue for Process.set_cpu_affinity() - on systems with more than 64 CPUs. -- #448: [Windows] get_children() and ppid() memory leak (patch by Ulrich - Klank). -- #457: [POSIX] pid_exists() always returns True for PID 0. -- #461: namedtuples are not pickle-able. -- #466: [Linux] process exe improper null bytes handling. (patch by - Gautam Singh) -- #470: wait_procs() might not wait. (patch by crusaderky) -- #471: [Windows] process exe improper unicode handling. (patch by - alex@mroja.net) -- #473: psutil.Popen.wait() does not set returncode attribute. -- #474: [Windows] Process.cpu_percent() is no longer capped at 100%. -- #476: [Linux] encoding error for process name and cmdline. - -**API changes** - -For the sake of consistency a lot of psutil APIs have been renamed. -In most cases accessing the old names will work but it will cause a -DeprecationWarning. - -- psutil.* module level constants have being replaced by functions: - - +-----------------------+-------------------------------+ - | Old name | Replacement | - +=======================+===============================+ - | psutil.NUM_CPUS | psutil.cpu_cpunt() | - +-----------------------+-------------------------------+ - | psutil.BOOT_TIME | psutil.boot_time() | - +-----------------------+-------------------------------+ - | psutil.TOTAL_PHYMEM | psutil.virtual_memory().total | - +-----------------------+-------------------------------+ - -- Renamed psutil.* functions: - - +--------------------------+-------------------------------+ - | Old name | Replacement | - +==========================+===============================+ - | - psutil.get_pid_list() | psutil.pids() | - +--------------------------+-------------------------------+ - | - psutil.get_users() | psutil.users() | - +--------------------------+-------------------------------+ - | - psutil.get_boot_time() | psutil.boot_time() | - +--------------------------+-------------------------------+ - -- All psutil.Process ``get_*`` methods lost the ``get_`` prefix. - get_ext_memory_info() renamed to memory_info_ex(). - Assuming "p = psutil.Process()": - - +--------------------------+----------------------+ - | Old name | Replacement | - +==========================+======================+ - | p.get_children() | p.children() | - +--------------------------+----------------------+ - | p.get_connections() | p.connections() | - +--------------------------+----------------------+ - | p.get_cpu_affinity() | p.cpu_affinity() | - +--------------------------+----------------------+ - | p.get_cpu_percent() | p.cpu_percent() | - +--------------------------+----------------------+ - | p.get_cpu_times() | p.cpu_times() | - +--------------------------+----------------------+ - | p.get_ext_memory_info() | p.memory_info_ex() | - +--------------------------+----------------------+ - | p.get_io_counters() | p.io_counters() | - +--------------------------+----------------------+ - | p.get_ionice() | p.ionice() | - +--------------------------+----------------------+ - | p.get_memory_info() | p.memory_info() | - +--------------------------+----------------------+ - | p.get_memory_maps() | p.memory_maps() | - +--------------------------+----------------------+ - | p.get_memory_percent() | p.memory_percent() | - +--------------------------+----------------------+ - | p.get_nice() | p.nice() | - +--------------------------+----------------------+ - | p.get_num_ctx_switches() | p.num_ctx_switches() | - +--------------------------+----------------------+ - | p.get_num_fds() | p.num_fds() | - +--------------------------+----------------------+ - | p.get_num_threads() | p.num_threads() | - +--------------------------+----------------------+ - | p.get_open_files() | p.open_files() | - +--------------------------+----------------------+ - | p.get_rlimit() | p.rlimit() | - +--------------------------+----------------------+ - | p.get_threads() | p.threads() | - +--------------------------+----------------------+ - | p.getcwd() | p.cwd() | - +--------------------------+----------------------+ - -- All psutil.Process ``set_*`` methods lost the ``set_`` prefix. - Assuming "p = psutil.Process()": - - +----------------------+---------------------------------+ - | Old name | Replacement | - +======================+=================================+ - | p.set_nice() | p.nice(value) | - +----------------------+---------------------------------+ - | p.set_ionice() | p.ionice(ioclass, value=None) | - +----------------------+---------------------------------+ - | p.set_cpu_affinity() | p.cpu_affinity(cpus) | - +----------------------+---------------------------------+ - | p.set_rlimit() | p.rlimit(resource, limits=None) | - +----------------------+---------------------------------+ - -- Except for 'pid' all psutil.Process class properties have been turned into - methods. This is the only case which there are no aliases. - Assuming "p = psutil.Process()": - - +---------------+-----------------+ - | Old name | Replacement | - +===============+=================+ - | p.name | p.name() | - +---------------+-----------------+ - | p.parent | p.parent() | - +---------------+-----------------+ - | p.ppid | p.ppid() | - +---------------+-----------------+ - | p.exe | p.exe() | - +---------------+-----------------+ - | p.cmdline | p.cmdline() | - +---------------+-----------------+ - | p.status | p.status() | - +---------------+-----------------+ - | p.uids | p.uids() | - +---------------+-----------------+ - | p.gids | p.gids() | - +---------------+-----------------+ - | p.username | p.username() | - +---------------+-----------------+ - | p.create_time | p.create_time() | - +---------------+-----------------+ - -- timeout parameter of cpu_percent* functions defaults to 0.0 instead of 0.1. -- long deprecated psutil.error module is gone; exception classes now live in - "psutil" namespace only. -- Process instances' "retcode" attribute returned by psutil.wait_procs() has - been renamed to "returncode" for consistency with subprocess.Popen. - - -1.2.1 - 2013-11-25 -================== - -**Bug fixes** - -- #348: [Windows XP] fixed "ImportError: DLL load failed" occurring on module - import. -- #425: [Solaris] crash on import due to failure at determining BOOT_TIME. -- #443: [Linux] can't set CPU affinity on systems with more than 64 cores. - - -1.2.0 - 2013-11-20 -================== - -**Enhancements** - -- #439: assume os.getpid() if no argument is passed to psutil.Process - constructor. -- #440: new psutil.wait_procs() utility function which waits for multiple - processes to terminate. - -**Bug fixes** - -- #348: [Windows XP/Vista] fix "ImportError: DLL load failed" occurring on - module import. - - -1.1.3 - 2013-11-07 -================== - -**Bug fixes** - -- #442: [Linux] psutil won't compile on certain version of Linux because of - missing prlimit(2) syscall. - - -1.1.2 - 2013-10-22 -================== - -**Bug fixes** - -- #442: [Linux] psutil won't compile on Debian 6.0 because of missing - prlimit(2) syscall. - - -1.1.1 - 2013-10-08 -================== - -**Bug fixes** - -- #442: [Linux] psutil won't compile on kernels < 2.6.36 due to missing - prlimit(2) syscall. - - -1.1.0 - 2013-09-28 -================== - -**Enhancements** - -- #410: host tar.gz and windows binary files are on PYPI. -- #412: [Linux] get/set process resource limits. -- #415: [Windows] Process.get_children() is an order of magnitude faster. -- #426: [Windows] Process.name is an order of magnitude faster. -- #431: [UNIX] Process.name is slightly faster because it unnecessarily - retrieved also process cmdline. - -**Bug fixes** - -- #391: [Windows] psutil.cpu_times_percent() returns negative percentages. -- #408: STATUS_* and CONN_* constants don't properly serialize on JSON. -- #411: [Windows] examples/disk_usage.py may pop-up a GUI error. -- #413: [Windows] Process.get_memory_info() leaks memory. -- #414: [Windows] Process.exe on Windows XP may raise ERROR_INVALID_PARAMETER. -- #416: psutil.disk_usage() doesn't work well with unicode path names. -- #430: [Linux] process IO counters report wrong number of r/w syscalls. -- #435: [Linux] psutil.net_io_counters() might report erreneous NIC names. -- #436: [Linux] psutil.net_io_counters() reports a wrong 'dropin' value. - -**API changes** - -- #408: turn STATUS_* and CONN_* constants into plain Python strings. - - -1.0.1 - 2013-07-12 -================== - -**Bug fixes** - -- #405: network_io_counters(pernic=True) no longer works as intended in 1.0.0. - - -1.0.0 - 2013-07-10 -================== - -**Enhancements** - -- #18: Solaris support (yay!) (thanks Justin Venus) -- #367: Process.get_connections() 'status' strings are now constants. -- #380: test suite exits with non-zero on failure. (patch by floppymaster) -- #391: introduce unittest2 facilities and provide workarounds if unittest2 - is not installed (python < 2.7). - -**Bug fixes** - -- #374: [Windows] negative memory usage reported if process uses a lot of - memory. -- #379: [Linux] Process.get_memory_maps() may raise ValueError. -- #394: [OSX] Mapped memory regions report incorrect file name. -- #404: [Linux] sched_*affinity() are implicitly declared. (patch by Arfrever) - -**API changes** - -- Process.get_connections() 'status' field is no longer a string but a - constant object (psutil.CONN_*). -- Process.get_connections() 'local_address' and 'remote_address' fields - renamed to 'laddr' and 'raddr'. -- psutil.network_io_counters() renamed to psutil.net_io_counters(). - - -0.7.1 - 2013-05-03 -================== - -**Bug fixes** - -- #325: [BSD] psutil.virtual_memory() can raise SystemError. - (patch by Jan Beich) -- #370: [BSD] Process.get_connections() requires root. (patch by John Baldwin) -- #372: [BSD] different process methods raise NoSuchProcess instead of - AccessDenied. - - -0.7.0 - 2013-04-12 -================== - -**Enhancements** - -- #233: code migrated to Mercurial (yay!) -- #246: psutil.error module is deprecated and scheduled for removal. -- #328: [Windows] process IO nice/priority support. -- #359: psutil.get_boot_time() -- #361: [Linux] psutil.cpu_times() now includes new 'steal', 'guest' and - 'guest_nice' fields available on recent Linux kernels. - Also, psutil.cpu_percent() is more accurate. -- #362: cpu_times_percent() (per-CPU-time utilization as a percentage) - -**Bug fixes** - -- #234: [Windows] disk_io_counters() fails to list certain disks. -- #264: [Windows] use of psutil.disk_partitions() may cause a message box to - appear. -- #313: [Linux] psutil.virtual_memory() and psutil.swap_memory() can crash on - certain exotic Linux flavors having an incomplete /proc interface. - If that's the case we now set the unretrievable stats to 0 and raise a - RuntimeWarning. -- #315: [OSX] fix some compilation warnings. -- #317: [Windows] cannot set process CPU affinity above 31 cores. -- #319: [Linux] process get_memory_maps() raises KeyError 'Anonymous' on Debian - squeeze. -- #321: [UNIX] Process.ppid property is no longer cached as the kernel may set - the ppid to 1 in case of a zombie process. -- #323: [OSX] disk_io_counters()'s read_time and write_time parameters were - reporting microseconds not milliseconds. (patch by Gregory Szorc) -- #331: Process cmdline is no longer cached after first acces as it may change. -- #333: [OSX] Leak of Mach ports on OS X (patch by rsesek@google.com) -- #337: [Linux] process methods not working because of a poor /proc - implementation will raise NotImplementedError rather than RuntimeError - and Process.as_dict() will not blow up. (patch by Curtin1060) -- #338: [Linux] disk_io_counters() fails to find some disks. -- #339: [FreeBSD] get_pid_list() can allocate all the memory on system. -- #341: [Linux] psutil might crash on import due to error in retrieving system - terminals map. -- #344: [FreeBSD] swap_memory() might return incorrect results due to - kvm_open(3) not being called. (patch by Jean Sebastien) -- #338: [Linux] disk_io_counters() fails to find some disks. -- #351: [Windows] if psutil is compiled with mingw32 (provided installers for - py2.4 and py2.5 are) disk_io_counters() will fail. (Patch by m.malycha) -- #353: [OSX] get_users() returns an empty list on OSX 10.8. -- #356: Process.parent now checks whether parent PID has been reused in which - case returns None. -- #365: Process.set_nice() should check PID has not been reused by another - process. -- #366: [FreeBSD] get_memory_maps(), get_num_fds(), get_open_files() and - getcwd() Process methods raise RuntimeError instead of AccessDenied. - -**API changes** - -- Process.cmdline property is no longer cached after first access. -- Process.ppid property is no longer cached after first access. -- [Linux] Process methods not working because of a poor /proc implementation - will raise NotImplementedError instead of RuntimeError. -- psutil.error module is deprecated and scheduled for removal. - - -0.6.1 - 2012-08-16 -================== - -**Enhancements** - -- #316: process cmdline property now makes a better job at guessing the process - executable from the cmdline. - -**Bug fixes** - -- #316: process exe was resolved in case it was a symlink. -- #318: python 2.4 compatibility was broken. - -**API changes** - -- process exe can now return an empty string instead of raising AccessDenied. -- process exe is no longer resolved in case it's a symlink. - - -0.6.0 - 2012-08-13 -================== - -**Enhancements** - -- #216: [POSIX] get_connections() UNIX sockets support. -- #220: [FreeBSD] get_connections() has been rewritten in C and no longer - requires lsof. -- #222: [OSX] add support for process cwd. -- #261: process extended memory info. -- #295: [OSX] process executable path is now determined by asking the OS - instead of being guessed from process cmdline. -- #297: [OSX] the Process methods below were always raising AccessDenied for - any process except the current one. Now this is no longer true. Also - they are 2.5x faster. - - name - - get_memory_info() - - get_memory_percent() - - get_cpu_times() - - get_cpu_percent() - - get_num_threads() -- #300: examples/pmap.py script. -- #301: process_iter() now yields processes sorted by their PIDs. -- #302: process number of voluntary and involuntary context switches. -- #303: [Windows] the Process methods below were always raising AccessDenied - for any process not owned by current user. Now this is no longer true: - - create_time - - get_cpu_times() - - get_cpu_percent() - - get_memory_info() - - get_memory_percent() - - get_num_handles() - - get_io_counters() -- #305: add examples/netstat.py script. -- #311: system memory functions has been refactorized and rewritten and now - provide a more detailed and consistent representation of the system - memory. New psutil.virtual_memory() function provides the following - memory amounts: - - total - - available - - percent - - used - - active [POSIX] - - inactive [POSIX] - - buffers (BSD, Linux) - - cached (BSD, OSX) - - wired (OSX, BSD) - - shared [FreeBSD] - New psutil.swap_memory() provides: - - total - - used - - free - - percent - - sin (no. of bytes the system has swapped in from disk (cumulative)) - - sout (no. of bytes the system has swapped out from disk (cumulative)) - All old memory-related functions are deprecated. - Also two new example scripts were added: free.py and meminfo.py. -- #312: psutil.network_io_counters() namedtuple includes 4 new fields: - errin, errout dropin and dropout, reflecting the number of packets - dropped and with errors. - -**Bugfixes** - -- #298: [OSX and BSD] memory leak in get_num_fds(). -- #299: potential memory leak every time PyList_New(0) is used. -- #303: [Windows] potential heap corruption in get_num_threads() and - get_status() Process methods. -- #305: [FreeBSD] psutil can't compile on FreeBSD 9 due to removal of utmp.h. -- #306: at C level, errors are not checked when invoking Py* functions which - create or manipulate Python objects leading to potential memory related - errors and/or segmentation faults. -- #307: [FreeBSD] values returned by psutil.network_io_counters() are wrong. -- #308: [BSD / Windows] psutil.virtmem_usage() wasn't actually returning - information about swap memory usage as it was supposed to do. It does - now. -- #309: get_open_files() might not return files which can not be accessed - due to limited permissions. AccessDenied is now raised instead. - -**API changes** - -- psutil.phymem_usage() is deprecated (use psutil.virtual_memory()) -- psutil.virtmem_usage() is deprecated (use psutil.swap_memory()) -- psutil.phymem_buffers() on Linux is deprecated (use psutil.virtual_memory()) -- psutil.cached_phymem() on Linux is deprecated (use psutil.virtual_memory()) -- [Windows and BSD] psutil.virtmem_usage() now returns information about swap - memory instead of virtual memory. - - -0.5.1 - 2012-06-29 -================== - -**Enhancements** - -- #293: [Windows] process executable path is now determined by asking the OS - instead of being guessed from process cmdline. - -**Bugfixes** - -- #292: [Linux] race condition in process files/threads/connections. -- #294: [Windows] Process CPU affinity is only able to set CPU #0. - - -0.5.0 - 2012-06-27 -================== - -**Enhancements** - -- #195: [Windows] number of handles opened by process. -- #209: psutil.disk_partitions() now provides also mount options. -- #229: list users currently connected on the system (psutil.get_users()). -- #238: [Linux, Windows] process CPU affinity (get and set). -- #242: Process.get_children(recursive=True): return all process - descendants. -- #245: [POSIX] Process.wait() incrementally consumes less CPU cycles. -- #257: [Windows] removed Windows 2000 support. -- #258: [Linux] Process.get_memory_info() is now 0.5x faster. -- #260: process's mapped memory regions. (Windows patch by wj32.64, OSX patch - by Jeremy Whitlock) -- #262: [Windows] psutil.disk_partitions() was slow due to inspecting the - floppy disk drive also when "all" argument was False. -- #273: psutil.get_process_list() is deprecated. -- #274: psutil no longer requires 2to3 at installation time in order to work - with Python 3. -- #278: new Process.as_dict() method. -- #281: ppid, name, exe, cmdline and create_time properties of Process class - are now cached after being accessed. -- #282: psutil.STATUS_* constants can now be compared by using their string - representation. -- #283: speedup Process.is_running() by caching its return value in case the - process is terminated. -- #284: [POSIX] per-process number of opened file descriptors. -- #287: psutil.process_iter() now caches Process instances between calls. -- #290: Process.nice property is deprecated in favor of new get_nice() and - set_nice() methods. - -**Bugfixes** - -- #193: psutil.Popen constructor can throw an exception if the spawned process - terminates quickly. -- #240: [OSX] incorrect use of free() for Process.get_connections(). -- #244: [POSIX] Process.wait() can hog CPU resources if called against a - process which is not our children. -- #248: [Linux] psutil.network_io_counters() might return erroneous NIC names. -- #252: [Windows] process getcwd() erroneously raise NoSuchProcess for - processes owned by another user. It now raises AccessDenied instead. -- #266: [Windows] psutil.get_pid_list() only shows 1024 processes. - (patch by Amoser) -- #267: [OSX] Process.get_connections() - an erroneous remote address was - returned. (Patch by Amoser) -- #272: [Linux] Porcess.get_open_files() - potential race condition can lead to - unexpected NoSuchProcess exception. Also, we can get incorrect reports - of not absolutized path names. -- #275: [Linux] Process.get_io_counters() erroneously raise NoSuchProcess on - old Linux versions. Where not available it now raises - NotImplementedError. -- #286: Process.is_running() doesn't actually check whether PID has been - reused. -- #314: Process.get_children() can sometimes return non-children. - -**API changes** - -- Process.nice property is deprecated in favor of new get_nice() and set_nice() - methods. -- psutil.get_process_list() is deprecated. -- ppid, name, exe, cmdline and create_time properties of Process class are now - cached after being accessed, meaning NoSuchProcess will no longer be raised - in case the process is gone in the meantime. -- psutil.STATUS_* constants can now be compared by using their string - representation. - - -0.4.1 - 2011-12-14 -================== - -**Bugfixes** - -- #228: some example scripts were not working with python 3. -- #230: [Windows / OSX] memory leak in Process.get_connections(). -- #232: [Linux] psutil.phymem_usage() can report erroneous values which are - different than "free" command. -- #236: [Windows] memory/handle leak in Process's get_memory_info(), - suspend() and resume() methods. - - -0.4.0 - 2011-10-29 -================== - -**Enhancements** - -- #150: network I/O counters. (OSX and Windows patch by Jeremy Whitlock) -- #154: [FreeBSD] add support for process getcwd() -- #157: [Windows] provide installer for Python 3.2 64-bit. -- #198: Process.wait(timeout=0) can now be used to make wait() return - immediately. -- #206: disk I/O counters. (OSX and Windows patch by Jeremy Whitlock) -- #213: examples/iotop.py script. -- #217: Process.get_connections() now has a "kind" argument to filter - for connections with different criteria. -- #221: [FreeBSD] Process.get_open_files has been rewritten in C and no longer - relies on lsof. -- #223: examples/top.py script. -- #227: examples/nettop.py script. - -**Bugfixes** - -- #135: [OSX] psutil cannot create Process object. -- #144: [Linux] no longer support 0 special PID. -- #188: [Linux] psutil import error on Linux ARM architectures. -- #194: [POSIX] psutil.Process.get_cpu_percent() now reports a percentage over - 100 on multicore processors. -- #197: [Linux] Process.get_connections() is broken on platforms not - supporting IPv6. -- #200: [Linux] psutil.NUM_CPUS not working on armel and sparc architectures - and causing crash on module import. -- #201: [Linux] Process.get_connections() is broken on big-endian - architectures. -- #211: Process instance can unexpectedly raise NoSuchProcess if tested for - equality with another object. -- #218: [Linux] crash at import time on Debian 64-bit because of a missing - line in /proc/meminfo. -- #226: [FreeBSD] crash at import time on FreeBSD 7 and minor. - - -0.3.0 - 2011-07-08 -================== - -**Enhancements** - -- #125: system per-cpu percentage utilization and times. -- #163: per-process associated terminal (TTY). -- #171: added get_phymem() and get_virtmem() functions returning system - memory information (total, used, free) and memory percent usage. - total_* avail_* and used_* memory functions are deprecated. -- #172: disk usage statistics. -- #174: mounted disk partitions. -- #179: setuptools is now used in setup.py - -**Bugfixes** - -- #159: SetSeDebug() does not close handles or unset impersonation on return. -- #164: [Windows] wait function raises a TimeoutException when a process - returns -1 . -- #165: process.status raises an unhandled exception. -- #166: get_memory_info() leaks handles hogging system resources. -- #168: psutil.cpu_percent() returns erroneous results when used in - non-blocking mode. (patch by Philip Roberts) -- #178: OSX - Process.get_threads() leaks memory -- #180: [Windows] Process's get_num_threads() and get_threads() methods can - raise NoSuchProcess exception while process still exists. - - -0.2.1 - 2011-03-20 -================== - -**Enhancements** - -- #64: per-process I/O counters. -- #116: per-process wait() (wait for process to terminate and return its exit - code). -- #134: per-process get_threads() returning information (id, user and kernel - times) about threads opened by process. -- #136: process executable path on FreeBSD is now determined by asking the - kernel instead of guessing it from cmdline[0]. -- #137: per-process real, effective and saved user and group ids. -- #140: system boot time. -- #142: per-process get and set niceness (priority). -- #143: per-process status. -- #147: per-process I/O nice (priority) - Linux only. -- #148: psutil.Popen class which tidies up subprocess.Popen and psutil.Process - in a unique interface. -- #152: [OSX] get_process_open_files() implementation has been rewritten - in C and no longer relies on lsof resulting in a 3x speedup. -- #153: [OSX] get_process_connection() implementation has been rewritten - in C and no longer relies on lsof resulting in a 3x speedup. - -**Bugfixes** - -- #83: process cmdline is empty on OSX 64-bit. -- #130: a race condition can cause IOError exception be raised on - Linux if process disappears between open() and subsequent read() calls. -- #145: WindowsError was raised instead of psutil.AccessDenied when using - process resume() or suspend() on Windows. -- #146: 'exe' property on Linux can raise TypeError if path contains NULL - bytes. -- #151: exe and getcwd() for PID 0 on Linux return inconsistent data. - -**API changes** - -- Process "uid" and "gid" properties are deprecated in favor of "uids" and - "gids" properties. - - -0.2.0 - 2010-11-13 -================== - -**Enhancements** - -- #79: per-process open files. -- #88: total system physical cached memory. -- #88: total system physical memory buffers used by the kernel. -- #91: per-process send_signal() and terminate() methods. -- #95: NoSuchProcess and AccessDenied exception classes now provide "pid", - "name" and "msg" attributes. -- #97: per-process children. -- #98: Process.get_cpu_times() and Process.get_memory_info now return - a namedtuple instead of a tuple. -- #103: per-process opened TCP and UDP connections. -- #107: add support for Windows 64 bit. (patch by cjgohlke) -- #111: per-process executable name. -- #113: exception messages now include process name and pid. -- #114: process username Windows implementation has been rewritten in pure - C and no longer uses WMI resulting in a big speedup. Also, pywin32 is no - longer required as a third-party dependancy. (patch by wj32) -- #117: added support for Windows 2000. -- #123: psutil.cpu_percent() and psutil.Process.cpu_percent() accept a - new 'interval' parameter. -- #129: per-process number of threads. - -**Bugfixes** - -- #80: fixed warnings when installing psutil with easy_install. -- #81: psutil fails to compile with Visual Studio. -- #94: suspend() raises OSError instead of AccessDenied. -- #86: psutil didn't compile against FreeBSD 6.x. -- #102: orphaned process handles obtained by using OpenProcess in C were - left behind every time Process class was instantiated. -- #111: path and name Process properties report truncated or erroneous - values on UNIX. -- #120: cpu_percent() always returning 100% on OS X. -- #112: uid and gid properties don't change if process changes effective - user/group id at some point. -- #126: ppid, uid, gid, name, exe, cmdline and create_time properties are - no longer cached and correctly raise NoSuchProcess exception if the process - disappears. - -**API changes** - -- psutil.Process.path property is deprecated and works as an alias for "exe" - property. -- psutil.Process.kill(): signal argument was removed - to send a signal to the - process use send_signal(signal) method instead. -- psutil.Process.get_memory_info() returns a nametuple instead of a tuple. -- psutil.cpu_times() returns a nametuple instead of a tuple. -- New psutil.Process methods: get_open_files(), get_connections(), - send_signal() and terminate(). -- ppid, uid, gid, name, exe, cmdline and create_time properties are no longer - cached and raise NoSuchProcess exception if process disappears. -- psutil.cpu_percent() no longer returns immediately (see issue 123). -- psutil.Process.get_cpu_percent() and psutil.cpu_percent() no longer returns - immediately by default (see issue 123). - - -0.1.3 - 2010-03-02 -================== - -**Enhancements** - -- #14: per-process username -- #51: per-process current working directory (Windows and Linux only) -- #59: Process.is_running() is now 10 times faster -- #61: added supoprt for FreeBSD 64 bit -- #71: implemented suspend/resume process -- #75: python 3 support - -**Bugfixes** - -- #36: process cpu_times() and memory_info() functions succeeded also for dead - processes while a NoSuchProcess exception is supposed to be raised. -- #48: incorrect size for mib array defined in getcmdargs for BSD -- #49: possible memory leak due to missing free() on error condition on -- #50: fixed getcmdargs() memory fragmentation on BSD -- #55: test_pid_4 was failing on Windows Vista -- #57: some unit tests were failing on systems where no swap memory is - available -- #58: is_running() is now called before kill() to make sure we are going - to kill the correct process. -- #73: virtual memory size reported on OS X includes shared library size -- #77: NoSuchProcess wasn't raised on Process.create_time if kill() was - used first. - - -0.1.2 - 2009-05-06 -================== - -**Enhancements** - -- #32: Per-process CPU user/kernel times -- #33: Process create time -- #34: Per-process CPU utilization percentage -- #38: Per-process memory usage (bytes) -- #41: Per-process memory utilization (percent) -- #39: System uptime -- #43: Total system virtual memory -- #46: Total system physical memory -- #44: Total system used/free virtual and physical memory - -**Bugfixes** - -- #36: [Windows] NoSuchProcess not raised when accessing timing methods. -- #40: test_get_cpu_times() failing on FreeBSD and OS X. -- #42: [Windows] get_memory_percent() raises AccessDenied. - - -0.1.1 - 2009-03-06 -================== - -**Enhancements** - -- #4: FreeBSD support for all functions of psutil -- #9: Process.uid and Process.gid now retrieve process UID and GID. -- #11: Support for parent/ppid - Process.parent property returns a - Process object representing the parent process, and Process.ppid returns - the parent PID. -- #12 & 15: - NoSuchProcess exception now raised when creating an object - for a nonexistent process, or when retrieving information about a process - that has gone away. -- #21: AccessDenied exception created for raising access denied errors - from OSError or WindowsError on individual platforms. -- #26: psutil.process_iter() function to iterate over processes as - Process objects with a generator. -- #?: Process objects can now also be compared with == operator for equality - (PID, name, command line are compared). - -**Bugfixes** - -- #16: [Windows] Special case for "System Idle Process" (PID 0) which - otherwise would return an "invalid parameter" exception. -- #17: get_process_list() ignores NoSuchProcess and AccessDenied - exceptions during building of the list. -- #22: [Windows] Process(0).kill() was failing with an unset exception. -- #23: Special case for pid_exists(0) -- #24: [Windows] Process(0).kill() now raises AccessDenied exception instead - of WindowsError. -- #30: psutil.get_pid_list() was returning two instances of PID 0 on OSX and - FreeBSD platforms. - - -0.1.0 - 2009-01-27 -================== - -- Initial release. diff --git a/python/psutil/INSTALL.rst b/python/psutil/INSTALL.rst deleted file mode 100644 index e518c430e..000000000 --- a/python/psutil/INSTALL.rst +++ /dev/null @@ -1,116 +0,0 @@ -============================ -Installing using pip on UNIX -============================ - -The easiest way to install psutil on UNIX is by using pip (but first you might -need to install python header files; see later). -First install pip:: - - $ wget https://bootstrap.pypa.io/get-pip.py - $ python get-pip.py - -...then run:: - - $ pip install psutil - -You may need to install gcc and python header files first (see later). - - -===================== -Installing on Windows -===================== - -Just get the right installer for your Python version and architecture from: -https://pypi.python.org/pypi/psutil/#downloads -Since wheels installers are also available you may also use pip. - - -======================================== -Compiling on Windows using Visual Studio -======================================== - -In order to compile psutil on Windows you'll need Visual Studio (Mingw32 is -no longer supported). You must have the same version of Visual Studio used to compile -your installation of Python, that is:: - -* Python 2.6: VS 2008 -* Python 2.7: VS 2008 -* Python 3.3, 3.4: VS 2010 (you can download it from `MS website <http://www.visualstudio.com/downloads/download-visual-studio-vs#d-2010-express>`_) -* Python 3.5: `VS 2015 UP <http://www.visualstudio.com/en-au/news/vs2015-preview-vs>`_ - -...then run:: - - setup.py build - -...or:: - - make.bat build - -Compiling 64 bit versions of Python 2.6 and 2.7 with VS 2008 requires -Windows SDK and .NET Framework 3.5 SP1 to be installed first. -Once you have those run vcvars64.bat, then compile: -http://stackoverflow.com/questions/11072521/ - -=================== -Installing on Linux -=================== - -gcc is required and so the python headers. They can easily be installed by -using the distro package manager. For example, on Debian and Ubuntu:: - - $ sudo apt-get install gcc python-dev - -...on Redhat and CentOS:: - - $ sudo yum install gcc python-devel - -Once done, you can build/install psutil with:: - - $ python setup.py install - - -================== -Installing on OS X -================== - -OS X installation from source will require gcc which you can obtain as part of -the 'XcodeTools' installer from Apple. Then you can run the standard distutils -commands. -To build only:: - - $ python setup.py build - -To install and build:: - - $ python setup.py install - - -===================== -Installing on FreeBSD -===================== - -The same compiler used to install Python must be present on the system in order -to build modules using distutils. Assuming it is installed, you can build using -the standard distutils commands. - -Build only:: - - $ python setup.py build - -Install and build:: - - $ python setup.py install - - -======== -Makefile -======== - -A makefile is available for both UNIX and Windows (make.bat). It provides -some automations for the tasks described above and might be preferred over -using setup.py. With it you can:: - - $ make install # just install (in --user mode) - $ make uninstall # uninstall (needs pip) - $ make test # run tests - $ make clean # remove installation files diff --git a/python/psutil/LICENSE b/python/psutil/LICENSE deleted file mode 100644 index e91b1359a..000000000 --- a/python/psutil/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -psutil is distributed under BSD license reproduced below. - -Copyright (c) 2009, Jay Loden, Dave Daeschler, Giampaolo Rodola' -All rights reserved. - -Redistribution and use in source and binary forms, with or without modification, -are permitted provided that the following conditions are met: - - * Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - * Neither the name of the psutil authors nor the names of its contributors - may be used to endorse or promote products derived from this software without - specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND -ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR -ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES -(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON -ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/python/psutil/MANIFEST.in b/python/psutil/MANIFEST.in deleted file mode 100644 index d807be289..000000000 --- a/python/psutil/MANIFEST.in +++ /dev/null @@ -1,22 +0,0 @@ -include .coveragerc -include .git-pre-commit -include .git-pre-commit -include .gitignore -include .travis.yml -include CREDITS -include HISTORY.rst -include INSTALL.rst -include LICENSE -include make.bat -include Makefile -include MANIFEST.in -include README.rst -include setup.py -include TODO -include tox.ini -recursive-exclude docs/_build * -recursive-include .appveyor/* -recursive-include docs * -recursive-include examples *.py -recursive-include psutil *.py *.c *.h -recursive-include test *.py README* diff --git a/python/psutil/Makefile b/python/psutil/Makefile deleted file mode 100644 index 1e4eb4b01..000000000 --- a/python/psutil/Makefile +++ /dev/null @@ -1,122 +0,0 @@ -# Shortcuts for various tasks (UNIX only). -# To use a specific Python version run: -# $ make install PYTHON=python3.3 - -# You can set these variables from the command line. -PYTHON = python -TSCRIPT = test/test_psutil.py - -all: test - -clean: - rm -f `find . -type f -name \*.py[co]` - rm -f `find . -type f -name \*.so` - rm -f `find . -type f -name .\*~` - rm -f `find . -type f -name \*.orig` - rm -f `find . -type f -name \*.bak` - rm -f `find . -type f -name \*.rej` - rm -rf `find . -type d -name __pycache__` - rm -rf *.core - rm -rf *.egg-info - rm -rf *\$testfile* - rm -rf .coverage - rm -rf .tox - rm -rf build - rm -rf dist - rm -rf docs/_build - rm -rf htmlcov - -build: clean - $(PYTHON) setup.py build - @# copies *.so files in ./psutil directory in order to allow - @# "import psutil" when using the interactive interpreter from within - @# this directory. - $(PYTHON) setup.py build_ext -i - -# useful deps which are nice to have while developing / testing -setup-dev-env: - python -c "import urllib2; \ - r = urllib2.urlopen('https://bootstrap.pypa.io/get-pip.py'); \ - open('/tmp/get-pip.py', 'w').write(r.read());" - $(PYTHON) /tmp/get-pip.py --user - rm /tmp/get-pip.py - $(PYTHON) -m pip install --user --upgrade pip - $(PYTHON) -m pip install --user --upgrade \ - coverage \ - flake8 \ - ipaddress \ - ipdb \ - mock==1.0.1 \ - nose \ - pep8 \ - pyflakes \ - sphinx \ - sphinx-pypi-upload \ - unittest2 \ - -install: build - $(PYTHON) setup.py install --user - -uninstall: - cd ..; $(PYTHON) -m pip uninstall -y -v psutil - -test: install - $(PYTHON) $(TSCRIPT) - -test-process: install - $(PYTHON) -m unittest -v test.test_psutil.TestProcess - -test-system: install - $(PYTHON) -m unittest -v test.test_psutil.TestSystemAPIs - -test-memleaks: install - $(PYTHON) test/test_memory_leaks.py - -# Run a specific test by name; e.g. "make test-by-name disk_" will run -# all test methods containing "disk_" in their name. -# Requires "pip install nose". -test-by-name: install - @$(PYTHON) -m nose test/test_psutil.py test/_* --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS)) - -# Same as above but for test_memory_leaks.py script. -test-memleaks-by-name: install - @$(PYTHON) -m nose test/test_memory_leaks.py --nocapture -v -m $(filter-out $@,$(MAKECMDGOALS)) - -coverage: install - # Note: coverage options are controlled by .coveragerc file - rm -rf .coverage htmlcov - $(PYTHON) -m coverage run $(TSCRIPT) - $(PYTHON) -m coverage report - @echo "writing results to htmlcov/index.html" - $(PYTHON) -m coverage html - $(PYTHON) -m webbrowser -t htmlcov/index.html - -pep8: - @git ls-files | grep \\.py$ | xargs $(PYTHON) -m pep8 - -pyflakes: - @export PYFLAKES_NODOCTEST=1 && \ - git ls-files | grep \\.py$ | xargs $(PYTHON) -m pyflakes - -flake8: - @git ls-files | grep \\.py$ | xargs $(PYTHON) -m flake8 - -# Upload source tarball on https://pypi.python.org/pypi/psutil. -upload-src: clean - $(PYTHON) setup.py sdist upload - -# Build and upload doc on https://pythonhosted.org/psutil/. -# Requires "pip install sphinx-pypi-upload". -upload-doc: - cd docs; make html - $(PYTHON) setup.py upload_sphinx --upload-dir=docs/_build/html - -# git-tag a new release -git-tag-release: - git tag -a release-`python -c "import setup; print(setup.get_version())"` -m `git rev-list HEAD --count`:`git rev-parse --short HEAD` - echo "done; now run 'git push --follow-tags' to push the new tag on the remote repo" - -# install GIT pre-commit hook -install-git-hooks: - ln -sf ../../.git-pre-commit .git/hooks/pre-commit - chmod +x .git/hooks/pre-commit diff --git a/python/psutil/PKG-INFO b/python/psutil/PKG-INFO deleted file mode 100644 index e74d33f65..000000000 --- a/python/psutil/PKG-INFO +++ /dev/null @@ -1,434 +0,0 @@ -Metadata-Version: 1.1 -Name: psutil -Version: 3.1.1 -Summary: psutil is a cross-platform library for retrieving information onrunning processes and system utilization (CPU, memory, disks, network)in Python. -Home-page: https://github.com/giampaolo/psutil -Author: Giampaolo Rodola -Author-email: g.rodola <at> gmail <dot> com -License: BSD -Description: .. image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pypi.python.org/pypi/psutil#downloads - :alt: Downloads this month - - .. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master - :target: https://travis-ci.org/giampaolo/psutil - :alt: Linux tests (Travis) - - .. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true - :target: https://ci.appveyor.com/project/giampaolo/psutil - :alt: Windows tests (Appveyor) - - .. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/giampaolo/psutil?branch=master - :alt: Test coverage (coverall.io) - - .. image:: https://img.shields.io/pypi/v/psutil.svg - :target: https://pypi.python.org/pypi/psutil/ - :alt: Latest version - - .. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/ - :alt: Github stars - - .. image:: https://img.shields.io/scrutinizer/g/giampaolo/psutil.svg - :target: https://scrutinizer-ci.com/g/giampaolo/psutil/ - :alt: Code quality (scrutinizer-ci.com) - - .. image:: https://img.shields.io/pypi/l/psutil.svg - :target: https://pypi.python.org/pypi/psutil/ - :alt: License - - =========== - Quick links - =========== - - - `Home page <https://github.com/giampaolo/psutil>`_ - - `Documentation <http://pythonhosted.org/psutil/>`_ - - `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_ - - `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_ - - `Forum <http://groups.google.com/group/psutil/topics>`_ - - `Blog <http://grodola.blogspot.com/search/label/psutil>`_ - - `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_ - - `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_ - - ======= - Summary - ======= - - psutil (python system and process utilities) is a cross-platform library for - retrieving information on **running processes** and **system utilization** - (CPU, memory, disks, network) in Python. It is useful mainly for **system - monitoring**, **profiling and limiting process resources** and **management of - running processes**. It implements many functionalities offered by command line - tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, - ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports - **Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and - **64-bit** architectures, with Python versions from **2.6 to 3.5** (users of - Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version). - `PyPy <http://pypy.org/>`__ is also known to work. - - ==================== - Example applications - ==================== - - .. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/top.png - :alt: top - - .. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/nettop.png - :alt: nettop - - .. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/iotop.png - :alt: iotop - - See also: - - * https://github.com/nicolargo/glances - * https://github.com/google/grr - * https://github.com/Jahaja/psdash - - ============== - Example usages - ============== - - CPU - === - - .. code-block:: python - - >>> import psutil - >>> psutil.cpu_times() - scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1) - ... - 4.0 - 5.9 - 3.8 - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1, percpu=True) - ... - [4.0, 6.9, 3.7, 9.2] - [7.0, 8.5, 2.4, 2.1] - [1.2, 9.0, 9.9, 7.2] - >>> - >>> - >>> for x in range(3): - ... psutil.cpu_times_percent(interval=1, percpu=False) - ... - scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - - Memory - ====== - - .. code-block:: python - - >>> psutil.virtual_memory() - svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336) - >>> psutil.swap_memory() - sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) - >>> - - Disks - ===== - - .. code-block:: python - - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), - sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] - >>> - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - >>> - >>> psutil.disk_io_counters(perdisk=False) - sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568) - >>> - - Network - ======= - - .. code-block:: python - - >>> psutil.net_io_counters(pernic=True) - {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), - 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} - >>> - >>> psutil.net_connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None) - ...] - >>> - >>> psutil.net_if_addrs() - {'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'), - snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')], - 'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'), - snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]} - >>> - >>> psutil.net_if_stats() - {'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500), - 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)} - - Other system info - ================= - - .. code-block:: python - - >>> psutil.users() - [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0), - user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)] - >>> - >>> psutil.boot_time() - 1365519115.0 - >>> - - Process management - ================== - - .. code-block:: python - - >>> import psutil - >>> psutil.pids() - [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, - 268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355, - 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, - 4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, - 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235, - 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] - >>> - >>> p = psutil.Process(7055) - >>> p.name() - 'python' - >>> p.exe() - '/usr/bin/python' - >>> p.cwd() - '/home/giampaolo' - >>> p.cmdline() - ['/usr/bin/python', 'main.py'] - >>> - >>> p.status() - 'running' - >>> p.username() - 'giampaolo' - >>> p.create_time() - 1267551141.5019531 - >>> p.terminal() - '/dev/pts/0' - >>> - >>> p.uids() - puids(real=1000, effective=1000, saved=1000) - >>> p.gids() - pgids(real=1000, effective=1000, saved=1000) - >>> - >>> p.cpu_times() - pcputimes(user=1.02, system=0.31) - >>> p.cpu_percent(interval=1.0) - 12.1 - >>> p.cpu_affinity() - [0, 1, 2, 3] - >>> p.cpu_affinity([0]) # set - >>> - >>> p.memory_percent() - 0.63423 - >>> - >>> p.memory_info() - pmem(rss=7471104, vms=68513792) - >>> p.memory_info_ex() - extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0) - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0), - pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0), - pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0), - pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0), - pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0), - ...] - >>> - >>> p.io_counters() - pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632) - >>> - >>> p.open_files() - [popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)] - >>> - >>> p.connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'), - pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'), - pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')] - >>> - >>> p.num_threads() - 4 - >>> p.num_fds() - 8 - >>> p.threads() - [pthread(id=5234, user_time=22.5, system_time=9.2891), - pthread(id=5235, user_time=0.0, system_time=0.0), - pthread(id=5236, user_time=0.0, system_time=0.0), - pthread(id=5237, user_time=0.0707, system_time=1.1)] - >>> - >>> p.num_ctx_switches() - pctxsw(voluntary=78, involuntary=19) - >>> - >>> p.nice() - 0 - >>> p.nice(10) # set - >>> - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) - >>> p.ionice() - pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0) - >>> - >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) - >>> p.rlimit(psutil.RLIMIT_NOFILE) - (5, 5) - >>> - >>> p.suspend() - >>> p.resume() - >>> - >>> p.terminate() - >>> p.wait(timeout=3) - 0 - >>> - >>> psutil.test() - USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND - root 1 0.0 0.0 24584 2240 Jun17 00:00 init - root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd - root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0 - ... - giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 - giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome - root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 - >>> - - Further process APIs - ==================== - - .. code-block:: python - - >>> for p in psutil.process_iter(): - ... print(p) - ... - psutil.Process(pid=1, name='init') - psutil.Process(pid=2, name='kthreadd') - psutil.Process(pid=3, name='ksoftirqd/0') - ... - >>> - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> # waits for multiple processes to terminate - >>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate) - >>> - - ====== - Donate - ====== - - A lot of time and effort went into making psutil as it is right now. - If you feel psutil is useful to you or your business and want to support its future development please consider donating me (`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money. - I only ask for a small donation, but of course I appreciate any amount. - - .. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif - :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 - :alt: Donate via PayPal - - Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_. - - ============ - Mailing list - ============ - - http://groups.google.com/group/psutil/ - - ======== - Timeline - ======== - - - 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_ - - 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_ - - 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_ - - 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_ - - 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_ - - 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_ - - 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_ - - 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_ - - 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_ - - 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_ - - 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_ - - 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_ - - 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_ - - 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_ - - 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_ - - 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_ - - 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_ - - 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_ - - 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_ - - 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_ - - 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_ - - 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_ - - 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_ - - 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_ - - 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_ - - 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_ - - 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_ - - 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_ - - 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_ - - 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_ - - 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_ - - 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_ - - 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_ - - 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_ - -Keywords: ps,top,kill,free,lsof,netstat,nice,tty,ionice,uptime,taskmgr,process,df,iotop,iostat,ifconfig,taskset,who,pidof,pmap,smem,pstree,monitoring,ulimit,prlimit -Platform: Platform Independent -Classifier: Development Status :: 5 - Production/Stable -Classifier: Environment :: Console -Classifier: Environment :: Win32 (MS Windows) -Classifier: Intended Audience :: Developers -Classifier: Intended Audience :: Information Technology -Classifier: Intended Audience :: System Administrators -Classifier: License :: OSI Approved :: BSD License -Classifier: Operating System :: MacOS :: MacOS X -Classifier: Operating System :: Microsoft :: Windows :: Windows NT/2000 -Classifier: Operating System :: Microsoft -Classifier: Operating System :: OS Independent -Classifier: Operating System :: POSIX :: BSD :: FreeBSD -Classifier: Operating System :: POSIX :: Linux -Classifier: Operating System :: POSIX :: SunOS/Solaris -Classifier: Operating System :: POSIX -Classifier: Programming Language :: C -Classifier: Programming Language :: Python :: 2 -Classifier: Programming Language :: Python :: 2.6 -Classifier: Programming Language :: Python :: 2.7 -Classifier: Programming Language :: Python :: 3 -Classifier: Programming Language :: Python :: 3.0 -Classifier: Programming Language :: Python :: 3.1 -Classifier: Programming Language :: Python :: 3.2 -Classifier: Programming Language :: Python :: 3.3 -Classifier: Programming Language :: Python :: 3.4 -Classifier: Programming Language :: Python :: Implementation :: CPython -Classifier: Programming Language :: Python :: Implementation :: PyPy -Classifier: Programming Language :: Python -Classifier: Topic :: Software Development :: Libraries :: Python Modules -Classifier: Topic :: Software Development :: Libraries -Classifier: Topic :: System :: Benchmark -Classifier: Topic :: System :: Hardware -Classifier: Topic :: System :: Monitoring -Classifier: Topic :: System :: Networking :: Monitoring -Classifier: Topic :: System :: Networking -Classifier: Topic :: System :: Systems Administration -Classifier: Topic :: Utilities diff --git a/python/psutil/README.rst b/python/psutil/README.rst deleted file mode 100644 index 564656146..000000000 --- a/python/psutil/README.rst +++ /dev/null @@ -1,386 +0,0 @@ -.. image:: https://img.shields.io/pypi/dm/psutil.svg - :target: https://pypi.python.org/pypi/psutil#downloads - :alt: Downloads this month - -.. image:: https://api.travis-ci.org/giampaolo/psutil.png?branch=master - :target: https://travis-ci.org/giampaolo/psutil - :alt: Linux tests (Travis) - -.. image:: https://ci.appveyor.com/api/projects/status/qdwvw7v1t915ywr5/branch/master?svg=true - :target: https://ci.appveyor.com/project/giampaolo/psutil - :alt: Windows tests (Appveyor) - -.. image:: https://coveralls.io/repos/giampaolo/psutil/badge.svg?branch=master&service=github - :target: https://coveralls.io/github/giampaolo/psutil?branch=master - :alt: Test coverage (coverall.io) - -.. image:: https://img.shields.io/pypi/v/psutil.svg - :target: https://pypi.python.org/pypi/psutil/ - :alt: Latest version - -.. image:: https://img.shields.io/github/stars/giampaolo/psutil.svg - :target: https://github.com/giampaolo/psutil/ - :alt: Github stars - -.. image:: https://img.shields.io/scrutinizer/g/giampaolo/psutil.svg - :target: https://scrutinizer-ci.com/g/giampaolo/psutil/ - :alt: Code quality (scrutinizer-ci.com) - -.. image:: https://img.shields.io/pypi/l/psutil.svg - :target: https://pypi.python.org/pypi/psutil/ - :alt: License - -=========== -Quick links -=========== - -- `Home page <https://github.com/giampaolo/psutil>`_ -- `Documentation <http://pythonhosted.org/psutil/>`_ -- `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_ -- `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`_ -- `Forum <http://groups.google.com/group/psutil/topics>`_ -- `Blog <http://grodola.blogspot.com/search/label/psutil>`_ -- `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_ -- `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`_ - -======= -Summary -======= - -psutil (python system and process utilities) is a cross-platform library for -retrieving information on **running processes** and **system utilization** -(CPU, memory, disks, network) in Python. It is useful mainly for **system -monitoring**, **profiling and limiting process resources** and **management of -running processes**. It implements many functionalities offered by command line -tools such as: ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, -ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap. It currently supports -**Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, both **32-bit** and -**64-bit** architectures, with Python versions from **2.6 to 3.5** (users of -Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version). -`PyPy <http://pypy.org/>`__ is also known to work. - -==================== -Example applications -==================== - -.. image:: http://psutil.googlecode.com/svn/wiki/images/top-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/top.png - :alt: top - -.. image:: http://psutil.googlecode.com/svn/wiki/images/nettop-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/nettop.png - :alt: nettop - -.. image:: http://psutil.googlecode.com/svn/wiki/images/iotop-thumb.png - :target: http://psutil.googlecode.com/svn/wiki/images/iotop.png - :alt: iotop - -See also: - - * https://github.com/nicolargo/glances - * https://github.com/google/grr - * https://github.com/Jahaja/psdash - -============== -Example usages -============== - -CPU -=== - -.. code-block:: python - - >>> import psutil - >>> psutil.cpu_times() - scputimes(user=3961.46, nice=169.729, system=2150.659, idle=16900.540, iowait=629.59, irq=0.0, softirq=19.42, steal=0.0, guest=0, nice=0.0) - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1) - ... - 4.0 - 5.9 - 3.8 - >>> - >>> for x in range(3): - ... psutil.cpu_percent(interval=1, percpu=True) - ... - [4.0, 6.9, 3.7, 9.2] - [7.0, 8.5, 2.4, 2.1] - [1.2, 9.0, 9.9, 7.2] - >>> - >>> - >>> for x in range(3): - ... psutil.cpu_times_percent(interval=1, percpu=False) - ... - scputimes(user=1.5, nice=0.0, system=0.5, idle=96.5, iowait=1.5, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=1.0, nice=0.0, system=0.0, idle=99.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - scputimes(user=2.0, nice=0.0, system=0.0, idle=98.0, iowait=0.0, irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - -Memory -====== - -.. code-block:: python - - >>> psutil.virtual_memory() - svmem(total=8374149120, available=2081050624, percent=75.1, used=8074080256, free=300068864, active=3294920704, inactive=1361616896, buffers=529895424, cached=1251086336) - >>> psutil.swap_memory() - sswap(total=2097147904, used=296128512, free=1801019392, percent=14.1, sin=304193536, sout=677842944) - >>> - -Disks -===== - -.. code-block:: python - - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda1', mountpoint='/', fstype='ext4', opts='rw,nosuid'), - sdiskpart(device='/dev/sda2', mountpoint='/home', fstype='ext, opts='rw')] - >>> - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - >>> - >>> psutil.disk_io_counters(perdisk=False) - sdiskio(read_count=719566, write_count=1082197, read_bytes=18626220032, write_bytes=24081764352, read_time=5023392, write_time=63199568) - >>> - -Network -======= - -.. code-block:: python - - >>> psutil.net_io_counters(pernic=True) - {'eth0': netio(bytes_sent=485291293, bytes_recv=6004858642, packets_sent=3251564, packets_recv=4787798, errin=0, errout=0, dropin=0, dropout=0), - 'lo': netio(bytes_sent=2838627, bytes_recv=2838627, packets_sent=30567, packets_recv=30567, errin=0, errout=0, dropin=0, dropout=0)} - >>> - >>> psutil.net_connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None) - ...] - >>> - >>> psutil.net_if_addrs() - {'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'), - snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')], - 'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'), - snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]} - >>> - >>> psutil.net_if_stats() - {'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500), - 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)} - -Other system info -================= - -.. code-block:: python - - >>> psutil.users() - [user(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0), - user(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)] - >>> - >>> psutil.boot_time() - 1365519115.0 - >>> - -Process management -================== - -.. code-block:: python - - >>> import psutil - >>> psutil.pids() - [1, 2, 3, 4, 5, 6, 7, 46, 48, 50, 51, 178, 182, 222, 223, 224, - 268, 1215, 1216, 1220, 1221, 1243, 1244, 1301, 1601, 2237, 2355, - 2637, 2774, 3932, 4176, 4177, 4185, 4187, 4189, 4225, 4243, 4245, - 4263, 4282, 4306, 4311, 4312, 4313, 4314, 4337, 4339, 4357, 4358, - 4363, 4383, 4395, 4408, 4433, 4443, 4445, 4446, 5167, 5234, 5235, - 5252, 5318, 5424, 5644, 6987, 7054, 7055, 7071] - >>> - >>> p = psutil.Process(7055) - >>> p.name() - 'python' - >>> p.exe() - '/usr/bin/python' - >>> p.cwd() - '/home/giampaolo' - >>> p.cmdline() - ['/usr/bin/python', 'main.py'] - >>> - >>> p.status() - 'running' - >>> p.username() - 'giampaolo' - >>> p.create_time() - 1267551141.5019531 - >>> p.terminal() - '/dev/pts/0' - >>> - >>> p.uids() - puids(real=1000, effective=1000, saved=1000) - >>> p.gids() - pgids(real=1000, effective=1000, saved=1000) - >>> - >>> p.cpu_times() - pcputimes(user=1.02, system=0.31) - >>> p.cpu_percent(interval=1.0) - 12.1 - >>> p.cpu_affinity() - [0, 1, 2, 3] - >>> p.cpu_affinity([0]) # set - >>> - >>> p.memory_percent() - 0.63423 - >>> - >>> p.memory_info() - pmem(rss=7471104, vms=68513792) - >>> p.memory_info_ex() - extmem(rss=9662464, vms=49192960, shared=3612672, text=2564096, lib=0, data=5754880, dirty=0) - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x86_64-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0), - pmmap_grouped(path='/lib/x86_64-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0), - pmmap_grouped(path='/lib/x86_64-linux-gnu/libcrypto.so.1.0.0', rss=34124, anonymous=1245, swap=0), - pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0), - pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0), - ...] - >>> - >>> p.io_counters() - pio(read_count=478001, write_count=59371, read_bytes=700416, write_bytes=69632) - >>> - >>> p.open_files() - [popenfile(path='/home/giampaolo/svn/psutil/somefile', fd=3)] - >>> - >>> p.connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'), - pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'), - pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')] - >>> - >>> p.num_threads() - 4 - >>> p.num_fds() - 8 - >>> p.threads() - [pthread(id=5234, user_time=22.5, system_time=9.2891), - pthread(id=5235, user_time=0.0, system_time=0.0), - pthread(id=5236, user_time=0.0, system_time=0.0), - pthread(id=5237, user_time=0.0707, system_time=1.1)] - >>> - >>> p.num_ctx_switches() - pctxsw(voluntary=78, involuntary=19) - >>> - >>> p.nice() - 0 - >>> p.nice(10) # set - >>> - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # IO priority (Win and Linux only) - >>> p.ionice() - pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0) - >>> - >>> p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) # set resource limits (Linux only) - >>> p.rlimit(psutil.RLIMIT_NOFILE) - (5, 5) - >>> - >>> p.suspend() - >>> p.resume() - >>> - >>> p.terminate() - >>> p.wait(timeout=3) - 0 - >>> - >>> psutil.test() - USER PID %CPU %MEM VSZ RSS TTY START TIME COMMAND - root 1 0.0 0.0 24584 2240 Jun17 00:00 init - root 2 0.0 0.0 0 0 Jun17 00:00 kthreadd - root 3 0.0 0.0 0 0 Jun17 00:05 ksoftirqd/0 - ... - giampaolo 31475 0.0 0.0 20760 3024 /dev/pts/0 Jun19 00:00 python2.4 - giampaolo 31721 0.0 2.2 773060 181896 00:04 10:30 chrome - root 31763 0.0 0.0 0 0 00:05 00:00 kworker/0:1 - >>> - -Further process APIs -==================== - -.. code-block:: python - - >>> for p in psutil.process_iter(): - ... print(p) - ... - psutil.Process(pid=1, name='init') - psutil.Process(pid=2, name='kthreadd') - psutil.Process(pid=3, name='ksoftirqd/0') - ... - >>> - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> # waits for multiple processes to terminate - >>> gone, alive = psutil.wait_procs(procs_list, 3, callback=on_terminate) - >>> - -====== -Donate -====== - -A lot of time and effort went into making psutil as it is right now. -If you feel psutil is useful to you or your business and want to support its future development please consider donating me (`Giampaolo Rodola' <http://grodola.blogspot.com/p/about.html>`_) some money. -I only ask for a small donation, but of course I appreciate any amount. - -.. image:: http://www.paypal.com/en_US/i/btn/x-click-but04.gif - :target: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=A9ZS7PKKRM3S8 - :alt: Donate via PayPal - -Don't want to donate money? Then maybe you could `write me a recommendation on Linkedin <http://www.linkedin.com/in/grodola>`_. - -============ -Mailing list -============ - -http://groups.google.com/group/psutil/ - -======== -Timeline -======== - -- 2015-07-15: `psutil-3.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.1.tar.gz>`_ -- 2015-07-15: `psutil-3.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.1.0.tar.gz>`_ -- 2015-06-18: `psutil-3.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.1.tar.gz>`_ -- 2015-06-13: `psutil-3.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-3.0.0.tar.gz>`_ -- 2015-02-02: `psutil-2.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.1.tar.gz>`_ -- 2015-01-06: `psutil-2.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.2.0.tar.gz>`_ -- 2014-09-26: `psutil-2.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.3.tar.gz>`_ -- 2014-09-21: `psutil-2.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.2.tar.gz>`_ -- 2014-04-30: `psutil-2.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.1.tar.gz>`_ -- 2014-04-08: `psutil-2.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.1.0.tar.gz>`_ -- 2014-03-10: `psutil-2.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-2.0.0.tar.gz>`_ -- 2013-11-25: `psutil-1.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.1.tar.gz>`_ -- 2013-11-20: `psutil-1.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.2.0.tar.gz>`_ -- 2013-11-07: `psutil-1.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.3.tar.gz>`_ -- 2013-10-22: `psutil-1.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.2.tar.gz>`_ -- 2013-10-08: `psutil-1.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.1.tar.gz>`_ -- 2013-09-28: `psutil-1.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.1.0.tar.gz>`_ -- 2013-07-12: `psutil-1.0.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.1.tar.gz>`_ -- 2013-07-10: `psutil-1.0.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-1.0.0.tar.gz>`_ -- 2013-05-03: `psutil-0.7.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.1.tar.gz>`_ -- 2013-04-12: `psutil-0.7.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.7.0.tar.gz>`_ -- 2012-08-16: `psutil-0.6.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.1.tar.gz>`_ -- 2012-08-13: `psutil-0.6.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.6.0.tar.gz>`_ -- 2012-06-29: `psutil-0.5.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.1.tar.gz>`_ -- 2012-06-27: `psutil-0.5.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.5.0.tar.gz>`_ -- 2011-12-14: `psutil-0.4.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.1.tar.gz>`_ -- 2011-10-29: `psutil-0.4.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.4.0.tar.gz>`_ -- 2011-07-08: `psutil-0.3.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.3.0.tar.gz>`_ -- 2011-03-20: `psutil-0.2.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.1.tar.gz>`_ -- 2010-11-13: `psutil-0.2.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.2.0.tar.gz>`_ -- 2010-03-02: `psutil-0.1.3.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.3.tar.gz>`_ -- 2009-05-06: `psutil-0.1.2.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.2.tar.gz>`_ -- 2009-03-06: `psutil-0.1.1.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.1.tar.gz>`_ -- 2009-01-27: `psutil-0.1.0.tar.gz <https://pypi.python.org/packages/source/p/psutil/psutil-0.1.0.tar.gz>`_ diff --git a/python/psutil/TODO b/python/psutil/TODO deleted file mode 100644 index a5df809d0..000000000 --- a/python/psutil/TODO +++ /dev/null @@ -1,167 +0,0 @@ -TODO -==== - -A collection of ideas and notes about stuff to implement in future versions. -"#NNN" occurrences refer to bug tracker issues at: -https://github.com/giampaolo/psutil/issues - - -HIGHER PRIORITY -=============== - - * OpenBSD support. - - * #371: CPU temperature (apparently OSX and Linux only; on Linux it requires - lm-sensors lib). - - * #269: expose network ifaces RX/TW queues. This should probably go into - net_if_stats(). Figure out on what platforms this is supported: - Linux: yes - Others: ? - - * Process.threads(): thread names; patch for OSX available at: - https://code.google.com/p/plcrashreporter/issues/detail?id=65 - - * Asynchronous psutil.Popen (see http://bugs.python.org/issue1191964) - - * (Windows) fall back on using WMIC for Process methods returning AccessDenied - - * #613: thread names. - - * #604: emulate os.getloadavg() on Windows - - * #269: NIC rx/tx queue. - - -LOWER PRIORITY -============== - - * #355: Android support. - - * #276: GNU/Hurd support. - - * #429: NetBSD support. - - * DragonFlyBSD support? - - * AIX support? - - * examples/taskmgr-gui.py (using tk). - - * system-wide number of open file descriptors: - * https://jira.hyperic.com/browse/SIGAR-30 - * http://www.netadmintools.com/part295.html - - * Number of system threads. - * Windows: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684824(v=vs.85).aspx - - * #357: what CPU a process is on. - - * Doc / wiki which compares similarities between UNIX cli tools and psutil. - Example: - df -a -> psutil.disk_partitions - lsof -> psutil.Process.open_files() and psutil.Process.open_connections() - killall-> (actual script) - tty -> psutil.Process.terminal() - who -> psutil.users() - - -DEBATABLE -========= - - * psutil.proc_tree() something which obtains a {pid:ppid, ...} dict for - all running processes in one shot. This can be factored out from - Process.children() and exposed as a first class function. - PROS: on Windows we can take advantage of _psutil_windows.ppid_map() - which is faster than iterating over all pids and calling ppid(). - CONS: examples/pstree.py shows this can be easily done in the user code - so maybe it's not worth the addition. - - * advanced cmdline interface exposing the whole API and providing different - kind of outputs (e.g. pprinted, colorized, json). - - * [Linux]: process cgroups (http://en.wikipedia.org/wiki/Cgroups). They look - similar to prlimit() in terms of functionality but uglier (they should allow - limiting per-process network IO resources though, which is great). Needs - further reading. - - * Should we expose OS constants (psutil.WINDOWS, psutil.OSX etc.)? - - * Python 3.3. exposed different sched.h functions: - http://docs.python.org/dev/whatsnew/3.3.html#os - http://bugs.python.org/issue12655 - http://docs.python.org/dev/library/os.html#interface-to-the-scheduler - It might be worth to take a look and figure out whether we can include some - of those in psutil. - Also, we can probably reimplement wait_pid() on POSIX which is currently - implemented as a busy-loop. - - * Certain systems provide CPU times about process children. On those systems - Process.cpu_times() might return a (user, system, user_children, - system_children) ntuple. - * Linux: /proc/{PID}/stat - * Solaris: pr_cutime and pr_cstime - * FreeBSD: none - * OSX: none - * Windows: none - - * ...also, os.times() provides 'elapsed' times as well. - - * ...also Linux provides guest_time and cguest_time. - - * Enrich exception classes hierarchy on Python >= 3.3 / post PEP-3151 so that: - - NoSuchProcess inherits from ProcessLookupError - - AccessDenied inherits from PermissionError - - TimeoutExpired inherits from TimeoutError (debatable) - See: http://docs.python.org/3/library/exceptions.html#os-exceptions - - * Process.threads() might grow an extra "id" parameter so that it can be - used as such: - - >>> p = psutil.Process(os.getpid()) - >>> p.threads(id=psutil.current_thread_id()) - thread(id=2539, user_time=0.03, system_time=0.02) - >>> - - Note: this leads to questions such as "should we have a custom NoSuchThread - exception? Also see issue #418. - - Note #2: this would work with os.getpid() only. - psutil.current_thread_id() might be desirable as per issue #418 though. - - * should psutil.TimeoutExpired exception have a 'msg' kwarg similar to - NoSuchProcess and AccessDenied? Not that we need it, but currently we - cannot raise a TimeoutExpired exception with a specific error string. - - * process_iter() might grow an "attrs" parameter similar to Process.as_dict() - invoke the necessary methods and include the results into a "cache" - attribute attached to the returned Process instances so that one can avoid - catching NSP and AccessDenied: - for p in process_iter(attrs=['cpu_percent']): - print(p.cache['cpu_percent']) - This also leads questions as whether we should introduce a sorting order. - - * round Process.memory_percent() result? - - * #550: number of threads per core. - - * Have psutil.Process().cpu_affinity([]) be an alias for "all CPUs"? - - -COMPATIBILITY BREAKAGE -====================== - -Removals (will likely happen in 2.2): - - * (S) psutil.Process.nice (deprecated in 0.5.0) - * (S) get_process_list (deprecated in 0.5.0) - * (S) psutil.*mem* functions (deprecated in 0.3.0 and 0.6.0) - * (M) psutil.network_io_counters (deprecated in 1.0.0) - * (M) local_address and remote_address Process.connection() namedtuple fields - (deprecated in 1.0.0) - - -REJECTED IDEAS -============== - -STUB diff --git a/python/psutil/docs/Makefile b/python/psutil/docs/Makefile deleted file mode 100644 index b23ab4ba8..000000000 --- a/python/psutil/docs/Makefile +++ /dev/null @@ -1,177 +0,0 @@ -# Makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -PAPER = -BUILDDIR = _build - -# User-friendly check for sphinx-build -ifeq ($(shell which $(SPHINXBUILD) >/dev/null 2>&1; echo $$?), 1) -$(error The '$(SPHINXBUILD)' command was not found. Make sure you have Sphinx installed, then set the SPHINXBUILD environment variable to point to the full path of the '$(SPHINXBUILD)' executable. Alternatively you can add the directory with the executable to your PATH. If you don't have Sphinx installed, grab it from http://sphinx-doc.org/) -endif - -# Internal variables. -PAPEROPT_a4 = -D latex_paper_size=a4 -PAPEROPT_letter = -D latex_paper_size=letter -ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . -# the i18n builder cannot share the environment and doctrees with the others -I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . - -.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext - -help: - @echo "Please use \`make <target>' where <target> is one of" - @echo " html to make standalone HTML files" - @echo " dirhtml to make HTML files named index.html in directories" - @echo " singlehtml to make a single large HTML file" - @echo " pickle to make pickle files" - @echo " json to make JSON files" - @echo " htmlhelp to make HTML files and a HTML help project" - @echo " qthelp to make HTML files and a qthelp project" - @echo " devhelp to make HTML files and a Devhelp project" - @echo " epub to make an epub" - @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" - @echo " latexpdf to make LaTeX files and run them through pdflatex" - @echo " latexpdfja to make LaTeX files and run them through platex/dvipdfmx" - @echo " text to make text files" - @echo " man to make manual pages" - @echo " texinfo to make Texinfo files" - @echo " info to make Texinfo files and run them through makeinfo" - @echo " gettext to make PO message catalogs" - @echo " changes to make an overview of all changed/added/deprecated items" - @echo " xml to make Docutils-native XML files" - @echo " pseudoxml to make pseudoxml-XML files for display purposes" - @echo " linkcheck to check all external links for integrity" - @echo " doctest to run all doctests embedded in the documentation (if enabled)" - -clean: - rm -rf $(BUILDDIR) - -html: - $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." - -dirhtml: - $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml - @echo - @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." - -singlehtml: - $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml - @echo - @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." - -pickle: - $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle - @echo - @echo "Build finished; now you can process the pickle files." - -json: - $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json - @echo - @echo "Build finished; now you can process the JSON files." - -htmlhelp: - $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp - @echo - @echo "Build finished; now you can run HTML Help Workshop with the" \ - ".hhp project file in $(BUILDDIR)/htmlhelp." - -qthelp: - $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp - @echo - @echo "Build finished; now you can run "qcollectiongenerator" with the" \ - ".qhcp project file in $(BUILDDIR)/qthelp, like this:" - @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/psutil.qhcp" - @echo "To view the help file:" - @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/psutil.qhc" - -devhelp: - $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp - @echo - @echo "Build finished." - @echo "To view the help file:" - @echo "# mkdir -p $$HOME/.local/share/devhelp/psutil" - @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/psutil" - @echo "# devhelp" - -epub: - $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub - @echo - @echo "Build finished. The epub file is in $(BUILDDIR)/epub." - -latex: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo - @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." - @echo "Run \`make' in that directory to run these through (pdf)latex" \ - "(use \`make latexpdf' here to do that automatically)." - -latexpdf: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through pdflatex..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -latexpdfja: - $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex - @echo "Running LaTeX files through platex and dvipdfmx..." - $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja - @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." - -text: - $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text - @echo - @echo "Build finished. The text files are in $(BUILDDIR)/text." - -man: - $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man - @echo - @echo "Build finished. The manual pages are in $(BUILDDIR)/man." - -texinfo: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo - @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." - @echo "Run \`make' in that directory to run these through makeinfo" \ - "(use \`make info' here to do that automatically)." - -info: - $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo - @echo "Running Texinfo files through makeinfo..." - make -C $(BUILDDIR)/texinfo info - @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." - -gettext: - $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale - @echo - @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." - -changes: - $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes - @echo - @echo "The overview file is in $(BUILDDIR)/changes." - -linkcheck: - $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck - @echo - @echo "Link check complete; look for any errors in the above output " \ - "or in $(BUILDDIR)/linkcheck/output.txt." - -doctest: - $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest - @echo "Testing of doctests in the sources finished, look at the " \ - "results in $(BUILDDIR)/doctest/output.txt." - -xml: - $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml - @echo - @echo "Build finished. The XML files are in $(BUILDDIR)/xml." - -pseudoxml: - $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml - @echo - @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." diff --git a/python/psutil/docs/README b/python/psutil/docs/README deleted file mode 100644 index 3aaea8a5b..000000000 --- a/python/psutil/docs/README +++ /dev/null @@ -1,15 +0,0 @@ -About -===== - -This directory contains the reStructuredText (reST) sources to the psutil -documentation. You don't need to build them yourself, prebuilt versions are -available at https://pythonhosted.org/psutil/. -In case you want, you need to install sphinx first: - - $ pip install sphinx - -Then run: - - $ make html - -You'll then have an HTML version of the doc at _build/html/index.html.
\ No newline at end of file diff --git a/python/psutil/docs/_static/copybutton.js b/python/psutil/docs/_static/copybutton.js deleted file mode 100644 index 5d82c672b..000000000 --- a/python/psutil/docs/_static/copybutton.js +++ /dev/null @@ -1,57 +0,0 @@ -$(document).ready(function() { - /* Add a [>>>] button on the top-right corner of code samples to hide - * the >>> and ... prompts and the output and thus make the code - * copyable. */ - var div = $('.highlight-python .highlight,' + - '.highlight-python3 .highlight') - var pre = div.find('pre'); - - // get the styles from the current theme - pre.parent().parent().css('position', 'relative'); - var hide_text = 'Hide the prompts and output'; - var show_text = 'Show the prompts and output'; - var border_width = pre.css('border-top-width'); - var border_style = pre.css('border-top-style'); - var border_color = pre.css('border-top-color'); - var button_styles = { - 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', - 'border-color': border_color, 'border-style': border_style, - 'border-width': border_width, 'color': border_color, 'text-size': '75%', - 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em', - 'border-radius': '0 3px 0 0' - } - - // create and add the button to all the code blocks that contain >>> - div.each(function(index) { - var jthis = $(this); - if (jthis.find('.gp').length > 0) { - var button = $('<span class="copybutton">>>></span>'); - button.css(button_styles) - button.attr('title', hide_text); - jthis.prepend(button); - } - // tracebacks (.gt) contain bare text elements that need to be - // wrapped in a span to work with .nextUntil() (see later) - jthis.find('pre:has(.gt)').contents().filter(function() { - return ((this.nodeType == 3) && (this.data.trim().length > 0)); - }).wrap('<span>'); - }); - - // define the behavior of the button when it's clicked - $('.copybutton').toggle( - function() { - var button = $(this); - button.parent().find('.go, .gp, .gt').hide(); - button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden'); - button.css('text-decoration', 'line-through'); - button.attr('title', show_text); - }, - function() { - var button = $(this); - button.parent().find('.go, .gp, .gt').show(); - button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible'); - button.css('text-decoration', 'none'); - button.attr('title', hide_text); - }); -}); - diff --git a/python/psutil/docs/_static/favicon.ico b/python/psutil/docs/_static/favicon.ico Binary files differdeleted file mode 100644 index c9efc5844..000000000 --- a/python/psutil/docs/_static/favicon.ico +++ /dev/null diff --git a/python/psutil/docs/_static/logo.png b/python/psutil/docs/_static/logo.png Binary files differdeleted file mode 100644 index 7d975ec9d..000000000 --- a/python/psutil/docs/_static/logo.png +++ /dev/null diff --git a/python/psutil/docs/_static/sidebar.js b/python/psutil/docs/_static/sidebar.js deleted file mode 100644 index 337696391..000000000 --- a/python/psutil/docs/_static/sidebar.js +++ /dev/null @@ -1,161 +0,0 @@ -/* - * sidebar.js - * ~~~~~~~~~~ - * - * This script makes the Sphinx sidebar collapsible. - * - * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds in - * .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton used to - * collapse and expand the sidebar. - * - * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden and the - * width of the sidebar and the margin-left of the document are decreased. - * When the sidebar is expanded the opposite happens. This script saves a - * per-browser/per-session cookie used to remember the position of the sidebar - * among the pages. Once the browser is closed the cookie is deleted and the - * position reset to the default (expanded). - * - * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - * :license: BSD, see LICENSE for details. - * - */ - -$(function() { - // global elements used by the functions. - // the 'sidebarbutton' element is defined as global after its - // creation, in the add_sidebar_button function - var bodywrapper = $('.bodywrapper'); - var sidebar = $('.sphinxsidebar'); - var sidebarwrapper = $('.sphinxsidebarwrapper'); - - // original margin-left of the bodywrapper and width of the sidebar - // with the sidebar expanded - var bw_margin_expanded = bodywrapper.css('margin-left'); - var ssb_width_expanded = sidebar.width(); - - // margin-left of the bodywrapper and width of the sidebar - // with the sidebar collapsed - var bw_margin_collapsed = '.8em'; - var ssb_width_collapsed = '.8em'; - - // colors used by the current theme - var dark_color = '#AAAAAA'; - var light_color = '#CCCCCC'; - - function sidebar_is_collapsed() { - return sidebarwrapper.is(':not(:visible)'); - } - - function toggle_sidebar() { - if (sidebar_is_collapsed()) - expand_sidebar(); - else - collapse_sidebar(); - } - - function collapse_sidebar() { - sidebarwrapper.hide(); - sidebar.css('width', ssb_width_collapsed); - bodywrapper.css('margin-left', bw_margin_collapsed); - sidebarbutton.css({ - 'margin-left': '0', - //'height': bodywrapper.height(), - 'height': sidebar.height(), - 'border-radius': '5px' - }); - sidebarbutton.find('span').text('»'); - sidebarbutton.attr('title', _('Expand sidebar')); - document.cookie = 'sidebar=collapsed'; - } - - function expand_sidebar() { - bodywrapper.css('margin-left', bw_margin_expanded); - sidebar.css('width', ssb_width_expanded); - sidebarwrapper.show(); - sidebarbutton.css({ - 'margin-left': ssb_width_expanded-12, - //'height': bodywrapper.height(), - 'height': sidebar.height(), - 'border-radius': '0 5px 5px 0' - }); - sidebarbutton.find('span').text('«'); - sidebarbutton.attr('title', _('Collapse sidebar')); - //sidebarwrapper.css({'padding-top': - // Math.max(window.pageYOffset - sidebarwrapper.offset().top, 10)}); - document.cookie = 'sidebar=expanded'; - } - - function add_sidebar_button() { - sidebarwrapper.css({ - 'float': 'left', - 'margin-right': '0', - 'width': ssb_width_expanded - 28 - }); - // create the button - sidebar.append( - '<div id="sidebarbutton"><span>«</span></div>' - ); - var sidebarbutton = $('#sidebarbutton'); - // find the height of the viewport to center the '<<' in the page - var viewport_height; - if (window.innerHeight) - viewport_height = window.innerHeight; - else - viewport_height = $(window).height(); - var sidebar_offset = sidebar.offset().top; - - var sidebar_height = sidebar.height(); - //var sidebar_height = Math.max(bodywrapper.height(), sidebar.height()); - sidebarbutton.find('span').css({ - 'display': 'block', - 'margin-top': sidebar_height/2 - 10 - //'margin-top': (viewport_height - sidebar.position().top - 20) / 2 - //'position': 'fixed', - //'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10 - }); - - sidebarbutton.click(toggle_sidebar); - sidebarbutton.attr('title', _('Collapse sidebar')); - sidebarbutton.css({ - 'border-radius': '0 5px 5px 0', - 'color': '#444444', - 'background-color': '#CCCCCC', - 'font-size': '1.2em', - 'cursor': 'pointer', - 'height': sidebar_height, - 'padding-top': '1px', - 'padding-left': '1px', - 'margin-left': ssb_width_expanded - 12 - }); - - sidebarbutton.hover( - function () { - $(this).css('background-color', dark_color); - }, - function () { - $(this).css('background-color', light_color); - } - ); - } - - function set_position_from_cookie() { - if (!document.cookie) - return; - var items = document.cookie.split(';'); - for(var k=0; k<items.length; k++) { - var key_val = items[k].split('='); - var key = key_val[0]; - if (key == 'sidebar') { - var value = key_val[1]; - if ((value == 'collapsed') && (!sidebar_is_collapsed())) - collapse_sidebar(); - else if ((value == 'expanded') && (sidebar_is_collapsed())) - expand_sidebar(); - } - } - } - - add_sidebar_button(); - var sidebarbutton = $('#sidebarbutton'); - set_position_from_cookie(); -}); diff --git a/python/psutil/docs/_template/globaltoc.html b/python/psutil/docs/_template/globaltoc.html deleted file mode 100644 index f5fbb406c..000000000 --- a/python/psutil/docs/_template/globaltoc.html +++ /dev/null @@ -1,12 +0,0 @@ -{# - basic/globaltoc.html - ~~~~~~~~~~~~~~~~~~~~ - - Sphinx sidebar template: global table of contents. - - :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. - :license: BSD, see LICENSE for details. -#} -<h3>{{ _('Manual') }}</h3> -{{ toctree() }} -<a href="{{ pathto(master_doc) }}">Back to Welcome</a> diff --git a/python/psutil/docs/_template/indexcontent.html b/python/psutil/docs/_template/indexcontent.html deleted file mode 100644 index dd5e7249a..000000000 --- a/python/psutil/docs/_template/indexcontent.html +++ /dev/null @@ -1,4 +0,0 @@ -{% extends "defindex.html" %} -{% block tables %} - -{% endblock %} diff --git a/python/psutil/docs/_template/indexsidebar.html b/python/psutil/docs/_template/indexsidebar.html deleted file mode 100644 index 903675d10..000000000 --- a/python/psutil/docs/_template/indexsidebar.html +++ /dev/null @@ -1,8 +0,0 @@ -<h3>Useful links</h3> -<ul> - <li><a href="https://github.com/giampaolo/psutil">Github project</a></li> - <li><a href="http://grodola.blogspot.com/search/label/psutil">Blog</a></li> - <li><a href="https://pypi.python.org/pypi?:action=display&name=psutil#downloads">Download</a></li> - <li><a href="https://github.com/giampaolo/psutil/issues">Issues</a></li> - <li><a href="http://groups.google.com/group/psutil/topics">Forum</a></li> -</ul> diff --git a/python/psutil/docs/_template/page.html b/python/psutil/docs/_template/page.html deleted file mode 100644 index 04b47b415..000000000 --- a/python/psutil/docs/_template/page.html +++ /dev/null @@ -1,66 +0,0 @@ -{% extends "!page.html" %} -{% block extrahead %} -{{ super() }} -{% if not embedded %}<script type="text/javascript" src="{{ pathto('_static/copybutton.js', 1) }}"></script>{% endif %} -<script type="text/javascript"> - - // Store editor pop-up help state in localStorage - // so it does not re-pop-up itself between page loads. - // Do not even to pretend to support IE gracefully. - (function($) { - - $(document).ready(function() { - var box = $("#editor-trap"); - var klass = "toggled"; - var storageKey = "toggled"; - - function toggle() { - box.toggleClass(klass); - // Store the toggle status in local storage as "has value string" or null - window.localStorage.setItem(storageKey, box.hasClass(klass) ? "toggled" : "not-toggled"); - } - - box.click(toggle); - - // Check the persistent state of the editor pop-up - // Note that localStorage does not necessarily support boolean values (ugh!) - // http://stackoverflow.com/questions/3263161/cannot-set-boolean-values-in-localstorage - var v = window.localStorage.getItem(storageKey); - if(v == "toggled" || !v) { - box.addClass(klass); - } - - }); - - })(jQuery); -</script> -<script type="text/javascript"> - - var _gaq = _gaq || []; - _gaq.push(['_setAccount', 'UA-2097050-4']); - _gaq.push(['_trackPageview']); - - (function() { - var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; - ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; - var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); - })(); - -</script> -{% endblock %} - -{% block rootrellink %} - <li><a href="https://github.com/giampaolo/psutil/"><img src="{{ pathto('_static/logo.png', 1) }}" style="height: 30px; vertical-align: middle; padding-right: 1em;" /> Project Homepage</a>{{ reldelim1 }}</li> - <li><a href="{{ pathto('index') }}">{{ shorttitle }}</a>{{ reldelim1 }}</li> -{% endblock %} - - -{% block footer %} -<div class="footer"> - © Copyright {{ copyright|e }}. - <br /> - Last updated on {{ last_updated|e }}. - <br /> - Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> {{ sphinx_version|e }}. -</div> -{% endblock %}
\ No newline at end of file diff --git a/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css b/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css deleted file mode 100644 index 4196e5582..000000000 --- a/python/psutil/docs/_themes/pydoctheme/static/pydoctheme.css +++ /dev/null @@ -1,187 +0,0 @@ -@import url("default.css"); - -body { - background-color: white; - margin-left: 1em; - margin-right: 1em; -} - -div.related { - margin-bottom: 1.2em; - padding: 0.5em 0; - border-top: 1px solid #ccc; - margin-top: 0.5em; -} - -div.related a:hover { - color: #0095C4; -} - -div.related:first-child { - border-top: 0; - padding-top: 0; - border-bottom: 1px solid #ccc; -} - -div.sphinxsidebar { - background-color: #eeeeee; - border-radius: 5px; - line-height: 130%; - font-size: smaller; -} - -div.sphinxsidebar h3, div.sphinxsidebar h4 { - margin-top: 1.5em; -} - -div.sphinxsidebarwrapper > h3:first-child { - margin-top: 0.2em; -} - -div.sphinxsidebarwrapper > ul > li > ul > li { - margin-bottom: 0.4em; -} - -div.sphinxsidebar a:hover { - color: #0095C4; -} - -div.sphinxsidebar input { - font-family: 'Lucida Grande','Lucida Sans','DejaVu Sans',Arial,sans-serif; - border: 1px solid #999999; - font-size: smaller; - border-radius: 3px; -} - -div.sphinxsidebar input[type=text] { - max-width: 150px; -} - -div.body { - padding: 0 0 0 1.2em; -} - -div.body p { - line-height: 140%; -} - -div.body h1, div.body h2, div.body h3, div.body h4, div.body h5, div.body h6 { - margin: 0; - border: 0; - padding: 0.3em 0; -} - -div.body hr { - border: 0; - background-color: #ccc; - height: 1px; -} - -div.body pre { - border-radius: 3px; - border: 1px solid #ac9; -} - -div.body div.admonition, div.body div.impl-detail { - border-radius: 3px; -} - -div.body div.impl-detail > p { - margin: 0; -} - -div.body div.seealso { - border: 1px solid #dddd66; -} - -div.body a { - color: #00608f; -} - -div.body a:visited { - color: #30306f; -} - -div.body a:hover { - color: #00B0E4; -} - -tt, pre { - font-family: monospace, sans-serif; - font-size: 96.5%; -} - -div.body tt { - border-radius: 3px; -} - -div.body tt.descname { - font-size: 120%; -} - -div.body tt.xref, div.body a tt { - font-weight: normal; -} - -p.deprecated { - border-radius: 3px; -} - -table.docutils { - border: 1px solid #ddd; - min-width: 20%; - border-radius: 3px; - margin-top: 10px; - margin-bottom: 10px; -} - -table.docutils td, table.docutils th { - border: 1px solid #ddd !important; - border-radius: 3px; -} - -table p, table li { - text-align: left !important; -} - -table.docutils th { - background-color: #eee; - padding: 0.3em 0.5em; -} - -table.docutils td { - background-color: white; - padding: 0.3em 0.5em; -} - -table.footnote, table.footnote td { - border: 0 !important; -} - -div.footer { - line-height: 150%; - margin-top: -2em; - text-align: right; - width: auto; - margin-right: 10px; -} - -div.footer a:hover { - color: #0095C4; -} - -div.body h1, -div.body h2, -div.body h3 { - background-color: #EAEAEA; - border-bottom: 1px solid #CCC; - padding-top: 2px; - padding-bottom: 2px; - padding-left: 5px; - margin-top: 5px; - margin-bottom: 5px; -} - -div.body h2 { - padding-left:10px; -} diff --git a/python/psutil/docs/_themes/pydoctheme/theme.conf b/python/psutil/docs/_themes/pydoctheme/theme.conf deleted file mode 100644 index 95b97e536..000000000 --- a/python/psutil/docs/_themes/pydoctheme/theme.conf +++ /dev/null @@ -1,23 +0,0 @@ -[theme] -inherit = default -stylesheet = pydoctheme.css -pygments_style = sphinx - -[options] -bodyfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif -headfont = 'Lucida Grande', 'Lucida Sans', 'DejaVu Sans', Arial, sans-serif -footerbgcolor = white -footertextcolor = #555555 -relbarbgcolor = white -relbartextcolor = #666666 -relbarlinkcolor = #444444 -sidebarbgcolor = white -sidebartextcolor = #444444 -sidebarlinkcolor = #444444 -bgcolor = white -textcolor = #222222 -linkcolor = #0090c0 -visitedlinkcolor = #00608f -headtextcolor = #1a1a1a -headbgcolor = white -headlinkcolor = #aaaaaa diff --git a/python/psutil/docs/conf.py b/python/psutil/docs/conf.py deleted file mode 100644 index ad880110f..000000000 --- a/python/psutil/docs/conf.py +++ /dev/null @@ -1,248 +0,0 @@ -# -*- coding: utf-8 -*- -# -# psutil documentation build configuration file, created by -# sphinx-quickstart. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - -import datetime -import os - - -PROJECT_NAME = "psutil" -AUTHOR = "Giampaolo Rodola'" -THIS_YEAR = str(datetime.datetime.utcnow().year) -HERE = os.path.abspath(os.path.dirname(__file__)) - - -def get_version(): - INIT = os.path.abspath(os.path.join(HERE, '../psutil/__init__.py')) - with open(INIT, 'r') as f: - for line in f: - if line.startswith('__version__'): - ret = eval(line.strip().split(' = ')[1]) - assert ret.count('.') == 2, ret - for num in ret.split('.'): - assert num.isdigit(), ret - return ret - else: - raise ValueError("couldn't find version string") - -VERSION = get_version() - -# If your documentation needs a minimal Sphinx version, state it here. -needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = ['sphinx.ext.autodoc', - 'sphinx.ext.coverage', - 'sphinx.ext.pngmath', - 'sphinx.ext.viewcode', - 'sphinx.ext.intersphinx'] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_template'] - -# The suffix of source filenames. -source_suffix = '.rst' - -# The encoding of source files. -# source_encoding = 'utf-8-sig' - -# The master toctree document. -master_doc = 'index' - -# General information about the project. -project = PROJECT_NAME -copyright = '2009-%s, %s' % (THIS_YEAR, AUTHOR) - -# The version info for the project you're documenting, acts as replacement for -# |version| and |release|, also used in various other places throughout the -# built documents. -# -# The short X.Y version. -version = VERSION - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -# today = '' -# Else, today_fmt is used as the format for a strftime call. -# today_fmt = '%B %d, %Y' - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -exclude_patterns = ['_build'] - -# The reST default role (used for this markup: `text`) to use for all -# documents. -# default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -add_function_parentheses = True -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -# add_module_names = True - -autodoc_docstring_signature = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -# show_authors = False - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' - -# A list of ignored prefixes for module index sorting. -# modindex_common_prefix = [] - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -html_theme = 'pydoctheme' -html_theme_options = {'collapsiblesidebar': True} - -# Add any paths that contain custom themes here, relative to this directory. -html_theme_path = ["_themes"] - -# The name for this set of Sphinx documents. If None, it defaults to -# "<project> v<release> documentation". -html_title = "{project} {version} documentation".format(**locals()) - -# A shorter title for the navigation bar. Default is the same as html_title. -# html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -# html_logo = 'logo.png' - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -html_favicon = '_static/favicon.ico' - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. -html_last_updated_fmt = '%b %d, %Y' - -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -html_sidebars = { - 'index': 'indexsidebar.html', - '**': ['globaltoc.html', - 'relations.html', - 'sourcelink.html', - 'searchbox.html'] -} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -# html_additional_pages = { -# 'index': 'indexcontent.html', -# } - -# If false, no module index is generated. -html_domain_indices = False - -# If false, no index is generated. -html_use_index = True - -# If true, the index is split into individual pages for each letter. -# html_split_index = False - -# If true, links to the reST sources are added to the pages. -# html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -# html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -# html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a <link> tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -# html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -# html_file_suffix = None - -# Output file base name for HTML help builder. -htmlhelp_basename = '%s-doc' % PROJECT_NAME - -# -- Options for LaTeX output ------------------------------------------------ - -# The paper size ('letter' or 'a4'). -# latex_paper_size = 'letter' - -# The font size ('10pt', '11pt' or '12pt'). -# latex_font_size = '10pt' - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, author, documentclass -# [howto/manual]). -latex_documents = [ - ('index', '%s.tex' % PROJECT_NAME, - '%s documentation' % PROJECT_NAME, AUTHOR), -] - -# The name of an image file (relative to this directory) to place at -# the top of the title page. -# latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -# latex_use_parts = False - -# If true, show page references after internal links. -# latex_show_pagerefs = False - -# If true, show URL addresses after external links. -# latex_show_urls = False - -# Additional stuff for the LaTeX preamble. -# latex_preamble = '' - -# Documents to append as an appendix to all manuals. -# latex_appendices = [] - -# If false, no module index is generated. -# latex_domain_indices = True - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - ('index', PROJECT_NAME, '%s documentation' % PROJECT_NAME, [AUTHOR], 1) -] - -# If true, show URL addresses after external links. -# man_show_urls = False diff --git a/python/psutil/docs/index.rst b/python/psutil/docs/index.rst deleted file mode 100644 index 443019226..000000000 --- a/python/psutil/docs/index.rst +++ /dev/null @@ -1,1400 +0,0 @@ -.. module:: psutil - :synopsis: psutil module -.. moduleauthor:: Giampaolo Rodola' <grodola@gmail.com> - -.. warning:: - - This documentation refers to new 2.X version of psutil. - Instructions on how to port existing 1.2.1 code are - `here <http://grodola.blogspot.com/2014/01/psutil-20-porting.html>`__. - Old 1.2.1 documentation is still available - `here <https://code.google.com/p/psutil/wiki/Documentation>`__. - -psutil documentation -==================== - -Quick links ------------ - -* `Home page <https://github.com/giampaolo/psutil>`__ -* `Blog <http://grodola.blogspot.com/search/label/psutil>`__ -* `Forum <http://groups.google.com/group/psutil/topics>`__ -* `Download <https://pypi.python.org/pypi?:action=display&name=psutil#downloads>`__ -* `Installation <https://github.com/giampaolo/psutil/blob/master/INSTALL.rst>`_ -* `Development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_ -* `What's new <https://github.com/giampaolo/psutil/blob/master/HISTORY.rst>`__ - -About ------ - -From project's home page: - - psutil (python system and process utilities) is a cross-platform library for - retrieving information on running - **processes** and **system utilization** (CPU, memory, disks, network) in - **Python**. - It is useful mainly for **system monitoring**, **profiling** and **limiting - process resources** and **management of running processes**. - It implements many functionalities offered by command line tools - such as: *ps, top, lsof, netstat, ifconfig, who, df, kill, free, nice, - ionice, iostat, iotop, uptime, pidof, tty, taskset, pmap*. - It currently supports **Linux, Windows, OSX, FreeBSD** and **Sun Solaris**, - both **32-bit** and **64-bit** architectures, with Python versions from - **2.6 to 3.4** (users of Python 2.4 and 2.5 may use `2.1.3 <https://pypi.python.org/pypi?name=psutil&version=2.1.3&:action=files>`__ version). - `PyPy <http://pypy.org/>`__ is also known to work. - -The psutil documentation you're reading is distributed as a single HTML page. - -System related functions -======================== - -CPU ---- - -.. function:: cpu_times(percpu=False) - - Return system CPU times as a namedtuple. - Every attribute represents the seconds the CPU has spent in the given mode. - The attributes availability varies depending on the platform: - - - **user** - - **system** - - **idle** - - **nice** *(UNIX)* - - **iowait** *(Linux)* - - **irq** *(Linux, FreeBSD)* - - **softirq** *(Linux)* - - **steal** *(Linux 2.6.11+)* - - **guest** *(Linux 2.6.24+)* - - **guest_nice** *(Linux 3.2.0+)* - - When *percpu* is ``True`` return a list of namedtuples for each logical CPU - on the system. - First element of the list refers to first CPU, second element to second CPU - and so on. - The order of the list is consistent across calls. - Example output on Linux: - - >>> import psutil - >>> psutil.cpu_times() - scputimes(user=17411.7, nice=77.99, system=3797.02, idle=51266.57, iowait=732.58, irq=0.01, softirq=142.43, steal=0.0, guest=0.0, guest_nice=0.0) - -.. function:: cpu_percent(interval=None, percpu=False) - - Return a float representing the current system-wide CPU utilization as a - percentage. When *interval* is > ``0.0`` compares system CPU times elapsed - before and after the interval (blocking). - When *interval* is ``0.0`` or ``None`` compares system CPU times elapsed - since last call or module import, returning immediately. - That means the first time this is called it will return a meaningless ``0.0`` - value which you are supposed to ignore. - In this case is recommended for accuracy that this function be called with at - least ``0.1`` seconds between calls. - When *percpu* is ``True`` returns a list of floats representing the - utilization as a percentage for each CPU. - First element of the list refers to first CPU, second element to second CPU - and so on. The order of the list is consistent across calls. - - >>> import psutil - >>> # blocking - >>> psutil.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> psutil.cpu_percent(interval=None) - 2.9 - >>> # blocking, per-cpu - >>> psutil.cpu_percent(interval=1, percpu=True) - [2.0, 1.0] - >>> - - .. warning:: - - the first time this function is called with *interval* = ``0.0`` or ``None`` - it will return a meaningless ``0.0`` value which you are supposed to - ignore. - -.. function:: cpu_times_percent(interval=None, percpu=False) - - Same as :func:`cpu_percent()` but provides utilization percentages for each - specific CPU time as is returned by - :func:`psutil.cpu_times(percpu=True)<cpu_times()>`. - *interval* and - *percpu* arguments have the same meaning as in :func:`cpu_percent()`. - - .. warning:: - - the first time this function is called with *interval* = ``0.0`` or - ``None`` it will return a meaningless ``0.0`` value which you are supposed - to ignore. - -.. function:: cpu_count(logical=True) - - Return the number of logical CPUs in the system (same as - `os.cpu_count() <http://docs.python.org/3/library/os.html#os.cpu_count>`__ - in Python 3.4). - If *logical* is ``False`` return the number of physical cores only (hyper - thread CPUs are excluded). Return ``None`` if undetermined. - - >>> import psutil - >>> psutil.cpu_count() - 4 - >>> psutil.cpu_count(logical=False) - 2 - >>> - -Memory ------- - -.. function:: virtual_memory() - - Return statistics about system memory usage as a namedtuple including the - following fields, expressed in bytes: - - - **total**: total physical memory available. - - **available**: the actual amount of available memory that can be given - instantly to processes that request more memory in bytes; this is - calculated by summing different memory values depending on the platform - (e.g. free + buffers + cached on Linux) and it is supposed to be used to - monitor actual memory usage in a cross platform fashion. - - **percent**: the percentage usage calculated as - ``(total - available) / total * 100``. - - **used**: memory used, calculated differently depending on the platform and - designed for informational purposes only. - - **free**: memory not being used at all (zeroed) that is readily available; - note that this doesn't reflect the actual memory available (use 'available' - instead). - - Platform-specific fields: - - - **active**: (UNIX): memory currently in use or very recently used, and so - it is in RAM. - - **inactive**: (UNIX): memory that is marked as not used. - - **buffers**: (Linux, BSD): cache for things like file system metadata. - - **cached**: (Linux, BSD): cache for various things. - - **wired**: (BSD, OSX): memory that is marked to always stay in RAM. It is - never moved to disk. - - **shared**: (BSD): memory that may be simultaneously accessed by multiple - processes. - - The sum of **used** and **available** does not necessarily equal **total**. - On Windows **available** and **free** are the same. - See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__ - script providing an example on how to convert bytes in a human readable form. - - >>> import psutil - >>> mem = psutil.virtual_memory() - >>> mem - svmem(total=8374149120L, available=1247768576L, percent=85.1, used=8246628352L, free=127520768L, active=3208777728, inactive=1133408256, buffers=342413312L, cached=777834496) - >>> - >>> THRESHOLD = 100 * 1024 * 1024 # 100MB - >>> if mem.available <= THRESHOLD: - ... print("warning") - ... - >>> - - -.. function:: swap_memory() - - Return system swap memory statistics as a namedtuple including the following - fields: - - * **total**: total swap memory in bytes - * **used**: used swap memory in bytes - * **free**: free swap memory in bytes - * **percent**: the percentage usage calculated as ``(total - available) / total * 100`` - * **sin**: the number of bytes the system has swapped in from disk - (cumulative) - * **sout**: the number of bytes the system has swapped out from disk - (cumulative) - - **sin** and **sout** on Windows are meaningless and are always set to ``0``. - See `examples/meminfo.py <https://github.com/giampaolo/psutil/blob/master/examples/meminfo.py>`__ - script providing an example on how to convert bytes in a human readable form. - - >>> import psutil - >>> psutil.swap_memory() - sswap(total=2097147904L, used=886620160L, free=1210527744L, percent=42.3, sin=1050411008, sout=1906720768) - -Disks ------ - -.. function:: disk_partitions(all=False) - - Return all mounted disk partitions as a list of namedtuples including device, - mount point and filesystem type, similarly to "df" command on UNIX. If *all* - parameter is ``False`` return physical devices only (e.g. hard disks, cd-rom - drives, USB keys) and ignore all others (e.g. memory partitions such as - `/dev/shm <http://www.cyberciti.biz/tips/what-is-devshm-and-its-practical-usage.html>`__). - Namedtuple's **fstype** field is a string which varies depending on the - platform. - On Linux it can be one of the values found in /proc/filesystems (e.g. - ``'ext3'`` for an ext3 hard drive o ``'iso9660'`` for the CD-ROM drive). - On Windows it is determined via - `GetDriveType <http://msdn.microsoft.com/en-us/library/aa364939(v=vs.85).aspx>`__ - and can be either ``"removable"``, ``"fixed"``, ``"remote"``, ``"cdrom"``, - ``"unmounted"`` or ``"ramdisk"``. On OSX and FreeBSD it is retrieved via - `getfsstat(2) <http://www.manpagez.com/man/2/getfsstat/>`__. See - `disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__ - script providing an example usage. - - >>> import psutil - >>> psutil.disk_partitions() - [sdiskpart(device='/dev/sda3', mountpoint='/', fstype='ext4', opts='rw,errors=remount-ro'), - sdiskpart(device='/dev/sda7', mountpoint='/home', fstype='ext4', opts='rw')] - -.. function:: disk_usage(path) - - Return disk usage statistics about the given *path* as a namedtuple including - **total**, **used** and **free** space expressed in bytes, plus the - **percentage** usage. - `OSError <http://docs.python.org/3/library/exceptions.html#OSError>`__ is - raised if *path* does not exist. See - `examples/disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__ - script providing an example usage. Starting from - `Python 3.3 <http://bugs.python.org/issue12442>`__ this is also - available as - `shutil.disk_usage() <http://docs.python.org/3/library/shutil.html#shutil.disk_usage>`__. - See - `disk_usage.py <https://github.com/giampaolo/psutil/blob/master/examples/disk_usage.py>`__ - script providing an example usage. - - >>> import psutil - >>> psutil.disk_usage('/') - sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5) - -.. function:: disk_io_counters(perdisk=False) - - Return system-wide disk I/O statistics as a namedtuple including the - following fields: - - - **read_count**: number of reads - - **write_count**: number of writes - - **read_bytes**: number of bytes read - - **write_bytes**: number of bytes written - - **read_time**: time spent reading from disk (in milliseconds) - - **write_time**: time spent writing to disk (in milliseconds) - - If *perdisk* is ``True`` return the same information for every physical disk - installed on the system as a dictionary with partition names as the keys and - the namedtuple described above as the values. - See `examples/iotop.py <https://github.com/giampaolo/psutil/blob/master/examples/iotop.py>`__ - for an example application. - - >>> import psutil - >>> psutil.disk_io_counters() - sdiskio(read_count=8141, write_count=2431, read_bytes=290203, write_bytes=537676, read_time=5868, write_time=94922) - >>> - >>> psutil.disk_io_counters(perdisk=True) - {'sda1': sdiskio(read_count=920, write_count=1, read_bytes=2933248, write_bytes=512, read_time=6016, write_time=4), - 'sda2': sdiskio(read_count=18707, write_count=8830, read_bytes=6060, write_bytes=3443, read_time=24585, write_time=1572), - 'sdb1': sdiskio(read_count=161, write_count=0, read_bytes=786432, write_bytes=0, read_time=44, write_time=0)} - -Network -------- - -.. function:: net_io_counters(pernic=False) - - Return system-wide network I/O statistics as a namedtuple including the - following attributes: - - - **bytes_sent**: number of bytes sent - - **bytes_recv**: number of bytes received - - **packets_sent**: number of packets sent - - **packets_recv**: number of packets received - - **errin**: total number of errors while receiving - - **errout**: total number of errors while sending - - **dropin**: total number of incoming packets which were dropped - - **dropout**: total number of outgoing packets which were dropped (always 0 - on OSX and BSD) - - If *pernic* is ``True`` return the same information for every network - interface installed on the system as a dictionary with network interface - names as the keys and the namedtuple described above as the values. - See `examples/nettop.py <https://github.com/giampaolo/psutil/blob/master/examples/nettop.py>`__ - for an example application. - - >>> import psutil - >>> psutil.net_io_counters() - snetio(bytes_sent=14508483, bytes_recv=62749361, packets_sent=84311, packets_recv=94888, errin=0, errout=0, dropin=0, dropout=0) - >>> - >>> psutil.net_io_counters(pernic=True) - {'lo': snetio(bytes_sent=547971, bytes_recv=547971, packets_sent=5075, packets_recv=5075, errin=0, errout=0, dropin=0, dropout=0), - 'wlan0': snetio(bytes_sent=13921765, bytes_recv=62162574, packets_sent=79097, packets_recv=89648, errin=0, errout=0, dropin=0, dropout=0)} - -.. function:: net_connections(kind='inet') - - Return system-wide socket connections as a list of namedtuples. - Every namedtuple provides 7 attributes: - - - **fd**: the socket file descriptor, if retrievable, else ``-1``. - If the connection refers to the current process this may be passed to - `socket.fromfd() <http://docs.python.org/library/socket.html#socket.fromfd>`__ - to obtain a usable socket object. - - **family**: the address family, either `AF_INET - <http://docs.python.org//library/socket.html#socket.AF_INET>`__, - `AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__ - or `AF_UNIX <http://docs.python.org//library/socket.html#socket.AF_UNIX>`__. - - **type**: the address type, either `SOCK_STREAM - <http://docs.python.org//library/socket.html#socket.SOCK_STREAM>`__ or - `SOCK_DGRAM - <http://docs.python.org//library/socket.html#socket.SOCK_DGRAM>`__. - - **laddr**: the local address as a ``(ip, port)`` tuple or a ``path`` - in case of AF_UNIX sockets. - - **raddr**: the remote address as a ``(ip, port)`` tuple or an absolute - ``path`` in case of UNIX sockets. - When the remote endpoint is not connected you'll get an empty tuple - (AF_INET*) or ``None`` (AF_UNIX). - On Linux AF_UNIX sockets will always have this set to ``None``. - - **status**: represents the status of a TCP connection. The return value - is one of the :data:`psutil.CONN_* <psutil.CONN_ESTABLISHED>` constants - (a string). - For UDP and UNIX sockets this is always going to be - :const:`psutil.CONN_NONE`. - - **pid**: the PID of the process which opened the socket, if retrievable, - else ``None``. On some platforms (e.g. Linux) the availability of this - field changes depending on process privileges (root is needed). - - The *kind* parameter is a string which filters for connections that fit the - following criteria: - - .. table:: - - +----------------+-----------------------------------------------------+ - | **Kind value** | **Connections using** | - +================+=====================================================+ - | "inet" | IPv4 and IPv6 | - +----------------+-----------------------------------------------------+ - | "inet4" | IPv4 | - +----------------+-----------------------------------------------------+ - | "inet6" | IPv6 | - +----------------+-----------------------------------------------------+ - | "tcp" | TCP | - +----------------+-----------------------------------------------------+ - | "tcp4" | TCP over IPv4 | - +----------------+-----------------------------------------------------+ - | "tcp6" | TCP over IPv6 | - +----------------+-----------------------------------------------------+ - | "udp" | UDP | - +----------------+-----------------------------------------------------+ - | "udp4" | UDP over IPv4 | - +----------------+-----------------------------------------------------+ - | "udp6" | UDP over IPv6 | - +----------------+-----------------------------------------------------+ - | "unix" | UNIX socket (both UDP and TCP protocols) | - +----------------+-----------------------------------------------------+ - | "all" | the sum of all the possible families and protocols | - +----------------+-----------------------------------------------------+ - - On OSX this function requires root privileges. - To get per-process connections use :meth:`Process.connections`. - Also, see - `netstat.py sample script <https://github.com/giampaolo/psutil/blob/master/examples/netstat.py>`__. - Example: - - >>> import psutil - >>> psutil.net_connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED', pid=1254), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING', pid=2987), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED', pid=None), - pconn(fd=-1, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT', pid=None) - ...] - - .. note:: (OSX) :class:`psutil.AccessDenied` is always raised unless running - as root (lsof does the same). - .. note:: (Solaris) UNIX sockets are not supported. - - .. versionadded:: 2.1.0 - -.. function:: net_if_addrs() - - Return the addresses associated to each NIC (network interface card) - installed on the system as a dictionary whose keys are the NIC names and - value is a list of namedtuples for each address assigned to the NIC. - Each namedtuple includes 4 fields: - - - **family** - - **address** - - **netmask** - - **broadcast** - - *family* can be either - `AF_INET <http://docs.python.org//library/socket.html#socket.AF_INET>`__, - `AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__ - or :const:`psutil.AF_LINK`, which refers to a MAC address. - *address* is the primary address, *netmask* and *broadcast* may be ``None``. - Example:: - - >>> import psutil - >>> psutil.net_if_addrs() - {'lo': [snic(family=<AddressFamily.AF_INET: 2>, address='127.0.0.1', netmask='255.0.0.0', broadcast='127.0.0.1'), - snic(family=<AddressFamily.AF_INET6: 10>, address='::1', netmask='ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='00:00:00:00:00:00', netmask=None, broadcast='00:00:00:00:00:00')], - 'wlan0': [snic(family=<AddressFamily.AF_INET: 2>, address='192.168.1.3', netmask='255.255.255.0', broadcast='192.168.1.255'), - snic(family=<AddressFamily.AF_INET6: 10>, address='fe80::c685:8ff:fe45:641%wlan0', netmask='ffff:ffff:ffff:ffff::', broadcast=None), - snic(family=<AddressFamily.AF_LINK: 17>, address='c4:85:08:45:06:41', netmask=None, broadcast='ff:ff:ff:ff:ff:ff')]} - >>> - - See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__ - for an example application. - - .. note:: if you're interested in others families (e.g. AF_BLUETOOTH) you can - use the more powerful `netifaces <https://pypi.python.org/pypi/netifaces/>`__ - extension. - - .. note:: you can have more than one address of the same family associated - with each interface (that's why dict values are lists). - - *New in 3.0.0* - -.. function:: net_if_stats() - - Return information about each NIC (network interface card) installed on the - system as a dictionary whose keys are the NIC names and value is a namedtuple - with the following fields: - - - **isup** - - **duplex** - - **speed** - - **mtu** - - *isup* is a boolean indicating whether the NIC is up and running, *duplex* - can be either :const:`NIC_DUPLEX_FULL`, :const:`NIC_DUPLEX_HALF` or - :const:`NIC_DUPLEX_UNKNOWN`, *speed* is the NIC speed expressed in mega bits - (MB), if it can't be determined (e.g. 'localhost') it will be set to ``0``, - *mtu* is the maximum transmission unit expressed in bytes. - See also `examples/ifconfig.py <https://github.com/giampaolo/psutil/blob/master/examples/ifconfig.py>`__ - for an example application. - Example: - - >>> import psutil - >>> psutil.net_if_stats() - {'eth0': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_FULL: 2>, speed=100, mtu=1500), - 'lo': snicstats(isup=True, duplex=<NicDuplex.NIC_DUPLEX_UNKNOWN: 0>, speed=0, mtu=65536)} - - *New in 3.0.0* - - -Other system info ------------------ - -.. function:: users() - - Return users currently connected on the system as a list of namedtuples - including the following fields: - - - **user**: the name of the user. - - **terminal**: the tty or pseudo-tty associated with the user, if any, - else ``None``. - - **host**: the host name associated with the entry, if any. - - **started**: the creation time as a floating point number expressed in - seconds since the epoch. - - Example:: - - >>> import psutil - >>> psutil.users() - [suser(name='giampaolo', terminal='pts/2', host='localhost', started=1340737536.0), - suser(name='giampaolo', terminal='pts/3', host='localhost', started=1340737792.0)] - -.. function:: boot_time() - - Return the system boot time expressed in seconds since the epoch. - Example: - - .. code-block:: python - - >>> import psutil, datetime - >>> psutil.boot_time() - 1389563460.0 - >>> datetime.datetime.fromtimestamp(psutil.boot_time()).strftime("%Y-%m-%d %H:%M:%S") - '2014-01-12 22:51:00' - -Processes -========= - -Functions ---------- - -.. function:: pids() - - Return a list of current running PIDs. To iterate over all processes - :func:`process_iter()` should be preferred. - -.. function:: pid_exists(pid) - - Check whether the given PID exists in the current process list. This is - faster than doing ``"pid in psutil.pids()"`` and should be preferred. - -.. function:: process_iter() - - Return an iterator yielding a :class:`Process` class instance for all running - processes on the local machine. - Every instance is only created once and then cached into an internal table - which is updated every time an element is yielded. - Cached :class:`Process` instances are checked for identity so that you're - safe in case a PID has been reused by another process, in which case the - cached instance is updated. - This is should be preferred over :func:`psutil.pids()` for iterating over - processes. - Sorting order in which processes are returned is - based on their PID. Example usage:: - - import psutil - - for proc in psutil.process_iter(): - try: - pinfo = proc.as_dict(attrs=['pid', 'name']) - except psutil.NoSuchProcess: - pass - else: - print(pinfo) - -.. function:: wait_procs(procs, timeout=None, callback=None) - - Convenience function which waits for a list of :class:`Process` instances to - terminate. Return a ``(gone, alive)`` tuple indicating which processes are - gone and which ones are still alive. The *gone* ones will have a new - *returncode* attribute indicating process exit status (it may be ``None``). - ``callback`` is a function which gets called every time a process terminates - (a :class:`Process` instance is passed as callback argument). Function will - return as soon as all processes terminate or when timeout occurs. Tipical use - case is: - - - send SIGTERM to a list of processes - - give them some time to terminate - - send SIGKILL to those ones which are still alive - - Example:: - - import psutil - - def on_terminate(proc): - print("process {} terminated with exit code {}".format(proc, proc.returncode)) - - procs = [...] # a list of Process instances - for p in procs: - p.terminate() - gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) - for p in alive: - p.kill() - -Exceptions ----------- - -.. class:: Error() - - Base exception class. All other exceptions inherit from this one. - -.. class:: NoSuchProcess(pid, name=None, msg=None) - - Raised by :class:`Process` class methods when no process with the given - *pid* is found in the current process list or when a process no longer - exists. "name" is the name the process had before disappearing - and gets set only if :meth:`Process.name()` was previosly called. - -.. class:: ZombieProcess(pid, name=None, ppid=None, msg=None) - - This may be raised by :class:`Process` class methods when querying a zombie - process on UNIX (Windows doesn't have zombie processes). Depending on the - method called the OS may be able to succeed in retrieving the process - information or not. - Note: this is a subclass of :class:`NoSuchProcess` so if you're not - interested in retrieving zombies (e.g. when using :func:`process_iter()`) - you can ignore this exception and just catch :class:`NoSuchProcess`. - - *New in 3.0.0* - -.. class:: AccessDenied(pid=None, name=None, msg=None) - - Raised by :class:`Process` class methods when permission to perform an - action is denied. "name" is the name of the process (may be ``None``). - -.. class:: TimeoutExpired(seconds, pid=None, name=None, msg=None) - - Raised by :meth:`Process.wait` if timeout expires and process is still - alive. - -Process class -------------- - -.. class:: Process(pid=None) - - Represents an OS process with the given *pid*. If *pid* is omitted current - process *pid* (`os.getpid() <http://docs.python.org/library/os.html#os.getpid>`__) - is used. - Raise :class:`NoSuchProcess` if *pid* does not exist. - When accessing methods of this class always be prepared to catch - :class:`NoSuchProcess` and :class:`AccessDenied` exceptions. - `hash() <http://docs.python.org/2/library/functions.html#hash>`__ builtin can - be used against instances of this class in order to identify a process - univocally over time (the hash is determined by mixing process PID - and creation time). As such it can also be used with - `set()s <http://docs.python.org/2/library/stdtypes.html#types-set>`__. - - .. warning:: - - the way this class is bound to a process is uniquely via its **PID**. - That means that if the :class:`Process` instance is old enough and - the PID has been reused by another process in the meantime you might end up - interacting with another process. - The only exceptions for which process identity is pre-emptively checked - (via PID + creation time) and guaranteed are for - :meth:`nice` (set), - :meth:`ionice` (set), - :meth:`cpu_affinity` (set), - :meth:`rlimit` (set), - :meth:`children`, - :meth:`parent`, - :meth:`suspend` - :meth:`resume`, - :meth:`send_signal`, - :meth:`terminate`, and - :meth:`kill` - methods. - To prevent this problem for all other methods you can use - :meth:`is_running()` before querying the process or use - :func:`process_iter()` in case you're iterating over all processes. - - .. attribute:: pid - - The process PID. - - .. method:: ppid() - - The process parent pid. On Windows the return value is cached after first - call. - - .. method:: name() - - The process name. The return value is cached after first call. - - .. method:: exe() - - The process executable as an absolute path. - On some systems this may also be an empty string. - The return value is cached after first call. - - .. method:: cmdline() - - The command line this process has been called with. - - .. method:: create_time() - - The process creation time as a floating point number expressed in seconds - since the epoch, in - `UTC <http://en.wikipedia.org/wiki/Coordinated_universal_time>`__. - The return value is cached after first call. - - >>> import psutil, datetime - >>> p = psutil.Process() - >>> p.create_time() - 1307289803.47 - >>> datetime.datetime.fromtimestamp(p.create_time()).strftime("%Y-%m-%d %H:%M:%S") - '2011-03-05 18:03:52' - - .. method:: as_dict(attrs=None, ad_value=None) - - Utility method returning process information as a hashable dictionary. - If *attrs* is specified it must be a list of strings reflecting available - :class:`Process` class's attribute names (e.g. ``['cpu_times', 'name']``) - else all public (read only) attributes are assumed. *ad_value* is the - value which gets assigned to a dict key in case :class:`AccessDenied` - or :class:`ZombieProcess` exception is raised when retrieving that - particular process information. - - >>> import psutil - >>> p = psutil.Process() - >>> p.as_dict(attrs=['pid', 'name', 'username']) - {'username': 'giampaolo', 'pid': 12366, 'name': 'python'} - - .. versionchanged:: 3.0.0 *ad_value* is used also when incurring into - :class:`ZombieProcess` exception, not only :class:`AccessDenied` - - .. method:: parent() - - Utility method which returns the parent process as a :class:`Process` - object pre-emptively checking whether PID has been reused. If no parent - PID is known return ``None``. - - .. method:: status() - - The current process status as a string. The returned string is one of the - :data:`psutil.STATUS_*<psutil.STATUS_RUNNING>` constants. - - .. method:: cwd() - - The process current working directory as an absolute path. - - .. method:: username() - - The name of the user that owns the process. On UNIX this is calculated by - using real process uid. - - .. method:: uids() - - The **real**, **effective** and **saved** user ids of this process as a - namedtuple. This is the same as - `os.getresuid() <http://docs.python.org//library/os.html#os.getresuid>`__ - but can be used for every process PID. - - Availability: UNIX - - .. method:: gids() - - The **real**, **effective** and **saved** group ids of this process as a - namedtuple. This is the same as - `os.getresgid() <http://docs.python.org//library/os.html#os.getresgid>`__ - but can be used for every process PID. - - Availability: UNIX - - .. method:: terminal() - - The terminal associated with this process, if any, else ``None``. This is - similar to "tty" command but can be used for every process PID. - - Availability: UNIX - - .. method:: nice(value=None) - - Get or set process - `niceness <blogs.techrepublic.com.com/opensource/?p=140>`__ (priority). - On UNIX this is a number which usually goes from ``-20`` to ``20``. - The higher the nice value, the lower the priority of the process. - - >>> import psutil - >>> p = psutil.Process() - >>> p.nice(10) # set - >>> p.nice() # get - 10 - >>> - - Starting from `Python 3.3 <http://bugs.python.org/issue10784>`__ this - functionality is also available as - `os.getpriority() <http://docs.python.org/3/library/os.html#os.getpriority>`__ - and - `os.setpriority() <http://docs.python.org/3/library/os.html#os.setpriority>`__ - (UNIX only). - - On Windows this is available as well by using - `GetPriorityClass <http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx>`__ - and `SetPriorityClass <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__ - and *value* is one of the - :data:`psutil.*_PRIORITY_CLASS <psutil.ABOVE_NORMAL_PRIORITY_CLASS>` - constants. - Example which increases process priority on Windows: - - >>> p.nice(psutil.HIGH_PRIORITY_CLASS) - - .. method:: ionice(ioclass=None, value=None) - - Get or set - `process I/O niceness <http://friedcpu.wordpress.com/2007/07/17/why-arent-you-using-ionice-yet/>`__ (priority). - On Linux *ioclass* is one of the - :data:`psutil.IOPRIO_CLASS_*<psutil.IOPRIO_CLASS_NONE>` constants. - *value* is a number which goes from ``0`` to ``7``. The higher the value, - the lower the I/O priority of the process. On Windows only *ioclass* is - used and it can be set to ``2`` (normal), ``1`` (low) or ``0`` (very low). - The example below sets IDLE priority class for the current process, - meaning it will only get I/O time when no other process needs the disk: - - >>> import psutil - >>> p = psutil.Process() - >>> p.ionice(psutil.IOPRIO_CLASS_IDLE) # set - >>> p.ionice() # get - pionice(ioclass=<IOPriority.IOPRIO_CLASS_IDLE: 3>, value=0) - >>> - - On Windows only *ioclass* is used and it can be set to ``2`` (normal), - ``1`` (low) or ``0`` (very low). - - Availability: Linux and Windows > Vista - - .. versionchanged:: 3.0.0 on >= Python 3.4 the returned ``ioclass`` - constant is an `enum <https://docs.python.org/3/library/enum.html#module-enum>`__ - instead of a plain integer. - - .. method:: rlimit(resource, limits=None) - - Get or set process resource limits (see - `man prlimit <http://linux.die.net/man/2/prlimit>`__). *resource* is one of - the :data:`psutil.RLIMIT_* <psutil.RLIMIT_INFINITY>` constants. - *limits* is a ``(soft, hard)`` tuple. - This is the same as `resource.getrlimit() <http://docs.python.org/library/resource.html#resource.getrlimit>`__ - and `resource.setrlimit() <http://docs.python.org/library/resource.html#resource.setrlimit>`__ - but can be used for every process PID and only on Linux. - Example: - - >>> import psutil - >>> p = psutil.Process() - >>> # process may open no more than 128 file descriptors - >>> p.rlimit(psutil.RLIMIT_NOFILE, (128, 128)) - >>> # process may create files no bigger than 1024 bytes - >>> p.rlimit(psutil.RLIMIT_FSIZE, (1024, 1024)) - >>> # get - >>> p.rlimit(psutil.RLIMIT_FSIZE) - (1024, 1024) - >>> - - Availability: Linux - - .. method:: io_counters() - - Return process I/O statistics as a namedtuple including the number of read - and write operations performed by the process and the amount of bytes read - and written. For Linux refer to - `/proc filesysem documentation <https://www.kernel.org/doc/Documentation/filesystems/proc.txt>`__. - On BSD there's apparently no way to retrieve bytes counters, hence ``-1`` - is returned for **read_bytes** and **write_bytes** fields. OSX is not - supported. - - >>> import psutil - >>> p = psutil.Process() - >>> p.io_counters() - pio(read_count=454556, write_count=3456, read_bytes=110592, write_bytes=0) - - Availability: all platforms except OSX and Solaris - - .. method:: num_ctx_switches() - - The number voluntary and involuntary context switches performed by - this process. - - .. method:: num_fds() - - The number of file descriptors used by this process. - - Availability: UNIX - - .. method:: num_handles() - - The number of handles used by this process. - - Availability: Windows - - .. method:: num_threads() - - The number of threads currently used by this process. - - .. method:: threads() - - Return threads opened by process as a list of namedtuples including thread - id and thread CPU times (user/system). - - .. method:: cpu_times() - - Return a tuple whose values are process CPU **user** and **system** - times which means the amount of time expressed in seconds that a process - has spent in - `user / system mode <http://stackoverflow.com/questions/556405/what-do-real-user-and-sys-mean-in-the-output-of-time1>`__. - This is similar to - `os.times() <http://docs.python.org//library/os.html#os.times>`__ - but can be used for every process PID. - - .. method:: cpu_percent(interval=None) - - Return a float representing the process CPU utilization as a percentage. - When *interval* is > ``0.0`` compares process times to system CPU times - elapsed before and after the interval (blocking). When interval is ``0.0`` - or ``None`` compares process times to system CPU times elapsed since last - call, returning immediately. That means the first time this is called it - will return a meaningless ``0.0`` value which you are supposed to ignore. - In this case is recommended for accuracy that this function be called a - second time with at least ``0.1`` seconds between calls. Example: - - >>> import psutil - >>> p = psutil.Process() - >>> - >>> # blocking - >>> p.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> p.cpu_percent(interval=None) - 2.9 - >>> - - .. note:: - a percentage > 100 is legitimate as it can result from a process with - multiple threads running on different CPU cores. - - .. warning:: - the first time this method is called with interval = ``0.0`` or - ``None`` it will return a meaningless ``0.0`` value which you are - supposed to ignore. - - .. method:: cpu_affinity(cpus=None) - - Get or set process current - `CPU affinity <http://www.linuxjournal.com/article/6799?page=0,0>`__. - CPU affinity consists in telling the OS to run a certain process on a - limited set of CPUs only. The number of eligible CPUs can be obtained with - ``list(range(psutil.cpu_count()))``. On set raises ``ValueError`` in case - an invalid CPU number is specified. - - >>> import psutil - >>> psutil.cpu_count() - 4 - >>> p = psutil.Process() - >>> p.cpu_affinity() # get - [0, 1, 2, 3] - >>> p.cpu_affinity([0]) # set; from now on, process will run on CPU #0 only - >>> p.cpu_affinity() - [0] - >>> - >>> # reset affinity against all CPUs - >>> all_cpus = list(range(psutil.cpu_count())) - >>> p.cpu_affinity(all_cpus) - >>> - - Availability: Linux, Windows, BSD - - .. versionchanged:: 2.2.0 added support for FreeBSD - - .. method:: memory_info() - - Return a tuple representing RSS (Resident Set Size) and VMS (Virtual - Memory Size) in bytes. On UNIX *rss* and *vms* are the same values shown - by ps. On Windows *rss* and *vms* refer to "Mem Usage" and "VM Size" - columns of taskmgr.exe. For more detailed memory stats use - :meth:`memory_info_ex`. - - .. method:: memory_info_ex() - - Return a namedtuple with variable fields depending on the platform - representing extended memory information about the process. - All numbers are expressed in bytes. - - +--------+---------+-------+-------+--------------------+ - | Linux | OSX | BSD | SunOS | Windows | - +========+=========+=======+=======+====================+ - | rss | rss | rss | rss | num_page_faults | - +--------+---------+-------+-------+--------------------+ - | vms | vms | vms | vms | peak_wset | - +--------+---------+-------+-------+--------------------+ - | shared | pfaults | text | | wset | - +--------+---------+-------+-------+--------------------+ - | text | pageins | data | | peak_paged_pool | - +--------+---------+-------+-------+--------------------+ - | lib | | stack | | paged_pool | - +--------+---------+-------+-------+--------------------+ - | data | | | | peak_nonpaged_pool | - +--------+---------+-------+-------+--------------------+ - | dirty | | | | nonpaged_pool | - +--------+---------+-------+-------+--------------------+ - | | | | | pagefile | - +--------+---------+-------+-------+--------------------+ - | | | | | peak_pagefile | - +--------+---------+-------+-------+--------------------+ - | | | | | private | - +--------+---------+-------+-------+--------------------+ - - Windows metrics are extracted from - `PROCESS_MEMORY_COUNTERS_EX <http://msdn.microsoft.com/en-us/library/windows/desktop/ms684874(v=vs.85).aspx>`__ structure. - Example on Linux: - - >>> import psutil - >>> p = psutil.Process() - >>> p.memory_info_ex() - pextmem(rss=15491072, vms=84025344, shared=5206016, text=2555904, lib=0, data=9891840, dirty=0) - - .. method:: memory_percent() - - Compare physical system memory to process resident memory (RSS) and - calculate process memory utilization as a percentage. - - .. method:: memory_maps(grouped=True) - - Return process's mapped memory regions as a list of namedtuples whose - fields are variable depending on the platform. As such, portable - applications should rely on namedtuple's `path` and `rss` fields only. - This method is useful to obtain a detailed representation of process - memory usage as explained - `here <http://bmaurer.blogspot.it/2006/03/memory-usage-with-smaps.html>`__. - If *grouped* is ``True`` the mapped regions with the same *path* are - grouped together and the different memory fields are summed. If *grouped* - is ``False`` every mapped region is shown as a single entity and the - namedtuple will also include the mapped region's address space (*addr*) - and permission set (*perms*). - See `examples/pmap.py <https://github.com/giampaolo/psutil/blob/master/examples/pmap.py>`__ - for an example application. - - >>> import psutil - >>> p = psutil.Process() - >>> p.memory_maps() - [pmmap_grouped(path='/lib/x8664-linux-gnu/libutil-2.15.so', rss=16384, anonymous=8192, swap=0), - pmmap_grouped(path='/lib/x8664-linux-gnu/libc-2.15.so', rss=6384, anonymous=15, swap=0), - pmmap_grouped(path='/lib/x8664-linux-gnu/libcrypto.so.0.1', rss=34124, anonymous=1245, swap=0), - pmmap_grouped(path='[heap]', rss=54653, anonymous=8192, swap=0), - pmmap_grouped(path='[stack]', rss=1542, anonymous=166, swap=0), - ...] - >>> - - .. method:: children(recursive=False) - - Return the children of this process as a list of :Class:`Process` objects, - pre-emptively checking whether PID has been reused. If recursive is `True` - return all the parent descendants. - Example assuming *A == this process*: - :: - - A ─┐ - │ - ├─ B (child) ─┐ - │ └─ X (grandchild) ─┐ - │ └─ Y (great grandchild) - ├─ C (child) - └─ D (child) - - >>> p.children() - B, C, D - >>> p.children(recursive=True) - B, X, Y, C, D - - Note that in the example above if process X disappears process Y won't be - returned either as the reference to process A is lost. - - .. method:: open_files() - - Return regular files opened by process as a list of namedtuples including - the absolute file name and the file descriptor number (on Windows this is - always ``-1``). Example: - - >>> import psutil - >>> f = open('file.ext', 'w') - >>> p = psutil.Process() - >>> p.open_files() - [popenfile(path='/home/giampaolo/svn/psutil/file.ext', fd=3)] - - .. warning:: - on Windows this is not fully reliable as due to some limitations of the - Windows API the underlying implementation may hang when retrieving - certain file handles. - In order to work around that psutil on Windows Vista (and higher) spawns - a thread and kills it if it's not responding after 100ms. - That implies that on Windows this method is not guaranteed to enumerate - all regular file handles (see full discusion - `here <https://github.com/giampaolo/psutil/pull/597>`_). - - .. warning:: - on FreeBSD this method can return files with a 'null' path (see - `issue 595 <https://github.com/giampaolo/psutil/pull/595>`_). - - .. versionchanged:: 3.1.0 no longer hangs on Windows. - - .. method:: connections(kind="inet") - - Return socket connections opened by process as a list of namedtuples. - To get system-wide connections use :func:`psutil.net_connections()`. - Every namedtuple provides 6 attributes: - - - **fd**: the socket file descriptor. This can be passed to - `socket.fromfd() <http://docs.python.org/library/socket.html#socket.fromfd>`__ - to obtain a usable socket object. - This is only available on UNIX; on Windows ``-1`` is always returned. - - **family**: the address family, either `AF_INET - <http://docs.python.org//library/socket.html#socket.AF_INET>`__, - `AF_INET6 <http://docs.python.org//library/socket.html#socket.AF_INET6>`__ - or `AF_UNIX <http://docs.python.org//library/socket.html#socket.AF_UNIX>`__. - - **type**: the address type, either `SOCK_STREAM - <http://docs.python.org//library/socket.html#socket.SOCK_STREAM>`__ or - `SOCK_DGRAM - <http://docs.python.org//library/socket.html#socket.SOCK_DGRAM>`__. - - **laddr**: the local address as a ``(ip, port)`` tuple or a ``path`` - in case of AF_UNIX sockets. - - **raddr**: the remote address as a ``(ip, port)`` tuple or an absolute - ``path`` in case of UNIX sockets. - When the remote endpoint is not connected you'll get an empty tuple - (AF_INET) or ``None`` (AF_UNIX). - On Linux AF_UNIX sockets will always have this set to ``None``. - - **status**: represents the status of a TCP connection. The return value - is one of the :data:`psutil.CONN_* <psutil.CONN_ESTABLISHED>` constants. - For UDP and UNIX sockets this is always going to be - :const:`psutil.CONN_NONE`. - - The *kind* parameter is a string which filters for connections that fit the - following criteria: - - .. table:: - - +----------------+-----------------------------------------------------+ - | **Kind value** | **Connections using** | - +================+=====================================================+ - | "inet" | IPv4 and IPv6 | - +----------------+-----------------------------------------------------+ - | "inet4" | IPv4 | - +----------------+-----------------------------------------------------+ - | "inet6" | IPv6 | - +----------------+-----------------------------------------------------+ - | "tcp" | TCP | - +----------------+-----------------------------------------------------+ - | "tcp4" | TCP over IPv4 | - +----------------+-----------------------------------------------------+ - | "tcp6" | TCP over IPv6 | - +----------------+-----------------------------------------------------+ - | "udp" | UDP | - +----------------+-----------------------------------------------------+ - | "udp4" | UDP over IPv4 | - +----------------+-----------------------------------------------------+ - | "udp6" | UDP over IPv6 | - +----------------+-----------------------------------------------------+ - | "unix" | UNIX socket (both UDP and TCP protocols) | - +----------------+-----------------------------------------------------+ - | "all" | the sum of all the possible families and protocols | - +----------------+-----------------------------------------------------+ - - Example: - - >>> import psutil - >>> p = psutil.Process(1694) - >>> p.name() - 'firefox' - >>> p.connections() - [pconn(fd=115, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 48776), raddr=('93.186.135.91', 80), status='ESTABLISHED'), - pconn(fd=117, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 43761), raddr=('72.14.234.100', 80), status='CLOSING'), - pconn(fd=119, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 60759), raddr=('72.14.234.104', 80), status='ESTABLISHED'), - pconn(fd=123, family=<AddressFamily.AF_INET: 2>, type=<SocketType.SOCK_STREAM: 1>, laddr=('10.0.0.1', 51314), raddr=('72.14.234.83', 443), status='SYN_SENT')] - - .. method:: is_running() - - Return whether the current process is running in the current process list. - This is reliable also in case the process is gone and its PID reused by - another process, therefore it must be preferred over doing - ``psutil.pid_exists(p.pid)``. - - .. note:: - this will return ``True`` also if the process is a zombie - (``p.status() == psutil.STATUS_ZOMBIE``). - - .. method:: send_signal(signal) - - Send a signal to process (see - `signal module <http://docs.python.org//library/signal.html>`__ - constants) pre-emptively checking whether PID has been reused. - This is the same as ``os.kill(pid, sig)``. - On Windows only **SIGTERM** is valid and is treated as an alias for - :meth:`kill()`. - - .. method:: suspend() - - Suspend process execution with **SIGSTOP** signal pre-emptively checking - whether PID has been reused. - On UNIX this is the same as ``os.kill(pid, signal.SIGSTOP)``. - On Windows this is done by suspending all process threads execution. - - .. method:: resume() - - Resume process execution with **SIGCONT** signal pre-emptively checking - whether PID has been reused. - On UNIX this is the same as ``os.kill(pid, signal.SIGCONT)``. - On Windows this is done by resuming all process threads execution. - - .. method:: terminate() - - Terminate the process with **SIGTERM** signal pre-emptively checking - whether PID has been reused. - On UNIX this is the same as ``os.kill(pid, signal.SIGTERM)``. - On Windows this is an alias for :meth:`kill`. - - .. method:: kill() - - Kill the current process by using **SIGKILL** signal pre-emptively - checking whether PID has been reused. - On UNIX this is the same as ``os.kill(pid, signal.SIGKILL)``. - On Windows this is done by using - `TerminateProcess <http://msdn.microsoft.com/en-us/library/windows/desktop/ms686714(v=vs.85).aspx>`__. - - .. method:: wait(timeout=None) - - Wait for process termination and if the process is a children of the - current one also return the exit code, else ``None``. On Windows there's - no such limitation (exit code is always returned). If the process is - already terminated immediately return ``None`` instead of raising - :class:`NoSuchProcess`. If *timeout* is specified and process is still - alive raise :class:`TimeoutExpired` exception. It can also be used in a - non-blocking fashion by specifying ``timeout=0`` in which case it will - either return immediately or raise :class:`TimeoutExpired`. - To wait for multiple processes use :func:`psutil.wait_procs()`. - - -Popen class ------------ - -.. class:: Popen(*args, **kwargs) - - A more convenient interface to stdlib - `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__. - It starts a sub process and deals with it exactly as when using - `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__ - but in addition it also provides all the methods of - :class:`psutil.Process` class in a single interface. - For method names common to both classes such as - :meth:`send_signal() <psutil.Process.send_signal()>`, - :meth:`terminate() <psutil.Process.terminate()>` and - :meth:`kill() <psutil.Process.kill()>` - :class:`psutil.Process` implementation takes precedence. - For a complete documentation refer to - `subprocess module documentation <http://docs.python.org/library/subprocess.html>`__. - - .. note:: - - Unlike `subprocess.Popen <http://docs.python.org/library/subprocess.html#subprocess.Popen>`__ - this class pre-emptively checks wheter PID has been reused on - :meth:`send_signal() <psutil.Process.send_signal()>`, - :meth:`terminate() <psutil.Process.terminate()>` and - :meth:`kill() <psutil.Process.kill()>` - so that you can't accidentally terminate another process, fixing - http://bugs.python.org/issue6973. - - >>> import psutil - >>> from subprocess import PIPE - >>> - >>> p = psutil.Popen(["/usr/bin/python", "-c", "print('hello')"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hello\n', None) - >>> p.wait(timeout=2) - 0 - >>> - -Constants -========= - -.. _const-pstatus: -.. data:: STATUS_RUNNING - STATUS_SLEEPING - STATUS_DISK_SLEEP - STATUS_STOPPED - STATUS_TRACING_STOP - STATUS_ZOMBIE - STATUS_DEAD - STATUS_WAKE_KILL - STATUS_WAKING - STATUS_IDLE - STATUS_LOCKED - STATUS_WAITING - - A set of strings representing the status of a process. - Returned by :meth:`psutil.Process.status()`. - -.. _const-conn: -.. data:: CONN_ESTABLISHED - CONN_SYN_SENT - CONN_SYN_RECV - CONN_FIN_WAIT1 - CONN_FIN_WAIT2 - CONN_TIME_WAIT - CONN_CLOSE - CONN_CLOSE_WAIT - CONN_LAST_ACK - CONN_LISTEN - CONN_CLOSING - CONN_NONE - CONN_DELETE_TCB (Windows) - CONN_IDLE (Solaris) - CONN_BOUND (Solaris) - - A set of strings representing the status of a TCP connection. - Returned by :meth:`psutil.Process.connections()` (`status` field). - -.. _const-prio: -.. data:: ABOVE_NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS - HIGH_PRIORITY_CLASS - IDLE_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS - REALTIME_PRIORITY_CLASS - - A set of integers representing the priority of a process on Windows (see - `MSDN documentation <http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx>`__). - They can be used in conjunction with - :meth:`psutil.Process.nice()` to get or set process priority. - - Availability: Windows - - .. versionchanged:: 3.0.0 on Python >= 3.4 these constants are - `enums <https://docs.python.org/3/library/enum.html#module-enum>`__ - instead of a plain integer. - -.. _const-ioprio: -.. data:: IOPRIO_CLASS_NONE - IOPRIO_CLASS_RT - IOPRIO_CLASS_BE - IOPRIO_CLASS_IDLE - - A set of integers representing the I/O priority of a process on Linux. They - can be used in conjunction with :meth:`psutil.Process.ionice()` to get or set - process I/O priority. - *IOPRIO_CLASS_NONE* and *IOPRIO_CLASS_BE* (best effort) is the default for - any process that hasn't set a specific I/O priority. - *IOPRIO_CLASS_RT* (real time) means the process is given first access to the - disk, regardless of what else is going on in the system. - *IOPRIO_CLASS_IDLE* means the process will get I/O time when no-one else - needs the disk. - For further information refer to manuals of - `ionice <http://linux.die.net/man/1/ionice>`__ - command line utility or - `ioprio_get <http://linux.die.net/man/2/ioprio_get>`__ - system call. - - Availability: Linux - - .. versionchanged:: 3.0.0 on Python >= 3.4 thse constants are - `enums <https://docs.python.org/3/library/enum.html#module-enum>`__ - instead of a plain integer. - -.. _const-rlimit: -.. data:: RLIMIT_INFINITY - RLIMIT_AS - RLIMIT_CORE - RLIMIT_CPU - RLIMIT_DATA - RLIMIT_FSIZE - RLIMIT_LOCKS - RLIMIT_MEMLOCK - RLIMIT_MSGQUEUE - RLIMIT_NICE - RLIMIT_NOFILE - RLIMIT_NPROC - RLIMIT_RSS - RLIMIT_RTPRIO - RLIMIT_RTTIME - RLIMIT_RTPRIO - RLIMIT_SIGPENDING - RLIMIT_STACK - - Constants used for getting and setting process resource limits to be used in - conjunction with :meth:`psutil.Process.rlimit()`. See - `man prlimit <http://linux.die.net/man/2/prlimit>`__ for futher information. - - Availability: Linux - -.. _const-aflink: -.. data:: AF_LINK - - Constant which identifies a MAC address associated with a network interface. - To be used in conjunction with :func:`psutil.net_if_addrs()`. - - *New in 3.0.0* - -.. _const-duplex: -.. data:: NIC_DUPLEX_FULL - NIC_DUPLEX_HALF - NIC_DUPLEX_UNKNOWN - - Constants which identifies whether a NIC (network interface card) has full or - half mode speed. NIC_DUPLEX_FULL means the NIC is able to send and receive - data (files) simultaneously, NIC_DUPLEX_FULL means the NIC can either send or - receive data at a time. - To be used in conjunction with :func:`psutil.net_if_stats()`. - - *New in 3.0.0* - -Development guide -================= - -If you plan on hacking on psutil (e.g. want to add a new feature or fix a bug) -take a look at the -`development guide <https://github.com/giampaolo/psutil/blob/master/DEVGUIDE.rst>`_. diff --git a/python/psutil/docs/make.bat b/python/psutil/docs/make.bat deleted file mode 100644 index 9bc67515c..000000000 --- a/python/psutil/docs/make.bat +++ /dev/null @@ -1,242 +0,0 @@ -@ECHO OFF - -REM Command file for Sphinx documentation - -if "%SPHINXBUILD%" == "" ( - set SPHINXBUILD=sphinx-build -) -set BUILDDIR=_build -set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . -set I18NSPHINXOPTS=%SPHINXOPTS% . -if NOT "%PAPER%" == "" ( - set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% - set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% -) - -if "%1" == "" goto help - -if "%1" == "help" ( - :help - echo.Please use `make ^<target^>` where ^<target^> is one of - echo. html to make standalone HTML files - echo. dirhtml to make HTML files named index.html in directories - echo. singlehtml to make a single large HTML file - echo. pickle to make pickle files - echo. json to make JSON files - echo. htmlhelp to make HTML files and a HTML help project - echo. qthelp to make HTML files and a qthelp project - echo. devhelp to make HTML files and a Devhelp project - echo. epub to make an epub - echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter - echo. text to make text files - echo. man to make manual pages - echo. texinfo to make Texinfo files - echo. gettext to make PO message catalogs - echo. changes to make an overview over all changed/added/deprecated items - echo. xml to make Docutils-native XML files - echo. pseudoxml to make pseudoxml-XML files for display purposes - echo. linkcheck to check all external links for integrity - echo. doctest to run all doctests embedded in the documentation if enabled - goto end -) - -if "%1" == "clean" ( - for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i - del /q /s %BUILDDIR%\* - goto end -) - - -%SPHINXBUILD% 2> nul -if errorlevel 9009 ( - echo. - echo.The 'sphinx-build' command was not found. Make sure you have Sphinx - echo.installed, then set the SPHINXBUILD environment variable to point - echo.to the full path of the 'sphinx-build' executable. Alternatively you - echo.may add the Sphinx directory to PATH. - echo. - echo.If you don't have Sphinx installed, grab it from - echo.http://sphinx-doc.org/ - exit /b 1 -) - -if "%1" == "html" ( - %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/html. - goto end -) - -if "%1" == "dirhtml" ( - %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. - goto end -) - -if "%1" == "singlehtml" ( - %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. - goto end -) - -if "%1" == "pickle" ( - %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the pickle files. - goto end -) - -if "%1" == "json" ( - %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can process the JSON files. - goto end -) - -if "%1" == "htmlhelp" ( - %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run HTML Help Workshop with the ^ -.hhp project file in %BUILDDIR%/htmlhelp. - goto end -) - -if "%1" == "qthelp" ( - %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; now you can run "qcollectiongenerator" with the ^ -.qhcp project file in %BUILDDIR%/qthelp, like this: - echo.^> qcollectiongenerator %BUILDDIR%\qthelp\psutil.qhcp - echo.To view the help file: - echo.^> assistant -collectionFile %BUILDDIR%\qthelp\psutil.ghc - goto end -) - -if "%1" == "devhelp" ( - %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. - goto end -) - -if "%1" == "epub" ( - %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The epub file is in %BUILDDIR%/epub. - goto end -) - -if "%1" == "latex" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - if errorlevel 1 exit /b 1 - echo. - echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdf" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "latexpdfja" ( - %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex - cd %BUILDDIR%/latex - make all-pdf-ja - cd %BUILDDIR%/.. - echo. - echo.Build finished; the PDF files are in %BUILDDIR%/latex. - goto end -) - -if "%1" == "text" ( - %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The text files are in %BUILDDIR%/text. - goto end -) - -if "%1" == "man" ( - %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The manual pages are in %BUILDDIR%/man. - goto end -) - -if "%1" == "texinfo" ( - %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. - goto end -) - -if "%1" == "gettext" ( - %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The message catalogs are in %BUILDDIR%/locale. - goto end -) - -if "%1" == "changes" ( - %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes - if errorlevel 1 exit /b 1 - echo. - echo.The overview file is in %BUILDDIR%/changes. - goto end -) - -if "%1" == "linkcheck" ( - %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck - if errorlevel 1 exit /b 1 - echo. - echo.Link check complete; look for any errors in the above output ^ -or in %BUILDDIR%/linkcheck/output.txt. - goto end -) - -if "%1" == "doctest" ( - %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest - if errorlevel 1 exit /b 1 - echo. - echo.Testing of doctests in the sources finished, look at the ^ -results in %BUILDDIR%/doctest/output.txt. - goto end -) - -if "%1" == "xml" ( - %SPHINXBUILD% -b xml %ALLSPHINXOPTS% %BUILDDIR%/xml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The XML files are in %BUILDDIR%/xml. - goto end -) - -if "%1" == "pseudoxml" ( - %SPHINXBUILD% -b pseudoxml %ALLSPHINXOPTS% %BUILDDIR%/pseudoxml - if errorlevel 1 exit /b 1 - echo. - echo.Build finished. The pseudo-XML files are in %BUILDDIR%/pseudoxml. - goto end -) - -:end diff --git a/python/psutil/docs/xxx b/python/psutil/docs/xxx deleted file mode 100644 index b78d53f2d..000000000 --- a/python/psutil/docs/xxx +++ /dev/null @@ -1,11 +0,0 @@ -cpu 1974613 1749 485728 6305758 80280 15 5924 0 0 0 - -cpu0 519156 374 132999 5977865 72925 10 1458 0 0 0 - -cpu1 524667 401 125931 108960 2110 4 2214 0 0 0 - -cpu2 462286 520 117046 109514 2666 0 828 0 0 0 - -cpu3 468502 453 109750 109418 2578 0 1424 0 0 0 - - diff --git a/python/psutil/examples/disk_usage.py b/python/psutil/examples/disk_usage.py deleted file mode 100755 index d8600a8c4..000000000 --- a/python/psutil/examples/disk_usage.py +++ /dev/null @@ -1,62 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -List all mounted disk partitions a-la "df -h" command. - -$ python examples/disk_usage.py -Device Total Used Free Use % Type Mount -/dev/sdb3 18.9G 14.7G 3.3G 77% ext4 / -/dev/sda6 345.9G 83.8G 244.5G 24% ext4 /home -/dev/sda1 296.0M 43.1M 252.9M 14% vfat /boot/efi -/dev/sda2 600.0M 312.4M 287.6M 52% fuseblk /media/Recovery -""" - -import sys -import os -import psutil - - -def bytes2human(n): - # http://code.activestate.com/recipes/578019 - # >>> bytes2human(10000) - # '9.8K' - # >>> bytes2human(100001221) - # '95.4M' - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.1f%s' % (value, s) - return "%sB" % n - - -def main(): - templ = "%-17s %8s %8s %8s %5s%% %9s %s" - print(templ % ("Device", "Total", "Used", "Free", "Use ", "Type", - "Mount")) - for part in psutil.disk_partitions(all=False): - if os.name == 'nt': - if 'cdrom' in part.opts or part.fstype == '': - # skip cd-rom drives with no disk in it; they may raise - # ENOENT, pop-up a Windows GUI error for a non-ready - # partition or just hang. - continue - usage = psutil.disk_usage(part.mountpoint) - print(templ % ( - part.device, - bytes2human(usage.total), - bytes2human(usage.used), - bytes2human(usage.free), - int(usage.percent), - part.fstype, - part.mountpoint)) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/python/psutil/examples/free.py b/python/psutil/examples/free.py deleted file mode 100755 index 913ca58a4..000000000 --- a/python/psutil/examples/free.py +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'free' cmdline utility. - -$ python examples/free.py - total used free shared buffers cache -Mem: 10125520 8625996 1499524 0 349500 3307836 -Swap: 0 0 0 -""" - -import psutil - - -def main(): - virt = psutil.virtual_memory() - swap = psutil.swap_memory() - templ = "%-7s %10s %10s %10s %10s %10s %10s" - print(templ % ('', 'total', 'used', 'free', 'shared', 'buffers', 'cache')) - print(templ % ( - 'Mem:', - int(virt.total / 1024), - int(virt.used / 1024), - int(virt.free / 1024), - int(getattr(virt, 'shared', 0) / 1024), - int(getattr(virt, 'buffers', 0) / 1024), - int(getattr(virt, 'cached', 0) / 1024))) - print(templ % ( - 'Swap:', int(swap.total / 1024), - int(swap.used / 1024), - int(swap.free / 1024), - '', - '', - '')) - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/ifconfig.py b/python/psutil/examples/ifconfig.py deleted file mode 100644 index e7a436cc0..000000000 --- a/python/psutil/examples/ifconfig.py +++ /dev/null @@ -1,78 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'ifconfig' on UNIX. - -$ python examples/ifconfig.py -lo (speed=0MB, duplex=?, mtu=65536, up=yes): - IPv4 address : 127.0.0.1 - broadcast : 127.0.0.1 - netmask : 255.0.0.0 - IPv6 address : ::1 - netmask : ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff - MAC address : 00:00:00:00:00:00 - broadcast : 00:00:00:00:00:00 - -wlan0 (speed=0MB, duplex=?, mtu=1500, up=yes): - IPv4 address : 10.0.3.1 - broadcast : 10.0.3.255 - netmask : 255.255.255.0 - IPv6 address : fe80::3005:adff:fe31:8698 - netmask : ffff:ffff:ffff:ffff:: - MAC address : 32:05:ad:31:86:98 - broadcast : ff:ff:ff:ff:ff:ff - -eth0 (speed=100MB, duplex=full, mtu=1500, up=yes): - IPv4 address : 192.168.1.2 - broadcast : 192.168.1.255 - netmask : 255.255.255.0 - IPv6 address : fe80::c685:8ff:fe45:641 - netmask : ffff:ffff:ffff:ffff:: - MAC address : c4:85:08:45:06:41 - broadcast : ff:ff:ff:ff:ff:ff -""" - -from __future__ import print_function -import socket - -import psutil - - -af_map = { - socket.AF_INET: 'IPv4', - socket.AF_INET6: 'IPv6', - psutil.AF_LINK: 'MAC', -} - -duplex_map = { - psutil.NIC_DUPLEX_FULL: "full", - psutil.NIC_DUPLEX_HALF: "half", - psutil.NIC_DUPLEX_UNKNOWN: "?", -} - - -def main(): - stats = psutil.net_if_stats() - for nic, addrs in psutil.net_if_addrs().items(): - if nic in stats: - print("%s (speed=%sMB, duplex=%s, mtu=%s, up=%s):" % ( - nic, stats[nic].speed, duplex_map[stats[nic].duplex], - stats[nic].mtu, "yes" if stats[nic].isup else "no")) - else: - print("%s:" % (nic)) - for addr in addrs: - print(" %-8s" % af_map.get(addr.family, addr.family), end="") - print(" address : %s" % addr.address) - if addr.broadcast: - print(" broadcast : %s" % addr.broadcast) - if addr.netmask: - print(" netmask : %s" % addr.netmask) - print("") - - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/iotop.py b/python/psutil/examples/iotop.py deleted file mode 100755 index 16ac7fbf6..000000000 --- a/python/psutil/examples/iotop.py +++ /dev/null @@ -1,179 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of iotop (http://guichaz.free.fr/iotop/) showing real time -disk I/O statistics. - -It works on Linux only (FreeBSD and OSX are missing support for IO -counters). -It doesn't work on Windows as curses module is required. - -Example output: - -$ python examples/iotop.py -Total DISK READ: 0.00 B/s | Total DISK WRITE: 472.00 K/s -PID USER DISK READ DISK WRITE COMMAND -13155 giampao 0.00 B/s 428.00 K/s /usr/bin/google-chrome-beta -3260 giampao 0.00 B/s 0.00 B/s bash -3779 giampao 0.00 B/s 0.00 B/s gnome-session --session=ubuntu -3830 giampao 0.00 B/s 0.00 B/s /usr/bin/dbus-launch -3831 giampao 0.00 B/s 0.00 B/s //bin/dbus-daemon --fork --print-pid 5 -3841 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi-bus-launcher -3845 giampao 0.00 B/s 0.00 B/s /bin/dbus-daemon -3848 giampao 0.00 B/s 0.00 B/s /usr/lib/at-spi2-core/at-spi2-registryd -3862 giampao 0.00 B/s 0.00 B/s /usr/lib/gnome-settings-daemon - -Author: Giampaolo Rodola' <g.rodola@gmail.com> -""" - -import atexit -import time -import sys -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil - - -# --- curses stuff -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 -# --- /curses stuff - - -def bytes2human(n): - """ - >>> bytes2human(10000) - '9.8 K/s' - >>> bytes2human(100001221) - '95.4 M/s' - """ - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.2f %s/s' % (value, s) - return '%.2f B/s' % (n) - - -def poll(interval): - """Calculate IO usage by comparing IO statics before and - after the interval. - Return a tuple including all currently running processes - sorted by IO activity and total disks I/O activity. - """ - # first get a list of all processes and disk io counters - procs = [p for p in psutil.process_iter()] - for p in procs[:]: - try: - p._before = p.io_counters() - except psutil.Error: - procs.remove(p) - continue - disks_before = psutil.disk_io_counters() - - # sleep some time - time.sleep(interval) - - # then retrieve the same info again - for p in procs[:]: - try: - p._after = p.io_counters() - p._cmdline = ' '.join(p.cmdline()) - if not p._cmdline: - p._cmdline = p.name() - p._username = p.username() - except (psutil.NoSuchProcess, psutil.ZombieProcess): - procs.remove(p) - disks_after = psutil.disk_io_counters() - - # finally calculate results by comparing data before and - # after the interval - for p in procs: - p._read_per_sec = p._after.read_bytes - p._before.read_bytes - p._write_per_sec = p._after.write_bytes - p._before.write_bytes - p._total = p._read_per_sec + p._write_per_sec - - disks_read_per_sec = disks_after.read_bytes - disks_before.read_bytes - disks_write_per_sec = disks_after.write_bytes - disks_before.write_bytes - - # sort processes by total disk IO so that the more intensive - # ones get listed first - processes = sorted(procs, key=lambda p: p._total, reverse=True) - - return (processes, disks_read_per_sec, disks_write_per_sec) - - -def refresh_window(procs, disks_read, disks_write): - """Print results on screen by using curses.""" - curses.endwin() - templ = "%-5s %-7s %11s %11s %s" - win.erase() - - disks_tot = "Total DISK READ: %s | Total DISK WRITE: %s" \ - % (bytes2human(disks_read), bytes2human(disks_write)) - print_line(disks_tot) - - header = templ % ("PID", "USER", "DISK READ", "DISK WRITE", "COMMAND") - print_line(header, highlight=True) - - for p in procs: - line = templ % ( - p.pid, - p._username[:7], - bytes2human(p._read_per_sec), - bytes2human(p._write_per_sec), - p._cmdline) - try: - print_line(line) - except curses.error: - break - win.refresh() - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/killall.py b/python/psutil/examples/killall.py deleted file mode 100755 index b548e7bc5..000000000 --- a/python/psutil/examples/killall.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Kill a process by name. -""" - -import os -import sys -import psutil - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: %s name' % __file__) - else: - NAME = sys.argv[1] - - killed = [] - for proc in psutil.process_iter(): - if proc.name() == NAME and proc.pid != os.getpid(): - proc.kill() - killed.append(proc.pid) - if not killed: - sys.exit('%s: no process found' % NAME) - else: - sys.exit(0) - -sys.exit(main()) diff --git a/python/psutil/examples/meminfo.py b/python/psutil/examples/meminfo.py deleted file mode 100755 index c463a3de4..000000000 --- a/python/psutil/examples/meminfo.py +++ /dev/null @@ -1,68 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Print system memory information. - -$ python examples/meminfo.py -MEMORY ------- -Total : 9.7G -Available : 4.9G -Percent : 49.0 -Used : 8.2G -Free : 1.4G -Active : 5.6G -Inactive : 2.1G -Buffers : 341.2M -Cached : 3.2G - -SWAP ----- -Total : 0B -Used : 0B -Free : 0B -Percent : 0.0 -Sin : 0B -Sout : 0B -""" - -import psutil - - -def bytes2human(n): - # http://code.activestate.com/recipes/578019 - # >>> bytes2human(10000) - # '9.8K' - # >>> bytes2human(100001221) - # '95.4M' - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.1f%s' % (value, s) - return "%sB" % n - - -def pprint_ntuple(nt): - for name in nt._fields: - value = getattr(nt, name) - if name != 'percent': - value = bytes2human(value) - print('%-10s : %7s' % (name.capitalize(), value)) - - -def main(): - print('MEMORY\n------') - pprint_ntuple(psutil.virtual_memory()) - print('\nSWAP\n----') - pprint_ntuple(psutil.swap_memory()) - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/netstat.py b/python/psutil/examples/netstat.py deleted file mode 100755 index 884622e9e..000000000 --- a/python/psutil/examples/netstat.py +++ /dev/null @@ -1,64 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'netstat -antp' on Linux. - -$ python examples/netstat.py -Proto Local address Remote address Status PID Program name -tcp 127.0.0.1:48256 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:47073 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:47072 127.0.0.1:45884 ESTABLISHED 13646 chrome -tcp 127.0.0.1:45884 - LISTEN 13651 GoogleTalkPlugi -tcp 127.0.0.1:60948 - LISTEN 13651 GoogleTalkPlugi -tcp 172.17.42.1:49102 127.0.0.1:19305 CLOSE_WAIT 13651 GoogleTalkPlugi -tcp 172.17.42.1:55797 127.0.0.1:443 CLOSE_WAIT 13651 GoogleTalkPlugi -... -""" - -import socket -from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM - -import psutil - - -AD = "-" -AF_INET6 = getattr(socket, 'AF_INET6', object()) -proto_map = { - (AF_INET, SOCK_STREAM): 'tcp', - (AF_INET6, SOCK_STREAM): 'tcp6', - (AF_INET, SOCK_DGRAM): 'udp', - (AF_INET6, SOCK_DGRAM): 'udp6', -} - - -def main(): - templ = "%-5s %-30s %-30s %-13s %-6s %s" - print(templ % ( - "Proto", "Local address", "Remote address", "Status", "PID", - "Program name")) - proc_names = {} - for p in psutil.process_iter(): - try: - proc_names[p.pid] = p.name() - except psutil.Error: - pass - for c in psutil.net_connections(kind='inet'): - laddr = "%s:%s" % (c.laddr) - raddr = "" - if c.raddr: - raddr = "%s:%s" % (c.raddr) - print(templ % ( - proto_map[(c.family, c.type)], - laddr, - raddr or AD, - c.status, - c.pid or AD, - proc_names.get(c.pid, '?')[:15], - )) - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/nettop.py b/python/psutil/examples/nettop.py deleted file mode 100755 index 7a8343ee4..000000000 --- a/python/psutil/examples/nettop.py +++ /dev/null @@ -1,165 +0,0 @@ -#!/usr/bin/env python -# -# $Id: iotop.py 1160 2011-10-14 18:50:36Z g.rodola@gmail.com $ -# -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Shows real-time network statistics. - -Author: Giampaolo Rodola' <g.rodola@gmail.com> - -$ python examples/nettop.py ------------------------------------------------------------ -total bytes: sent: 1.49 G received: 4.82 G -total packets: sent: 7338724 received: 8082712 - -wlan0 TOTAL PER-SEC ------------------------------------------------------------ -bytes-sent 1.29 G 0.00 B/s -bytes-recv 3.48 G 0.00 B/s -pkts-sent 7221782 0 -pkts-recv 6753724 0 - -eth1 TOTAL PER-SEC ------------------------------------------------------------ -bytes-sent 131.77 M 0.00 B/s -bytes-recv 1.28 G 0.00 B/s -pkts-sent 0 0 -pkts-recv 1214470 0 -""" - -import atexit -import time -import sys -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil - - -# --- curses stuff -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 -# --- curses stuff - - -def bytes2human(n): - """ - >>> bytes2human(10000) - '9.8 K' - >>> bytes2human(100001221) - '95.4 M' - """ - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.2f %s' % (value, s) - return '%.2f B' % (n) - - -def poll(interval): - """Retrieve raw stats within an interval window.""" - tot_before = psutil.net_io_counters() - pnic_before = psutil.net_io_counters(pernic=True) - # sleep some time - time.sleep(interval) - tot_after = psutil.net_io_counters() - pnic_after = psutil.net_io_counters(pernic=True) - return (tot_before, tot_after, pnic_before, pnic_after) - - -def refresh_window(tot_before, tot_after, pnic_before, pnic_after): - """Print stats on screen.""" - global lineno - - # totals - print_line("total bytes: sent: %-10s received: %s" % ( - bytes2human(tot_after.bytes_sent), - bytes2human(tot_after.bytes_recv)) - ) - print_line("total packets: sent: %-10s received: %s" % ( - tot_after.packets_sent, tot_after.packets_recv)) - - # per-network interface details: let's sort network interfaces so - # that the ones which generated more traffic are shown first - print_line("") - nic_names = list(pnic_after.keys()) - nic_names.sort(key=lambda x: sum(pnic_after[x]), reverse=True) - for name in nic_names: - stats_before = pnic_before[name] - stats_after = pnic_after[name] - templ = "%-15s %15s %15s" - print_line(templ % (name, "TOTAL", "PER-SEC"), highlight=True) - print_line(templ % ( - "bytes-sent", - bytes2human(stats_after.bytes_sent), - bytes2human( - stats_after.bytes_sent - stats_before.bytes_sent) + '/s', - )) - print_line(templ % ( - "bytes-recv", - bytes2human(stats_after.bytes_recv), - bytes2human( - stats_after.bytes_recv - stats_before.bytes_recv) + '/s', - )) - print_line(templ % ( - "pkts-sent", - stats_after.packets_sent, - stats_after.packets_sent - stats_before.packets_sent, - )) - print_line(templ % ( - "pkts-recv", - stats_after.packets_recv, - stats_after.packets_recv - stats_before.packets_recv, - )) - print_line("") - win.refresh() - lineno = 0 - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/pidof.py b/python/psutil/examples/pidof.py deleted file mode 100755 index 8692a3152..000000000 --- a/python/psutil/examples/pidof.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola', karthikrev. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - - -""" -A clone of 'pidof' cmdline utility. -$ pidof python -1140 1138 1136 1134 1133 1129 1127 1125 1121 1120 1119 -""" - -from __future__ import print_function -import psutil -import sys - - -def pidof(pgname): - pids = [] - for proc in psutil.process_iter(): - # search for matches in the process name and cmdline - try: - name = proc.name() - except psutil.Error: - pass - else: - if name == pgname: - pids.append(str(proc.pid)) - continue - - try: - cmdline = proc.cmdline() - except psutil.Error: - pass - else: - if cmdline and cmdline[0] == pgname: - pids.append(str(proc.pid)) - - return pids - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: %s pgname' % __file__) - else: - pgname = sys.argv[1] - pids = pidof(pgname) - if pids: - print(" ".join(pids)) - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/pmap.py b/python/psutil/examples/pmap.py deleted file mode 100755 index 7593777ae..000000000 --- a/python/psutil/examples/pmap.py +++ /dev/null @@ -1,57 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'pmap' utility on Linux, 'vmmap' on OSX and 'procstat -v' on BSD. -Report memory map of a process. - -$ python examples/pmap.py 32402 -pid=32402, name=hg -Address RSS Mode Mapping -0000000000400000 1200K r-xp /usr/bin/python2.7 -0000000000838000 4K r--p /usr/bin/python2.7 -0000000000839000 304K rw-p /usr/bin/python2.7 -00000000008ae000 68K rw-p [anon] -000000000275e000 5396K rw-p [heap] -00002b29bb1e0000 124K r-xp /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb203000 8K rw-p [anon] -00002b29bb220000 528K rw-p [anon] -00002b29bb2d8000 768K rw-p [anon] -00002b29bb402000 4K r--p /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb403000 8K rw-p /lib/x86_64-linux-gnu/ld-2.17.so -00002b29bb405000 60K r-xp /lib/x86_64-linux-gnu/libpthread-2.17.so -00002b29bb41d000 0K ---p /lib/x86_64-linux-gnu/libpthread-2.17.so -00007fff94be6000 48K rw-p [stack] -00007fff94dd1000 4K r-xp [vdso] -ffffffffff600000 0K r-xp [vsyscall] -... -""" - -import sys - -import psutil - - -def main(): - if len(sys.argv) != 2: - sys.exit('usage: pmap <pid>') - p = psutil.Process(int(sys.argv[1])) - print("pid=%s, name=%s" % (p.pid, p.name())) - templ = "%-16s %10s %-7s %s" - print(templ % ("Address", "RSS", "Mode", "Mapping")) - total_rss = 0 - for m in p.memory_maps(grouped=False): - total_rss += m.rss - print(templ % ( - m.addr.split('-')[0].zfill(16), - str(m.rss / 1024) + 'K', - m.perms, - m.path)) - print("-" * 33) - print(templ % ("Total", str(total_rss / 1024) + 'K', '', '')) - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/process_detail.py b/python/psutil/examples/process_detail.py deleted file mode 100755 index e20371aef..000000000 --- a/python/psutil/examples/process_detail.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Print detailed information about a process. -Author: Giampaolo Rodola' <g.rodola@gmail.com> - -$ python examples/process_detail.py -pid 820 -name python -exe /usr/bin/python2.7 -parent 29613 (bash) -cmdline python examples/process_detail.py -started 2014-41-27 03:41 -user giampaolo -uids real=1000, effective=1000, saved=1000 -gids real=1000, effective=1000, saved=1000 -terminal /dev/pts/17 -cwd /ssd/svn/psutil -memory 0.1% (resident=10.6M, virtual=58.5M) -cpu 0.0% (user=0.09, system=0.0) -status running -niceness 0 -num threads 1 -I/O bytes-read=0B, bytes-written=0B -open files -running threads id=820, user-time=0.09, sys-time=0.0 -""" - -import datetime -import os -import socket -import sys - -import psutil - - -POSIX = os.name == 'posix' - - -def convert_bytes(n): - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = float(n) / prefix[s] - return '%.1f%s' % (value, s) - return "%sB" % n - - -def print_(a, b): - if sys.stdout.isatty() and POSIX: - fmt = '\x1b[1;32m%-17s\x1b[0m %s' % (a, b) - else: - fmt = '%-15s %s' % (a, b) - # python 2/3 compatibility layer - sys.stdout.write(fmt + '\n') - sys.stdout.flush() - - -def run(pid): - ACCESS_DENIED = '' - try: - p = psutil.Process(pid) - pinfo = p.as_dict(ad_value=ACCESS_DENIED) - except psutil.NoSuchProcess as err: - sys.exit(str(err)) - - try: - parent = p.parent() - if parent: - parent = '(%s)' % parent.name() - else: - parent = '' - except psutil.Error: - parent = '' - if pinfo['create_time'] != ACCESS_DENIED: - started = datetime.datetime.fromtimestamp( - pinfo['create_time']).strftime('%Y-%m-%d %H:%M') - else: - started = ACCESS_DENIED - io = pinfo.get('io_counters', ACCESS_DENIED) - if pinfo['memory_info'] != ACCESS_DENIED: - mem = '%s%% (resident=%s, virtual=%s) ' % ( - round(pinfo['memory_percent'], 1), - convert_bytes(pinfo['memory_info'].rss), - convert_bytes(pinfo['memory_info'].vms)) - else: - mem = ACCESS_DENIED - children = p.children() - - print_('pid', pinfo['pid']) - print_('name', pinfo['name']) - print_('exe', pinfo['exe']) - print_('parent', '%s %s' % (pinfo['ppid'], parent)) - print_('cmdline', ' '.join(pinfo['cmdline'])) - print_('started', started) - print_('user', pinfo['username']) - if POSIX and pinfo['uids'] and pinfo['gids']: - print_('uids', 'real=%s, effective=%s, saved=%s' % pinfo['uids']) - if POSIX and pinfo['gids']: - print_('gids', 'real=%s, effective=%s, saved=%s' % pinfo['gids']) - if POSIX: - print_('terminal', pinfo['terminal'] or '') - print_('cwd', pinfo['cwd']) - print_('memory', mem) - print_('cpu', '%s%% (user=%s, system=%s)' % ( - pinfo['cpu_percent'], - getattr(pinfo['cpu_times'], 'user', '?'), - getattr(pinfo['cpu_times'], 'system', '?'))) - print_('status', pinfo['status']) - print_('niceness', pinfo['nice']) - print_('num threads', pinfo['num_threads']) - if io != ACCESS_DENIED: - print_('I/O', 'bytes-read=%s, bytes-written=%s' % ( - convert_bytes(io.read_bytes), - convert_bytes(io.write_bytes))) - if children: - print_('children', '') - for child in children: - print_('', 'pid=%s name=%s' % (child.pid, child.name())) - - if pinfo['open_files'] != ACCESS_DENIED: - print_('open files', '') - for file in pinfo['open_files']: - print_('', 'fd=%s %s ' % (file.fd, file.path)) - - if pinfo['threads']: - print_('running threads', '') - for thread in pinfo['threads']: - print_('', 'id=%s, user-time=%s, sys-time=%s' % ( - thread.id, thread.user_time, thread.system_time)) - if pinfo['connections'] not in (ACCESS_DENIED, []): - print_('open connections', '') - for conn in pinfo['connections']: - if conn.type == socket.SOCK_STREAM: - type = 'TCP' - elif conn.type == socket.SOCK_DGRAM: - type = 'UDP' - else: - type = 'UNIX' - lip, lport = conn.laddr - if not conn.raddr: - rip, rport = '*', '*' - else: - rip, rport = conn.raddr - print_('', '%s:%s -> %s:%s type=%s status=%s' % ( - lip, lport, rip, rport, type, conn.status)) - - -def main(argv=None): - if argv is None: - argv = sys.argv - if len(argv) == 1: - sys.exit(run(os.getpid())) - elif len(argv) == 2: - sys.exit(run(int(argv[1]))) - else: - sys.exit('usage: %s [pid]' % __file__) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/python/psutil/examples/ps.py b/python/psutil/examples/ps.py deleted file mode 100644 index 2b67bd18f..000000000 --- a/python/psutil/examples/ps.py +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'ps -aux' on UNIX. - -$ python examples/ps.py -... -""" - -import datetime -import os -import time - -import psutil - - -def main(): - today_day = datetime.date.today() - templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s" - attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times', - 'create_time', 'memory_info'] - if os.name == 'posix': - attrs.append('uids') - attrs.append('terminal') - print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY", - "START", "TIME", "COMMAND")) - for p in psutil.process_iter(): - try: - pinfo = p.as_dict(attrs, ad_value='') - except psutil.NoSuchProcess: - pass - else: - if pinfo['create_time']: - ctime = datetime.datetime.fromtimestamp(pinfo['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - cputime = time.strftime("%M:%S", - time.localtime(sum(pinfo['cpu_times']))) - try: - user = p.username() - except KeyError: - if os.name == 'posix': - if pinfo['uids']: - user = str(pinfo['uids'].real) - else: - user = '' - else: - raise - except psutil.Error: - user = '' - if os.name == 'nt' and '\\' in user: - user = user.split('\\')[1] - vms = pinfo['memory_info'] and \ - int(pinfo['memory_info'].vms / 1024) or '?' - rss = pinfo['memory_info'] and \ - int(pinfo['memory_info'].rss / 1024) or '?' - memp = pinfo['memory_percent'] and \ - round(pinfo['memory_percent'], 1) or '?' - print(templ % ( - user[:10], - pinfo['pid'], - pinfo['cpu_percent'], - memp, - vms, - rss, - pinfo.get('terminal', '') or '?', - ctime, - cputime, - pinfo['name'].strip() or '?')) - - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/pstree.py b/python/psutil/examples/pstree.py deleted file mode 100644 index 1bf8c9c04..000000000 --- a/python/psutil/examples/pstree.py +++ /dev/null @@ -1,71 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -Similar to 'ps aux --forest' on Linux, prints the process list -as a tree structure. - -$ python examples/pstree.py -0 ? -|- 1 init -| |- 289 cgmanager -| |- 616 upstart-socket-bridge -| |- 628 rpcbind -| |- 892 upstart-file-bridge -| |- 907 dbus-daemon -| |- 978 avahi-daemon -| | `_ 979 avahi-daemon -| |- 987 NetworkManager -| | |- 2242 dnsmasq -| | `_ 10699 dhclient -| |- 993 polkitd -| |- 1061 getty -| |- 1066 su -| | `_ 1190 salt-minion... -... -""" - -from __future__ import print_function -import collections -import sys - -import psutil - - -def print_tree(parent, tree, indent=''): - try: - name = psutil.Process(parent).name() - except psutil.Error: - name = "?" - print(parent, name) - if parent not in tree: - return - children = tree[parent][:-1] - for child in children: - sys.stdout.write(indent + "|- ") - print_tree(child, tree, indent + "| ") - child = tree[parent][-1] - sys.stdout.write(indent + "`_ ") - print_tree(child, tree, indent + " ") - - -def main(): - # construct a dict where 'values' are all the processes - # having 'key' as their parent - tree = collections.defaultdict(list) - for p in psutil.process_iter(): - try: - tree[p.ppid()].append(p.pid) - except (psutil.NoSuchProcess, psutil.ZombieProcess): - pass - # on systems supporting PID 0, PID 0's parent is usually 0 - if 0 in tree and 0 in tree[0]: - tree[0].remove(0) - print_tree(min(tree), tree) - - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/top.py b/python/psutil/examples/top.py deleted file mode 100755 index 30df417f5..000000000 --- a/python/psutil/examples/top.py +++ /dev/null @@ -1,233 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of top / htop. - -Author: Giampaolo Rodola' <g.rodola@gmail.com> - -$ python examples/top.py - CPU0 [| ] 4.9% - CPU1 [||| ] 7.8% - CPU2 [ ] 2.0% - CPU3 [||||| ] 13.9% - Mem [||||||||||||||||||| ] 49.8% 4920M/9888M - Swap [ ] 0.0% 0M/0M - Processes: 287 (running=1 sleeping=286) - Load average: 0.34 0.54 0.46 Uptime: 3 days, 10:16:37 - -PID USER NI VIRT RES CPU% MEM% TIME+ NAME ------------------------------------------------------------- -989 giampaol 0 66M 12M 7.4 0.1 0:00.61 python -2083 root 0 506M 159M 6.5 1.6 0:29.26 Xorg -4503 giampaol 0 599M 25M 6.5 0.3 3:32.60 gnome-terminal -3868 giampaol 0 358M 8M 2.8 0.1 23:12.60 pulseaudio -3936 giampaol 0 1G 111M 2.8 1.1 33:41.67 compiz -4401 giampaol 0 536M 141M 2.8 1.4 35:42.73 skype -4047 giampaol 0 743M 76M 1.8 0.8 42:03.33 unity-panel-service -13155 giampaol 0 1G 280M 1.8 2.8 41:57.34 chrome -10 root 0 0B 0B 0.9 0.0 4:01.81 rcu_sched -339 giampaol 0 1G 113M 0.9 1.1 8:15.73 chrome -... -""" - -from datetime import datetime, timedelta -import atexit -import os -import time -import sys -try: - import curses -except ImportError: - sys.exit('platform not supported') - -import psutil - - -# --- curses stuff -def tear_down(): - win.keypad(0) - curses.nocbreak() - curses.echo() - curses.endwin() - -win = curses.initscr() -atexit.register(tear_down) -curses.endwin() -lineno = 0 - - -def print_line(line, highlight=False): - """A thin wrapper around curses's addstr().""" - global lineno - try: - if highlight: - line += " " * (win.getmaxyx()[1] - len(line)) - win.addstr(lineno, 0, line, curses.A_REVERSE) - else: - win.addstr(lineno, 0, line, 0) - except curses.error: - lineno = 0 - win.refresh() - raise - else: - lineno += 1 -# --- /curses stuff - - -def bytes2human(n): - """ - >>> bytes2human(10000) - '9K' - >>> bytes2human(100001221) - '95M' - """ - symbols = ('K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y') - prefix = {} - for i, s in enumerate(symbols): - prefix[s] = 1 << (i + 1) * 10 - for s in reversed(symbols): - if n >= prefix[s]: - value = int(float(n) / prefix[s]) - return '%s%s' % (value, s) - return "%sB" % n - - -def poll(interval): - # sleep some time - time.sleep(interval) - procs = [] - procs_status = {} - for p in psutil.process_iter(): - try: - p.dict = p.as_dict(['username', 'nice', 'memory_info', - 'memory_percent', 'cpu_percent', - 'cpu_times', 'name', 'status']) - try: - procs_status[p.dict['status']] += 1 - except KeyError: - procs_status[p.dict['status']] = 1 - except psutil.NoSuchProcess: - pass - else: - procs.append(p) - - # return processes sorted by CPU percent usage - processes = sorted(procs, key=lambda p: p.dict['cpu_percent'], - reverse=True) - return (processes, procs_status) - - -def print_header(procs_status, num_procs): - """Print system-related info, above the process list.""" - - def get_dashes(perc): - dashes = "|" * int((float(perc) / 10 * 4)) - empty_dashes = " " * (40 - len(dashes)) - return dashes, empty_dashes - - # cpu usage - percs = psutil.cpu_percent(interval=0, percpu=True) - for cpu_num, perc in enumerate(percs): - dashes, empty_dashes = get_dashes(perc) - print_line(" CPU%-2s [%s%s] %5s%%" % (cpu_num, dashes, empty_dashes, - perc)) - mem = psutil.virtual_memory() - dashes, empty_dashes = get_dashes(mem.percent) - used = mem.total - mem.available - line = " Mem [%s%s] %5s%% %6s/%s" % ( - dashes, empty_dashes, - mem.percent, - str(int(used / 1024 / 1024)) + "M", - str(int(mem.total / 1024 / 1024)) + "M" - ) - print_line(line) - - # swap usage - swap = psutil.swap_memory() - dashes, empty_dashes = get_dashes(swap.percent) - line = " Swap [%s%s] %5s%% %6s/%s" % ( - dashes, empty_dashes, - swap.percent, - str(int(swap.used / 1024 / 1024)) + "M", - str(int(swap.total / 1024 / 1024)) + "M" - ) - print_line(line) - - # processes number and status - st = [] - for x, y in procs_status.items(): - if y: - st.append("%s=%s" % (x, y)) - st.sort(key=lambda x: x[:3] in ('run', 'sle'), reverse=1) - print_line(" Processes: %s (%s)" % (num_procs, ' '.join(st))) - # load average, uptime - uptime = datetime.utcnow() - datetime.fromtimestamp(psutil.boot_time()) - av1, av2, av3 = os.getloadavg() - line = " Load average: %.2f %.2f %.2f Uptime: %s" \ - % (av1, av2, av3, str(uptime).split('.')[0]) - print_line(line) - - -def refresh_window(procs, procs_status): - """Print results on screen by using curses.""" - curses.endwin() - templ = "%-6s %-8s %4s %5s %5s %6s %4s %9s %2s" - win.erase() - header = templ % ("PID", "USER", "NI", "VIRT", "RES", "CPU%", "MEM%", - "TIME+", "NAME") - print_header(procs_status, len(procs)) - print_line("") - print_line(header, highlight=True) - for p in procs: - # TIME+ column shows process CPU cumulative time and it - # is expressed as: "mm:ss.ms" - if p.dict['cpu_times'] is not None: - ctime = timedelta(seconds=sum(p.dict['cpu_times'])) - ctime = "%s:%s.%s" % (ctime.seconds // 60 % 60, - str((ctime.seconds % 60)).zfill(2), - str(ctime.microseconds)[:2]) - else: - ctime = '' - if p.dict['memory_percent'] is not None: - p.dict['memory_percent'] = round(p.dict['memory_percent'], 1) - else: - p.dict['memory_percent'] = '' - if p.dict['cpu_percent'] is None: - p.dict['cpu_percent'] = '' - if p.dict['username']: - username = p.dict['username'][:8] - else: - username = "" - line = templ % (p.pid, - username, - p.dict['nice'], - bytes2human(getattr(p.dict['memory_info'], 'vms', 0)), - bytes2human(getattr(p.dict['memory_info'], 'rss', 0)), - p.dict['cpu_percent'], - p.dict['memory_percent'], - ctime, - p.dict['name'] or '', - ) - try: - print_line(line) - except curses.error: - break - win.refresh() - - -def main(): - try: - interval = 0 - while True: - args = poll(interval) - refresh_window(*args) - interval = 1 - except (KeyboardInterrupt, SystemExit): - pass - -if __name__ == '__main__': - main() diff --git a/python/psutil/examples/who.py b/python/psutil/examples/who.py deleted file mode 100755 index b382bebfa..000000000 --- a/python/psutil/examples/who.py +++ /dev/null @@ -1,33 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A clone of 'who' command; print information about users who are -currently logged in. - -$ python examples/who.py -giampaolo tty7 2014-02-23 17:25 (:0) -giampaolo pts/7 2014-02-24 18:25 (:192.168.1.56) -giampaolo pts/8 2014-02-24 18:25 (:0) -giampaolo pts/9 2014-02-27 01:32 (:0) -""" - -from datetime import datetime - -import psutil - - -def main(): - users = psutil.users() - for user in users: - print("%-15s %-15s %s (%s)" % ( - user.name, - user.terminal or '-', - datetime.fromtimestamp(user.started).strftime("%Y-%m-%d %H:%M"), - user.host)) - -if __name__ == '__main__': - main() diff --git a/python/psutil/make.bat b/python/psutil/make.bat deleted file mode 100644 index 9c430101d..000000000 --- a/python/psutil/make.bat +++ /dev/null @@ -1,201 +0,0 @@ -@echo off - -rem ========================================================================== -rem Shortcuts for various tasks, emulating UNIX "make" on Windows. -rem It is primarly intended as a shortcut for compiling / installing -rem psutil ("make.bat build", "make.bat install") and running tests -rem ("make.bat test"). -rem -rem This script is modeled after my Windows installation which uses: -rem - Visual studio 2008 for Python 2.6, 2.7, 3.2 -rem - Visual studio 2010 for Python 3.3+ -rem ...therefore it might not work on your Windows installation. -rem -rem By default C:\Python27\python.exe is used. -rem To compile for a specific Python version run: -rem set PYTHON=C:\Python34\python.exe & make.bat build -rem -rem To use a different test script: -rem set PYTHON=C:\Python34\python.exe & set TSCRIPT=foo.py & make.bat test -rem ========================================================================== - -if "%PYTHON%" == "" ( - set PYTHON=C:\Python27\python.exe -) -if "%TSCRIPT%" == "" ( - set TSCRIPT=test\test_psutil.py -) - -set PYTHON26=C:\Python26\python.exe -set PYTHON27=C:\Python27\python.exe -set PYTHON33=C:\Python33\python.exe -set PYTHON34=C:\Python34\python.exe -set PYTHON26-64=C:\Python26-64\python.exe -set PYTHON27-64=C:\Python27-64\python.exe -set PYTHON33-64=C:\Python33-64\python.exe -set PYTHON34-64=C:\Python34-64\python.exe - -set ALL_PYTHONS=%PYTHON26% %PYTHON27% %PYTHON33% %PYTHON34% %PYTHON26-64% %PYTHON27-64% %PYTHON33-64% %PYTHON34-64% - -rem Needed to locate the .pypirc file and upload exes on PYPI. -set HOME=%USERPROFILE% - -rem ========================================================================== - -if "%1" == "help" ( - :help - echo Run `make ^<target^>` where ^<target^> is one of: - echo build compile without installing - echo build-all build exes + wheels - echo clean clean build files - echo flake8 run flake8 - echo install compile and install - echo setup-dev-env install pip, pywin32, wheels, etc. for all python versions - echo test run tests - echo test-memleaks run memory leak tests - echo test-process run process related tests - echo test-system run system APIs related tests - echo uninstall uninstall - echo upload-all upload exes + wheels - goto :eof -) - -if "%1" == "clean" ( - for /r %%R in (__pycache__) do if exist %%R (rmdir /S /Q %%R) - for /r %%R in (*.pyc) do if exist %%R (del /s %%R) - for /r %%R in (*.pyd) do if exist %%R (del /s %%R) - for /r %%R in (*.orig) do if exist %%R (del /s %%R) - for /r %%R in (*.bak) do if exist %%R (del /s %%R) - for /r %%R in (*.rej) do if exist %%R (del /s %%R) - if exist psutil.egg-info (rmdir /S /Q psutil.egg-info) - if exist build (rmdir /S /Q build) - if exist dist (rmdir /S /Q dist) - goto :eof -) - -if "%1" == "build" ( - :build - "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" - %PYTHON% setup.py build - if %errorlevel% neq 0 goto :error - rem copies *.pyd files in ./psutil directory in order to allow - rem "import psutil" when using the interactive interpreter from - rem within this directory. - %PYTHON% setup.py build_ext -i - if %errorlevel% neq 0 goto :error - goto :eof -) - -if "%1" == "install" ( - :install - call :build - %PYTHON% setup.py install - goto :eof -) - -if "%1" == "uninstall" ( - for %%A in ("%PYTHON%") do ( - set folder=%%~dpA - ) - for /F "delims=" %%i in ('dir /b %folder%\Lib\site-packages\*psutil*') do ( - rmdir /S /Q %folder%\Lib\site-packages\%%i - ) - goto :eof -) - -if "%1" == "test" ( - call :install - %PYTHON% %TSCRIPT% - goto :eof -) - -if "%1" == "test-process" ( - call :install - %PYTHON% -m unittest -v test.test_psutil.TestProcess - goto :eof -) - -if "%1" == "test-system" ( - call :install - %PYTHON% -m unittest -v test.test_psutil.TestSystem - goto :eof -) - -if "%1" == "test-memleaks" ( - call :install - %PYTHON% test\test_memory_leaks.py - goto :eof -) - -if "%1" == "build-all" ( - :build-all - "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" - for %%P in (%ALL_PYTHONS%) do ( - @echo ------------------------------------------------ - @echo building exe for %%P - @echo ------------------------------------------------ - %%P setup.py build bdist_wininst || goto :error - @echo ------------------------------------------------ - @echo building wheel for %%P - @echo ------------------------------------------------ - %%P setup.py build bdist_wheel || goto :error - ) - echo OK - goto :eof -) - -if "%1" == "upload-all" ( - :upload-exes - "C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC\bin\vcvars64.bat" - for %%P in (%ALL_PYTHONS%) do ( - @echo ------------------------------------------------ - @echo uploading exe for %%P - @echo ------------------------------------------------ - %%P setup.py build bdist_wininst upload || goto :error - @echo ------------------------------------------------ - @echo uploading wheel for %%P - @echo ------------------------------------------------ - %%P setup.py build bdist_wheel upload || goto :error - ) - echo OK - goto :eof -) - -if "%1" == "setup-dev-env" ( - :setup-env - @echo ------------------------------------------------ - @echo downloading pip installer - @echo ------------------------------------------------ - C:\python27\python.exe -c "import urllib2; r = urllib2.urlopen('https://raw.github.com/pypa/pip/master/contrib/get-pip.py'); open('get-pip.py', 'wb').write(r.read())" - for %%P in (%ALL_PYTHONS%) do ( - @echo ------------------------------------------------ - @echo installing pip for %%P - @echo ------------------------------------------------ - %%P get-pip.py - ) - for %%P in (%ALL_PYTHONS%) do ( - @echo ------------------------------------------------ - @echo installing deps for %%P - @echo ------------------------------------------------ - rem mandatory / for unittests - %%P -m pip install unittest2 ipaddress mock wmi wheel pypiwin32 --upgrade - rem nice to have - %%P -m pip install ipdb pep8 pyflakes flake8 --upgrade - ) - goto :eof -) - -if "%1" == "flake8" ( - :flake8 - %PYTHON% -c "from flake8.main import main; main()" - goto :eof -) - -goto :help - -:error - @echo ------------------------------------------------ - @echo last command exited with error code %errorlevel% - @echo ------------------------------------------------ - @exit /b %errorlevel% - goto :eof diff --git a/python/psutil/psutil/__init__.py b/python/psutil/psutil/__init__.py deleted file mode 100644 index 1444425b8..000000000 --- a/python/psutil/psutil/__init__.py +++ /dev/null @@ -1,1887 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""psutil is a cross-platform library for retrieving information on -running processes and system utilization (CPU, memory, disks, network) -in Python. -""" - -from __future__ import division - -import collections -import errno -import functools -import os -import signal -import subprocess -import sys -import time -try: - import pwd -except ImportError: - pwd = None - -from . import _common -from ._common import memoize -from ._compat import callable, long -from ._compat import PY3 as _PY3 - -from ._common import (STATUS_RUNNING, # NOQA - STATUS_SLEEPING, - STATUS_DISK_SLEEP, - STATUS_STOPPED, - STATUS_TRACING_STOP, - STATUS_ZOMBIE, - STATUS_DEAD, - STATUS_WAKING, - STATUS_LOCKED, - STATUS_IDLE, # bsd - STATUS_WAITING) # bsd - -from ._common import (CONN_ESTABLISHED, - CONN_SYN_SENT, - CONN_SYN_RECV, - CONN_FIN_WAIT1, - CONN_FIN_WAIT2, - CONN_TIME_WAIT, - CONN_CLOSE, - CONN_CLOSE_WAIT, - CONN_LAST_ACK, - CONN_LISTEN, - CONN_CLOSING, - CONN_NONE) - -from ._common import (NIC_DUPLEX_FULL, # NOQA - NIC_DUPLEX_HALF, - NIC_DUPLEX_UNKNOWN) - -if sys.platform.startswith("linux"): - from . import _pslinux as _psplatform - - from ._pslinux import (IOPRIO_CLASS_NONE, # NOQA - IOPRIO_CLASS_RT, - IOPRIO_CLASS_BE, - IOPRIO_CLASS_IDLE) - # Linux >= 2.6.36 - if _psplatform.HAS_PRLIMIT: - from ._psutil_linux import (RLIM_INFINITY, # NOQA - RLIMIT_AS, - RLIMIT_CORE, - RLIMIT_CPU, - RLIMIT_DATA, - RLIMIT_FSIZE, - RLIMIT_LOCKS, - RLIMIT_MEMLOCK, - RLIMIT_NOFILE, - RLIMIT_NPROC, - RLIMIT_RSS, - RLIMIT_STACK) - # Kinda ugly but considerably faster than using hasattr() and - # setattr() against the module object (we are at import time: - # speed matters). - from . import _psutil_linux - try: - RLIMIT_MSGQUEUE = _psutil_linux.RLIMIT_MSGQUEUE - except AttributeError: - pass - try: - RLIMIT_NICE = _psutil_linux.RLIMIT_NICE - except AttributeError: - pass - try: - RLIMIT_RTPRIO = _psutil_linux.RLIMIT_RTPRIO - except AttributeError: - pass - try: - RLIMIT_RTTIME = _psutil_linux.RLIMIT_RTTIME - except AttributeError: - pass - try: - RLIMIT_SIGPENDING = _psutil_linux.RLIMIT_SIGPENDING - except AttributeError: - pass - del _psutil_linux - -elif sys.platform.startswith("win32"): - from . import _pswindows as _psplatform - from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS, # NOQA - BELOW_NORMAL_PRIORITY_CLASS, - HIGH_PRIORITY_CLASS, - IDLE_PRIORITY_CLASS, - NORMAL_PRIORITY_CLASS, - REALTIME_PRIORITY_CLASS) - from ._pswindows import CONN_DELETE_TCB # NOQA - -elif sys.platform.startswith("darwin"): - from . import _psosx as _psplatform - -elif sys.platform.startswith("freebsd"): - from . import _psbsd as _psplatform - -elif sys.platform.startswith("sunos"): - from . import _pssunos as _psplatform - from ._pssunos import (CONN_IDLE, # NOQA - CONN_BOUND) - -else: # pragma: no cover - raise NotImplementedError('platform %s is not supported' % sys.platform) - - -__all__ = [ - # exceptions - "Error", "NoSuchProcess", "ZombieProcess", "AccessDenied", - "TimeoutExpired", - # constants - "version_info", "__version__", - "STATUS_RUNNING", "STATUS_IDLE", "STATUS_SLEEPING", "STATUS_DISK_SLEEP", - "STATUS_STOPPED", "STATUS_TRACING_STOP", "STATUS_ZOMBIE", "STATUS_DEAD", - "STATUS_WAKING", "STATUS_LOCKED", "STATUS_WAITING", "STATUS_LOCKED", - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", "CONN_NONE", - "AF_LINK", - "NIC_DUPLEX_FULL", "NIC_DUPLEX_HALF", "NIC_DUPLEX_UNKNOWN", - # classes - "Process", "Popen", - # functions - "pid_exists", "pids", "process_iter", "wait_procs", # proc - "virtual_memory", "swap_memory", # memory - "cpu_times", "cpu_percent", "cpu_times_percent", "cpu_count", # cpu - "net_io_counters", "net_connections", "net_if_addrs", # network - "net_if_stats", - "disk_io_counters", "disk_partitions", "disk_usage", # disk - "users", "boot_time", # others -] -__all__.extend(_psplatform.__extra__all__) -__author__ = "Giampaolo Rodola'" -__version__ = "3.1.1" -version_info = tuple([int(num) for num in __version__.split('.')]) -AF_LINK = _psplatform.AF_LINK -_TOTAL_PHYMEM = None -_POSIX = os.name == 'posix' -_WINDOWS = os.name == 'nt' -_timer = getattr(time, 'monotonic', time.time) - - -# Sanity check in case the user messed up with psutil installation -# or did something weird with sys.path. In this case we might end -# up importing a python module using a C extension module which -# was compiled for a different version of psutil. -# We want to prevent that by failing sooner rather than later. -# See: https://github.com/giampaolo/psutil/issues/564 -if (int(__version__.replace('.', '')) != - getattr(_psplatform.cext, 'version', None)): - msg = "version conflict: %r C extension module was built for another " \ - "version of psutil (different than %s)" % (_psplatform.cext.__file__, - __version__) - raise ImportError(msg) - - -# ===================================================================== -# --- exceptions -# ===================================================================== - -class Error(Exception): - """Base exception class. All other psutil exceptions inherit - from this one. - """ - - def __init__(self, msg=""): - self.msg = msg - - def __repr__(self): - ret = "%s.%s %s" % (self.__class__.__module__, - self.__class__.__name__, self.msg) - return ret.strip() - - __str__ = __repr__ - - -class NoSuchProcess(Error): - """Exception raised when a process with a certain PID doesn't - or no longer exists. - """ - - def __init__(self, pid, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if name: - details = "(pid=%s, name=%s)" % (self.pid, repr(self.name)) - else: - details = "(pid=%s)" % self.pid - self.msg = "process no longer exists " + details - - -class ZombieProcess(NoSuchProcess): - """Exception raised when querying a zombie process. This is - raised on OSX, BSD and Solaris only, and not always: depending - on the query the OS may be able to succeed anyway. - On Linux all zombie processes are querable (hence this is never - raised). Windows doesn't have zombie processes. - """ - - def __init__(self, pid, name=None, ppid=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.ppid = ppid - self.name = name - self.msg = msg - if msg is None: - if name and ppid: - details = "(pid=%s, name=%s, ppid=%s)" % ( - self.pid, repr(self.name), self.ppid) - elif name: - details = "(pid=%s, name=%s)" % (self.pid, repr(self.name)) - else: - details = "(pid=%s)" % self.pid - self.msg = "process still exists but it's a zombie " + details - - -class AccessDenied(Error): - """Exception raised when permission to perform an action is denied.""" - - def __init__(self, pid=None, name=None, msg=None): - Error.__init__(self, msg) - self.pid = pid - self.name = name - self.msg = msg - if msg is None: - if (pid is not None) and (name is not None): - self.msg = "(pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg = "(pid=%s)" % self.pid - else: - self.msg = "" - - -class TimeoutExpired(Error): - """Raised on Process.wait(timeout) if timeout expires and process - is still alive. - """ - - def __init__(self, seconds, pid=None, name=None): - Error.__init__(self, "timeout after %s seconds" % seconds) - self.seconds = seconds - self.pid = pid - self.name = name - if (pid is not None) and (name is not None): - self.msg += " (pid=%s, name=%s)" % (pid, repr(name)) - elif (pid is not None): - self.msg += " (pid=%s)" % self.pid - - -# push exception classes into platform specific module namespace -_psplatform.NoSuchProcess = NoSuchProcess -_psplatform.ZombieProcess = ZombieProcess -_psplatform.AccessDenied = AccessDenied -_psplatform.TimeoutExpired = TimeoutExpired - - -# ===================================================================== -# --- Process class -# ===================================================================== - - -def _assert_pid_not_reused(fun): - """Decorator which raises NoSuchProcess in case a process is no - longer running or its PID has been reused. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - return fun(self, *args, **kwargs) - return wrapper - - -class Process(object): - """Represents an OS process with the given PID. - If PID is omitted current process PID (os.getpid()) is used. - Raise NoSuchProcess if PID does not exist. - - Note that most of the methods of this class do not make sure - the PID of the process being queried has been reused over time. - That means you might end up retrieving an information referring - to another process in case the original one this instance - refers to is gone in the meantime. - - The only exceptions for which process identity is pre-emptively - checked and guaranteed are: - - - parent() - - children() - - nice() (set) - - ionice() (set) - - rlimit() (set) - - cpu_affinity (set) - - suspend() - - resume() - - send_signal() - - terminate() - - kill() - - To prevent this problem for all other methods you can: - - use is_running() before querying the process - - if you're continuously iterating over a set of Process - instances use process_iter() which pre-emptively checks - process identity for every yielded instance - """ - - def __init__(self, pid=None): - self._init(pid) - - def _init(self, pid, _ignore_nsp=False): - if pid is None: - pid = os.getpid() - else: - if not _PY3 and not isinstance(pid, (int, long)): - raise TypeError('pid must be an integer (got %r)' % pid) - if pid < 0: - raise ValueError('pid must be a positive integer (got %s)' - % pid) - self._pid = pid - self._name = None - self._exe = None - self._create_time = None - self._gone = False - self._hash = None - # used for caching on Windows only (on POSIX ppid may change) - self._ppid = None - # platform-specific modules define an _psplatform.Process - # implementation class - self._proc = _psplatform.Process(pid) - self._last_sys_cpu_times = None - self._last_proc_cpu_times = None - # cache creation time for later use in is_running() method - try: - self.create_time() - except AccessDenied: - # we should never get here as AFAIK we're able to get - # process creation time on all platforms even as a - # limited user - pass - except ZombieProcess: - # Let's consider a zombie process as legitimate as - # tehcnically it's still alive (it can be queried, - # although not always, and it's returned by pids()). - pass - except NoSuchProcess: - if not _ignore_nsp: - msg = 'no process found with pid %s' % pid - raise NoSuchProcess(pid, None, msg) - else: - self._gone = True - # This pair is supposed to indentify a Process instance - # univocally over time (the PID alone is not enough as - # it might refer to a process whose PID has been reused). - # This will be used later in __eq__() and is_running(). - self._ident = (self.pid, self._create_time) - - def __str__(self): - try: - pid = self.pid - name = repr(self.name()) - except ZombieProcess: - details = "(pid=%s (zombie))" % self.pid - except NoSuchProcess: - details = "(pid=%s (terminated))" % self.pid - except AccessDenied: - details = "(pid=%s)" % (self.pid) - else: - details = "(pid=%s, name=%s)" % (pid, name) - return "%s.%s%s" % (self.__class__.__module__, - self.__class__.__name__, details) - - def __repr__(self): - return "<%s at %s>" % (self.__str__(), id(self)) - - def __eq__(self, other): - # Test for equality with another Process object based - # on PID and creation time. - if not isinstance(other, Process): - return NotImplemented - return self._ident == other._ident - - def __ne__(self, other): - return not self == other - - def __hash__(self): - if self._hash is None: - self._hash = hash(self._ident) - return self._hash - - # --- utility methods - - def as_dict(self, attrs=None, ad_value=None): - """Utility method returning process information as a - hashable dictionary. - - If 'attrs' is specified it must be a list of strings - reflecting available Process class' attribute names - (e.g. ['cpu_times', 'name']) else all public (read - only) attributes are assumed. - - 'ad_value' is the value which gets assigned in case - AccessDenied or ZombieProcess exception is raised when - retrieving that particular process information. - """ - excluded_names = set( - ['send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'is_running', 'as_dict', 'parent', 'children', 'rlimit']) - retdict = dict() - ls = set(attrs or [x for x in dir(self)]) - for name in ls: - if name.startswith('_'): - continue - if name in excluded_names: - continue - try: - attr = getattr(self, name) - if callable(attr): - ret = attr() - else: - ret = attr - except (AccessDenied, ZombieProcess): - ret = ad_value - except NotImplementedError: - # in case of not implemented functionality (may happen - # on old or exotic systems) we want to crash only if - # the user explicitly asked for that particular attr - if attrs: - raise - continue - retdict[name] = ret - return retdict - - def parent(self): - """Return the parent process as a Process object pre-emptively - checking whether PID has been reused. - If no parent is known return None. - """ - ppid = self.ppid() - if ppid is not None: - ctime = self.create_time() - try: - parent = Process(ppid) - if parent.create_time() <= ctime: - return parent - # ...else ppid has been reused by another process - except NoSuchProcess: - pass - - def is_running(self): - """Return whether this process is running. - It also checks if PID has been reused by another process in - which case return False. - """ - if self._gone: - return False - try: - # Checking if PID is alive is not enough as the PID might - # have been reused by another process: we also want to - # check process identity. - # Process identity / uniqueness over time is greanted by - # (PID + creation time) and that is verified in __eq__. - return self == Process(self.pid) - except NoSuchProcess: - self._gone = True - return False - - # --- actual API - - @property - def pid(self): - """The process PID.""" - return self._pid - - def ppid(self): - """The process parent PID. - On Windows the return value is cached after first call. - """ - # On POSIX we don't want to cache the ppid as it may unexpectedly - # change to 1 (init) in case this process turns into a zombie: - # https://github.com/giampaolo/psutil/issues/321 - # http://stackoverflow.com/questions/356722/ - - # XXX should we check creation time here rather than in - # Process.parent()? - if _POSIX: - return self._proc.ppid() - else: - self._ppid = self._ppid or self._proc.ppid() - return self._ppid - - def name(self): - """The process name. The return value is cached after first call.""" - if self._name is None: - name = self._proc.name() - if _POSIX and len(name) >= 15: - # On UNIX the name gets truncated to the first 15 characters. - # If it matches the first part of the cmdline we return that - # one instead because it's usually more explicative. - # Examples are "gnome-keyring-d" vs. "gnome-keyring-daemon". - try: - cmdline = self.cmdline() - except AccessDenied: - pass - else: - if cmdline: - extended_name = os.path.basename(cmdline[0]) - if extended_name.startswith(name): - name = extended_name - self._proc._name = name - self._name = name - return self._name - - def exe(self): - """The process executable as an absolute path. - May also be an empty string. - The return value is cached after first call. - """ - def guess_it(fallback): - # try to guess exe from cmdline[0] in absence of a native - # exe representation - cmdline = self.cmdline() - if cmdline and hasattr(os, 'access') and hasattr(os, 'X_OK'): - exe = cmdline[0] # the possible exe - # Attempt to guess only in case of an absolute path. - # It is not safe otherwise as the process might have - # changed cwd. - if (os.path.isabs(exe) and - os.path.isfile(exe) and - os.access(exe, os.X_OK)): - return exe - if isinstance(fallback, AccessDenied): - raise fallback - return fallback - - if self._exe is None: - try: - exe = self._proc.exe() - except AccessDenied as err: - return guess_it(fallback=err) - else: - if not exe: - # underlying implementation can legitimately return an - # empty string; if that's the case we don't want to - # raise AD while guessing from the cmdline - try: - exe = guess_it(fallback=exe) - except AccessDenied: - pass - self._exe = exe - return self._exe - - def cmdline(self): - """The command line this process has been called with.""" - return self._proc.cmdline() - - def status(self): - """The process current status as a STATUS_* constant.""" - try: - return self._proc.status() - except ZombieProcess: - return STATUS_ZOMBIE - - def username(self): - """The name of the user that owns the process. - On UNIX this is calculated by using *real* process uid. - """ - if _POSIX: - if pwd is None: - # might happen if python was installed from sources - raise ImportError( - "requires pwd module shipped with standard python") - real_uid = self.uids().real - try: - return pwd.getpwuid(real_uid).pw_name - except KeyError: - # the uid can't be resolved by the system - return str(real_uid) - else: - return self._proc.username() - - def create_time(self): - """The process creation time as a floating point number - expressed in seconds since the epoch, in UTC. - The return value is cached after first call. - """ - if self._create_time is None: - self._create_time = self._proc.create_time() - return self._create_time - - def cwd(self): - """Process current working directory as an absolute path.""" - return self._proc.cwd() - - def nice(self, value=None): - """Get or set process niceness (priority).""" - if value is None: - return self._proc.nice_get() - else: - if not self.is_running(): - raise NoSuchProcess(self.pid, self._name) - self._proc.nice_set(value) - - if _POSIX: - - def uids(self): - """Return process UIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.uids() - - def gids(self): - """Return process GIDs as a (real, effective, saved) - namedtuple. - """ - return self._proc.gids() - - def terminal(self): - """The terminal associated with this process, if any, - else None. - """ - return self._proc.terminal() - - def num_fds(self): - """Return the number of file descriptors opened by this - process (POSIX only). - """ - return self._proc.num_fds() - - # Linux, BSD and Windows only - if hasattr(_psplatform.Process, "io_counters"): - - def io_counters(self): - """Return process I/O statistics as a - (read_count, write_count, read_bytes, write_bytes) - namedtuple. - Those are the number of read/write calls performed and the - amount of bytes read and written by the process. - """ - return self._proc.io_counters() - - # Linux and Windows >= Vista only - if hasattr(_psplatform.Process, "ionice_get"): - - def ionice(self, ioclass=None, value=None): - """Get or set process I/O niceness (priority). - - On Linux 'ioclass' is one of the IOPRIO_CLASS_* constants. - 'value' is a number which goes from 0 to 7. The higher the - value, the lower the I/O priority of the process. - - On Windows only 'ioclass' is used and it can be set to 2 - (normal), 1 (low) or 0 (very low). - - Available on Linux and Windows > Vista only. - """ - if ioclass is None: - if value is not None: - raise ValueError("'ioclass' argument must be specified") - return self._proc.ionice_get() - else: - return self._proc.ionice_set(ioclass, value) - - # Linux only - if hasattr(_psplatform.Process, "rlimit"): - - def rlimit(self, resource, limits=None): - """Get or set process resource limits as a (soft, hard) - tuple. - - 'resource' is one of the RLIMIT_* constants. - 'limits' is supposed to be a (soft, hard) tuple. - - See "man prlimit" for further info. - Available on Linux only. - """ - if limits is None: - return self._proc.rlimit(resource) - else: - return self._proc.rlimit(resource, limits) - - # Windows, Linux and BSD only - if hasattr(_psplatform.Process, "cpu_affinity_get"): - - def cpu_affinity(self, cpus=None): - """Get or set process CPU affinity. - If specified 'cpus' must be a list of CPUs for which you - want to set the affinity (e.g. [0, 1]). - (Windows, Linux and BSD only). - """ - # Automatically remove duplicates both on get and - # set (for get it's not really necessary, it's - # just for extra safety). - if cpus is None: - return list(set(self._proc.cpu_affinity_get())) - else: - self._proc.cpu_affinity_set(list(set(cpus))) - - if _WINDOWS: - - def num_handles(self): - """Return the number of handles opened by this process - (Windows only). - """ - return self._proc.num_handles() - - def num_ctx_switches(self): - """Return the number of voluntary and involuntary context - switches performed by this process. - """ - return self._proc.num_ctx_switches() - - 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). - """ - return self._proc.threads() - - @_assert_pid_not_reused - def children(self, recursive=False): - """Return the children of this process as a list of Process - instances, pre-emptively checking whether PID has been reused. - If recursive is True return all the parent descendants. - - Example (A == this process): - - A ─┐ - │ - ├─ B (child) ─┐ - │ └─ X (grandchild) ─┐ - │ └─ Y (great grandchild) - ├─ C (child) - └─ D (child) - - >>> import psutil - >>> p = psutil.Process() - >>> p.children() - B, C, D - >>> p.children(recursive=True) - B, X, Y, C, D - - Note that in the example above if process X disappears - process Y won't be listed as the reference to process A - is lost. - """ - if hasattr(_psplatform, 'ppid_map'): - # Windows only: obtain a {pid:ppid, ...} dict for all running - # processes in one shot (faster). - ppid_map = _psplatform.ppid_map() - else: - ppid_map = None - - ret = [] - if not recursive: - if ppid_map is None: - # 'slow' version, common to all platforms except Windows - for p in process_iter(): - try: - if p.ppid() == self.pid: - # if child happens to be older than its parent - # (self) it means child's PID has been reused - if self.create_time() <= p.create_time(): - ret.append(p) - except (NoSuchProcess, ZombieProcess): - pass - else: - # Windows only (faster) - for pid, ppid in ppid_map.items(): - if ppid == self.pid: - try: - child = Process(pid) - # if child happens to be older than its parent - # (self) it means child's PID has been reused - if self.create_time() <= child.create_time(): - ret.append(child) - except (NoSuchProcess, ZombieProcess): - pass - else: - # construct a dict where 'values' are all the processes - # having 'key' as their parent - table = collections.defaultdict(list) - if ppid_map is None: - for p in process_iter(): - try: - table[p.ppid()].append(p) - except (NoSuchProcess, ZombieProcess): - pass - else: - for pid, ppid in ppid_map.items(): - try: - p = Process(pid) - table[ppid].append(p) - except (NoSuchProcess, ZombieProcess): - pass - # At this point we have a mapping table where table[self.pid] - # are the current process' children. - # Below, we look for all descendants recursively, similarly - # to a recursive function call. - checkpids = [self.pid] - for pid in checkpids: - for child in table[pid]: - try: - # if child happens to be older than its parent - # (self) it means child's PID has been reused - intime = self.create_time() <= child.create_time() - except (NoSuchProcess, ZombieProcess): - pass - else: - if intime: - ret.append(child) - if child.pid not in checkpids: - checkpids.append(child.pid) - return ret - - def cpu_percent(self, interval=None): - """Return a float representing the current process CPU - utilization as a percentage. - - When interval is 0.0 or None (default) compares process times - to system CPU times elapsed since last call, returning - immediately (non-blocking). That means that the first time - this is called it will return a meaningful 0.0 value. - - When interval is > 0.0 compares process times to system CPU - times elapsed before and after the interval (blocking). - - In this case is recommended for accuracy that this function - be called with at least 0.1 seconds between calls. - - Examples: - - >>> import psutil - >>> p = psutil.Process(os.getpid()) - >>> # blocking - >>> p.cpu_percent(interval=1) - 2.0 - >>> # non-blocking (percentage since last call) - >>> p.cpu_percent(interval=None) - 2.9 - >>> - """ - blocking = interval is not None and interval > 0.0 - num_cpus = cpu_count() - if _POSIX: - def timer(): - return _timer() * num_cpus - else: - def timer(): - return sum(cpu_times()) - if blocking: - st1 = timer() - pt1 = self._proc.cpu_times() - time.sleep(interval) - st2 = timer() - pt2 = self._proc.cpu_times() - else: - st1 = self._last_sys_cpu_times - pt1 = self._last_proc_cpu_times - st2 = timer() - pt2 = self._proc.cpu_times() - if st1 is None or pt1 is None: - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - return 0.0 - - delta_proc = (pt2.user - pt1.user) + (pt2.system - pt1.system) - delta_time = st2 - st1 - # reset values for next call in case of interval == None - self._last_sys_cpu_times = st2 - self._last_proc_cpu_times = pt2 - - try: - # The utilization split between all CPUs. - # Note: a percentage > 100 is legitimate as it can result - # from a process with multiple threads running on different - # CPU cores, see: - # http://stackoverflow.com/questions/1032357 - # https://github.com/giampaolo/psutil/issues/474 - overall_percent = ((delta_proc / delta_time) * 100) * num_cpus - except ZeroDivisionError: - # interval was too low - return 0.0 - else: - return round(overall_percent, 1) - - def cpu_times(self): - """Return a (user, system) namedtuple representing the - accumulated process time, in seconds. - This is the same as os.times() but per-process. - """ - return self._proc.cpu_times() - - def memory_info(self): - """Return a tuple representing RSS (Resident Set Size) and VMS - (Virtual Memory Size) in bytes. - - On UNIX RSS and VMS are the same values shown by 'ps'. - - On Windows RSS and VMS refer to "Mem Usage" and "VM Size" - columns of taskmgr.exe. - """ - return self._proc.memory_info() - - def memory_info_ex(self): - """Return a namedtuple with variable fields depending on the - platform representing extended memory information about - this process. All numbers are expressed in bytes. - """ - return self._proc.memory_info_ex() - - def memory_percent(self): - """Compare physical system memory to process resident memory - (RSS) and calculate process memory utilization as a percentage. - """ - rss = self._proc.memory_info()[0] - # use cached value if available - total_phymem = _TOTAL_PHYMEM or virtual_memory().total - try: - return (rss / float(total_phymem)) * 100 - except ZeroDivisionError: - return 0.0 - - def memory_maps(self, grouped=True): - """Return process' mapped memory regions as a list of namedtuples - whose fields are variable depending on the platform. - - If 'grouped' is True the mapped regions with the same 'path' - are grouped together and the different memory fields are summed. - - If 'grouped' is False every mapped region is shown as a single - entity and the namedtuple will also include the mapped region's - address space ('addr') and permission set ('perms'). - """ - it = self._proc.memory_maps() - if grouped: - d = {} - for tupl in it: - path = tupl[2] - nums = tupl[3:] - try: - d[path] = map(lambda x, y: x + y, d[path], nums) - except KeyError: - d[path] = nums - nt = _psplatform.pmmap_grouped - return [nt(path, *d[path]) for path in d] # NOQA - else: - nt = _psplatform.pmmap_ext - return [nt(*x) for x in it] - - def open_files(self): - """Return files opened by process as a list of - (path, fd) namedtuples including the absolute file name - and file descriptor number. - """ - return self._proc.open_files() - - def connections(self, kind='inet'): - """Return connections opened by process as a list of - (fd, family, type, laddr, raddr, status) namedtuples. - The 'kind' parameter filters for connections that match the - following criteria: - - Kind Value Connections using - inet IPv4 and IPv6 - inet4 IPv4 - inet6 IPv6 - tcp TCP - tcp4 TCP over IPv4 - tcp6 TCP over IPv6 - udp UDP - udp4 UDP over IPv4 - udp6 UDP over IPv6 - unix UNIX socket (both UDP and TCP protocols) - all the sum of all the possible families and protocols - """ - return self._proc.connections(kind) - - if _POSIX: - def _send_signal(self, sig): - if self.pid == 0: - # see "man 2 kill" - raise ValueError( - "preventing sending signal to process with PID 0 as it " - "would affect every process in the process group of the " - "calling process (os.getpid()) instead of PID 0") - try: - os.kill(self.pid, sig) - except OSError as err: - if err.errno == errno.ESRCH: - self._gone = True - raise NoSuchProcess(self.pid, self._name) - if err.errno == errno.EPERM: - raise AccessDenied(self.pid, self._name) - raise - - @_assert_pid_not_reused - def send_signal(self, sig): - """Send a signal to process pre-emptively checking whether - PID has been reused (see signal module constants) . - On Windows only SIGTERM is valid and is treated as an alias - for kill(). - """ - if _POSIX: - self._send_signal(sig) - else: - if sig == signal.SIGTERM: - self._proc.kill() - else: - raise ValueError("only SIGTERM is supported on Windows") - - @_assert_pid_not_reused - def suspend(self): - """Suspend process execution with SIGSTOP pre-emptively checking - whether PID has been reused. - On Windows this has the effect ot suspending all process threads. - """ - if _POSIX: - self._send_signal(signal.SIGSTOP) - else: - self._proc.suspend() - - @_assert_pid_not_reused - def resume(self): - """Resume process execution with SIGCONT pre-emptively checking - whether PID has been reused. - On Windows this has the effect of resuming all process threads. - """ - if _POSIX: - self._send_signal(signal.SIGCONT) - else: - self._proc.resume() - - @_assert_pid_not_reused - def terminate(self): - """Terminate the process with SIGTERM pre-emptively checking - whether PID has been reused. - On Windows this is an alias for kill(). - """ - if _POSIX: - self._send_signal(signal.SIGTERM) - else: - self._proc.kill() - - @_assert_pid_not_reused - def kill(self): - """Kill the current process with SIGKILL pre-emptively checking - whether PID has been reused. - """ - if _POSIX: - self._send_signal(signal.SIGKILL) - else: - self._proc.kill() - - def wait(self, timeout=None): - """Wait for process to terminate and, if process is a children - of os.getpid(), also return its exit code, else None. - - If the process is already terminated immediately return None - instead of raising NoSuchProcess. - - If timeout (in seconds) is specified and process is still alive - raise TimeoutExpired. - - To wait for multiple Process(es) use psutil.wait_procs(). - """ - if timeout is not None and not timeout >= 0: - raise ValueError("timeout must be a positive integer") - return self._proc.wait(timeout) - - -# ===================================================================== -# --- Popen class -# ===================================================================== - - -class Popen(Process): - """A more convenient interface to stdlib subprocess module. - It starts a sub process and deals with it exactly as when using - subprocess.Popen class but in addition also provides all the - properties and methods of psutil.Process class as a unified - interface: - - >>> import psutil - >>> from subprocess import PIPE - >>> p = psutil.Popen(["python", "-c", "print 'hi'"], stdout=PIPE) - >>> p.name() - 'python' - >>> p.uids() - user(real=1000, effective=1000, saved=1000) - >>> p.username() - 'giampaolo' - >>> p.communicate() - ('hi\n', None) - >>> p.terminate() - >>> p.wait(timeout=2) - 0 - >>> - - For method names common to both classes such as kill(), terminate() - and wait(), psutil.Process implementation takes precedence. - - Unlike subprocess.Popen this class pre-emptively checks wheter PID - has been reused on send_signal(), terminate() and kill() so that - you don't accidentally terminate another process, fixing - http://bugs.python.org/issue6973. - - For a complete documentation refer to: - http://docs.python.org/library/subprocess.html - """ - - def __init__(self, *args, **kwargs): - # Explicitly avoid to raise NoSuchProcess in case the process - # spawned by subprocess.Popen terminates too quickly, see: - # https://github.com/giampaolo/psutil/issues/193 - self.__subproc = subprocess.Popen(*args, **kwargs) - self._init(self.__subproc.pid, _ignore_nsp=True) - - def __dir__(self): - return sorted(set(dir(Popen) + dir(subprocess.Popen))) - - def __getattribute__(self, name): - try: - return object.__getattribute__(self, name) - except AttributeError: - try: - return object.__getattribute__(self.__subproc, name) - except AttributeError: - raise AttributeError("%s instance has no attribute '%s'" - % (self.__class__.__name__, name)) - - def wait(self, timeout=None): - if self.__subproc.returncode is not None: - return self.__subproc.returncode - ret = super(Popen, self).wait(timeout) - self.__subproc.returncode = ret - return ret - - -# ===================================================================== -# --- system processes related functions -# ===================================================================== - - -def pids(): - """Return a list of current running PIDs.""" - return _psplatform.pids() - - -def pid_exists(pid): - """Return True if given PID exists in the current process list. - This is faster than doing "pid in psutil.pids()" and - should be preferred. - """ - if pid < 0: - return False - elif pid == 0 and _POSIX: - # On POSIX we use os.kill() to determine PID existence. - # According to "man 2 kill" PID 0 has a special meaning - # though: it refers to <<every process in the process - # group of the calling process>> and that is not we want - # to do here. - return pid in pids() - else: - return _psplatform.pid_exists(pid) - - -_pmap = {} - - -def process_iter(): - """Return a generator yielding a Process instance for all - running processes. - - Every new Process instance is only created once and then cached - into an internal table which is updated every time this is used. - - Cached Process instances are checked for identity so that you're - safe in case a PID has been reused by another process, in which - case the cached instance is updated. - - The sorting order in which processes are yielded is based on - their PIDs. - """ - def add(pid): - proc = Process(pid) - _pmap[proc.pid] = proc - return proc - - def remove(pid): - _pmap.pop(pid, None) - - a = set(pids()) - b = set(_pmap.keys()) - new_pids = a - b - gone_pids = b - a - - for pid in gone_pids: - remove(pid) - for pid, proc in sorted(list(_pmap.items()) + - list(dict.fromkeys(new_pids).items())): - try: - if proc is None: # new process - yield add(pid) - else: - # use is_running() to check whether PID has been reused by - # another process in which case yield a new Process instance - if proc.is_running(): - yield proc - else: - yield add(pid) - except NoSuchProcess: - remove(pid) - except AccessDenied: - # Process creation time can't be determined hence there's - # no way to tell whether the pid of the cached process - # has been reused. Just return the cached version. - yield proc - - -def wait_procs(procs, timeout=None, callback=None): - """Convenience function which waits for a list of processes to - terminate. - - Return a (gone, alive) tuple indicating which processes - are gone and which ones are still alive. - - The gone ones will have a new 'returncode' attribute indicating - process exit status (may be None). - - 'callback' is a function which gets called every time a process - terminates (a Process instance is passed as callback argument). - - Function will return as soon as all processes terminate or when - timeout occurs. - - Typical use case is: - - - send SIGTERM to a list of processes - - give them some time to terminate - - send SIGKILL to those ones which are still alive - - Example: - - >>> def on_terminate(proc): - ... print("process {} terminated".format(proc)) - ... - >>> for p in procs: - ... p.terminate() - ... - >>> gone, alive = wait_procs(procs, timeout=3, callback=on_terminate) - >>> for p in alive: - ... p.kill() - """ - def check_gone(proc, timeout): - try: - returncode = proc.wait(timeout=timeout) - except TimeoutExpired: - pass - else: - if returncode is not None or not proc.is_running(): - proc.returncode = returncode - gone.add(proc) - if callback is not None: - callback(proc) - - if timeout is not None and not timeout >= 0: - msg = "timeout must be a positive integer, got %s" % timeout - raise ValueError(msg) - gone = set() - alive = set(procs) - if callback is not None and not callable(callback): - raise TypeError("callback %r is not a callable" % callable) - if timeout is not None: - deadline = _timer() + timeout - - while alive: - if timeout is not None and timeout <= 0: - break - for proc in alive: - # Make sure that every complete iteration (all processes) - # will last max 1 sec. - # We do this because we don't want to wait too long on a - # single process: in case it terminates too late other - # processes may disappear in the meantime and their PID - # reused. - max_timeout = 1.0 / len(alive) - if timeout is not None: - timeout = min((deadline - _timer()), max_timeout) - if timeout <= 0: - break - check_gone(proc, timeout) - else: - check_gone(proc, max_timeout) - alive = alive - gone - - if alive: - # Last attempt over processes survived so far. - # timeout == 0 won't make this function wait any further. - for proc in alive: - check_gone(proc, 0) - alive = alive - gone - - return (list(gone), list(alive)) - - -# ===================================================================== -# --- CPU related functions -# ===================================================================== - - -@memoize -def cpu_count(logical=True): - """Return the number of logical CPUs in the system (same as - os.cpu_count() in Python 3.4). - - If logical is False return the number of physical cores only - (e.g. hyper thread CPUs are excluded). - - Return None if undetermined. - - The return value is cached after first call. - If desired cache can be cleared like this: - - >>> psutil.cpu_count.cache_clear() - """ - if logical: - return _psplatform.cpu_count_logical() - else: - return _psplatform.cpu_count_physical() - - -def cpu_times(percpu=False): - """Return system-wide CPU times as a namedtuple. - Every CPU time represents the seconds the CPU has spent in the given mode. - The namedtuple's fields availability varies depending on the platform: - - user - - system - - idle - - nice (UNIX) - - iowait (Linux) - - irq (Linux, FreeBSD) - - softirq (Linux) - - steal (Linux >= 2.6.11) - - guest (Linux >= 2.6.24) - - guest_nice (Linux >= 3.2.0) - - When percpu is True return a list of namedtuples for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - """ - if not percpu: - return _psplatform.cpu_times() - else: - return _psplatform.per_cpu_times() - - -_last_cpu_times = cpu_times() -_last_per_cpu_times = cpu_times(percpu=True) - - -def cpu_percent(interval=None, percpu=False): - """Return a float representing the current system-wide CPU - utilization as a percentage. - - When interval is > 0.0 compares system CPU times elapsed before - and after the interval (blocking). - - When interval is 0.0 or None compares system CPU times elapsed - since last call or module import, returning immediately (non - blocking). That means the first time this is called it will - return a meaningless 0.0 value which you should ignore. - In this case is recommended for accuracy that this function be - called with at least 0.1 seconds between calls. - - When percpu is True returns a list of floats representing the - utilization as a percentage for each CPU. - First element of the list refers to first CPU, second element - to second CPU and so on. - The order of the list is consistent across calls. - - Examples: - - >>> # blocking, system-wide - >>> psutil.cpu_percent(interval=1) - 2.0 - >>> - >>> # blocking, per-cpu - >>> psutil.cpu_percent(interval=1, percpu=True) - [2.0, 1.0] - >>> - >>> # non-blocking (percentage since last call) - >>> psutil.cpu_percent(interval=None) - 2.9 - >>> - """ - global _last_cpu_times - global _last_per_cpu_times - blocking = interval is not None and interval > 0.0 - - def calculate(t1, t2): - t1_all = sum(t1) - t1_busy = t1_all - t1.idle - - t2_all = sum(t2) - t2_busy = t2_all - t2.idle - - # this usually indicates a float precision issue - if t2_busy <= t1_busy: - return 0.0 - - busy_delta = t2_busy - t1_busy - all_delta = t2_all - t1_all - busy_perc = (busy_delta / all_delta) * 100 - return round(busy_perc, 1) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times - _last_cpu_times = cpu_times() - return calculate(t1, _last_cpu_times) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times - _last_per_cpu_times = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times): - ret.append(calculate(t1, t2)) - return ret - - -# Use separate global vars for cpu_times_percent() so that it's -# independent from cpu_percent() and they can both be used within -# the same program. -_last_cpu_times_2 = _last_cpu_times -_last_per_cpu_times_2 = _last_per_cpu_times - - -def cpu_times_percent(interval=None, percpu=False): - """Same as cpu_percent() but provides utilization percentages - for each specific CPU time as is returned by cpu_times(). - For instance, on Linux we'll get: - - >>> cpu_times_percent() - cpupercent(user=4.8, nice=0.0, system=4.8, idle=90.5, iowait=0.0, - irq=0.0, softirq=0.0, steal=0.0, guest=0.0, guest_nice=0.0) - >>> - - interval and percpu arguments have the same meaning as in - cpu_percent(). - """ - global _last_cpu_times_2 - global _last_per_cpu_times_2 - blocking = interval is not None and interval > 0.0 - - def calculate(t1, t2): - nums = [] - all_delta = sum(t2) - sum(t1) - for field in t1._fields: - field_delta = getattr(t2, field) - getattr(t1, field) - try: - field_perc = (100 * field_delta) / all_delta - except ZeroDivisionError: - field_perc = 0.0 - field_perc = round(field_perc, 1) - # CPU times are always supposed to increase over time - # or at least remain the same and that's because time - # cannot go backwards. - # Surprisingly sometimes this might not be the case (at - # least on Windows and Linux), see: - # https://github.com/giampaolo/psutil/issues/392 - # https://github.com/giampaolo/psutil/issues/645 - # I really don't know what to do about that except - # forcing the value to 0 or 100. - if field_perc > 100.0: - field_perc = 100.0 - # `<=` because `-0.0 == 0.0` evaluates to True - elif field_perc <= 0.0: - field_perc = 0.0 - nums.append(field_perc) - return _psplatform.scputimes(*nums) - - # system-wide usage - if not percpu: - if blocking: - t1 = cpu_times() - time.sleep(interval) - else: - t1 = _last_cpu_times_2 - _last_cpu_times_2 = cpu_times() - return calculate(t1, _last_cpu_times_2) - # per-cpu usage - else: - ret = [] - if blocking: - tot1 = cpu_times(percpu=True) - time.sleep(interval) - else: - tot1 = _last_per_cpu_times_2 - _last_per_cpu_times_2 = cpu_times(percpu=True) - for t1, t2 in zip(tot1, _last_per_cpu_times_2): - ret.append(calculate(t1, t2)) - return ret - - -# ===================================================================== -# --- system memory related functions -# ===================================================================== - - -def virtual_memory(): - """Return statistics about system memory usage as a namedtuple - including the following fields, expressed in bytes: - - - total: - total physical memory available. - - - available: - the actual amount of available memory that can be given - instantly to processes that request more memory in bytes; this - is calculated by summing different memory values depending on - the platform (e.g. free + buffers + cached on Linux) and it is - supposed to be used to monitor actual memory usage in a cross - platform fashion. - - - percent: - the percentage usage calculated as (total - available) / total * 100 - - - used: - memory used, calculated differently depending on the platform and - designed for informational purposes only: - OSX: active + inactive + wired - BSD: active + wired + cached - LINUX: total - free - - - free: - memory not being used at all (zeroed) that is readily available; - note that this doesn't reflect the actual memory available - (use 'available' instead) - - Platform-specific fields: - - - active (UNIX): - memory currently in use or very recently used, and so it is in RAM. - - - inactive (UNIX): - memory that is marked as not used. - - - buffers (BSD, Linux): - cache for things like file system metadata. - - - cached (BSD, OSX): - cache for various things. - - - wired (OSX, BSD): - memory that is marked to always stay in RAM. It is never moved to disk. - - - shared (BSD): - memory that may be simultaneously accessed by multiple processes. - - The sum of 'used' and 'available' does not necessarily equal total. - On Windows 'available' and 'free' are the same. - """ - global _TOTAL_PHYMEM - ret = _psplatform.virtual_memory() - # cached for later use in Process.memory_percent() - _TOTAL_PHYMEM = ret.total - return ret - - -def swap_memory(): - """Return system swap memory statistics as a namedtuple including - the following fields: - - - total: total swap memory in bytes - - used: used swap memory in bytes - - free: free swap memory in bytes - - percent: the percentage usage - - sin: no. of bytes the system has swapped in from disk (cumulative) - - sout: no. of bytes the system has swapped out from disk (cumulative) - - 'sin' and 'sout' on Windows are meaningless and always set to 0. - """ - return _psplatform.swap_memory() - - -# ===================================================================== -# --- disks/paritions related functions -# ===================================================================== - - -def disk_usage(path): - """Return disk usage statistics about the given path as a namedtuple - including total, used and free space expressed in bytes plus the - percentage usage. - """ - return _psplatform.disk_usage(path) - - -def disk_partitions(all=False): - """Return mounted partitions as a list of - (device, mountpoint, fstype, opts) namedtuple. - 'opts' field is a raw string separated by commas indicating mount - options which may vary depending on the platform. - - If "all" parameter is False return physical devices only and ignore - all others. - """ - return _psplatform.disk_partitions(all) - - -def disk_io_counters(perdisk=False): - """Return system disk I/O statistics as a namedtuple including - the following fields: - - - read_count: number of reads - - write_count: number of writes - - read_bytes: number of bytes read - - write_bytes: number of bytes written - - read_time: time spent reading from disk (in milliseconds) - - write_time: time spent writing to disk (in milliseconds) - - If perdisk is True return the same information for every - physical disk installed on the system as a dictionary - with partition names as the keys and the namedtuple - described above as the values. - - On recent Windows versions 'diskperf -y' command may need to be - executed first otherwise this function won't find any disk. - """ - rawdict = _psplatform.disk_io_counters() - if not rawdict: - raise RuntimeError("couldn't find any physical disk") - if perdisk: - for disk, fields in rawdict.items(): - rawdict[disk] = _common.sdiskio(*fields) - return rawdict - else: - return _common.sdiskio(*[sum(x) for x in zip(*rawdict.values())]) - - -# ===================================================================== -# --- network related functions -# ===================================================================== - - -def net_io_counters(pernic=False): - """Return network I/O statistics as a namedtuple including - the following fields: - - - bytes_sent: number of bytes sent - - bytes_recv: number of bytes received - - packets_sent: number of packets sent - - packets_recv: number of packets received - - errin: total number of errors while receiving - - errout: total number of errors while sending - - dropin: total number of incoming packets which were dropped - - dropout: total number of outgoing packets which were dropped - (always 0 on OSX and BSD) - - If pernic is True return the same information for every - network interface installed on the system as a dictionary - with network interface names as the keys and the namedtuple - described above as the values. - """ - rawdict = _psplatform.net_io_counters() - if not rawdict: - raise RuntimeError("couldn't find any network interface") - if pernic: - for nic, fields in rawdict.items(): - rawdict[nic] = _common.snetio(*fields) - return rawdict - else: - return _common.snetio(*[sum(x) for x in zip(*rawdict.values())]) - - -def net_connections(kind='inet'): - """Return system-wide connections as a list of - (fd, family, type, laddr, raddr, status, pid) namedtuples. - In case of limited privileges 'fd' and 'pid' may be set to -1 - and None respectively. - The 'kind' parameter filters for connections that fit the - following criteria: - - Kind Value Connections using - inet IPv4 and IPv6 - inet4 IPv4 - inet6 IPv6 - tcp TCP - tcp4 TCP over IPv4 - tcp6 TCP over IPv6 - udp UDP - udp4 UDP over IPv4 - udp6 UDP over IPv6 - unix UNIX socket (both UDP and TCP protocols) - all the sum of all the possible families and protocols - - On OSX this function requires root privileges. - """ - return _psplatform.net_connections(kind) - - -def net_if_addrs(): - """Return the addresses associated to each NIC (network interface - card) installed on the system as a dictionary whose keys are the - NIC names and value is a list of namedtuples for each address - assigned to the NIC. Each namedtuple includes 4 fields: - - - family - - address - - netmask - - broadcast - - 'family' can be either socket.AF_INET, socket.AF_INET6 or - psutil.AF_LINK, which refers to a MAC address. - 'address' is the primary address, 'netmask' and 'broadcast' - may be None. - Note: you can have more than one address of the same family - associated with each interface. - """ - has_enums = sys.version_info >= (3, 4) - if has_enums: - import socket - rawlist = _psplatform.net_if_addrs() - rawlist.sort(key=lambda x: x[1]) # sort by family - ret = collections.defaultdict(list) - for name, fam, addr, mask, broadcast in rawlist: - if has_enums: - try: - fam = socket.AddressFamily(fam) - except ValueError: - if os.name == 'nt' and fam == -1: - fam = _psplatform.AF_LINK - elif (hasattr(_psplatform, "AF_LINK") and - _psplatform.AF_LINK == fam): - # Linux defines AF_LINK as an alias for AF_PACKET. - # We re-set the family here so that repr(family) - # will show AF_LINK rather than AF_PACKET - fam = _psplatform.AF_LINK - ret[name].append(_common.snic(fam, addr, mask, broadcast)) - return dict(ret) - - -def net_if_stats(): - """Return information about each NIC (network interface card) - installed on the system as a dictionary whose keys are the - NIC names and value is a namedtuple with the following fields: - - - isup: whether the interface is up (bool) - - duplex: can be either NIC_DUPLEX_FULL, NIC_DUPLEX_HALF or - NIC_DUPLEX_UNKNOWN - - speed: the NIC speed expressed in mega bits (MB); if it can't - be determined (e.g. 'localhost') it will be set to 0. - - mtu: the maximum transmission unit expressed in bytes. - """ - return _psplatform.net_if_stats() - - -# ===================================================================== -# --- other system related functions -# ===================================================================== - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - # Note: we are not caching this because it is subject to - # system clock updates. - return _psplatform.boot_time() - - -def users(): - """Return users currently connected on the system as a list of - namedtuples including the following fields. - - - user: the name of the user - - terminal: the tty or pseudo-tty associated with the user, if any. - - host: the host name associated with the entry, if any. - - started: the creation time as a floating point number expressed in - seconds since the epoch. - """ - return _psplatform.users() - - -def test(): - """List info of all currently running processes emulating ps aux - output. - """ - import datetime - - today_day = datetime.date.today() - templ = "%-10s %5s %4s %4s %7s %7s %-13s %5s %7s %s" - attrs = ['pid', 'cpu_percent', 'memory_percent', 'name', 'cpu_times', - 'create_time', 'memory_info'] - if _POSIX: - attrs.append('uids') - attrs.append('terminal') - print(templ % ("USER", "PID", "%CPU", "%MEM", "VSZ", "RSS", "TTY", - "START", "TIME", "COMMAND")) - for p in process_iter(): - try: - pinfo = p.as_dict(attrs, ad_value='') - except NoSuchProcess: - pass - else: - if pinfo['create_time']: - ctime = datetime.datetime.fromtimestamp(pinfo['create_time']) - if ctime.date() == today_day: - ctime = ctime.strftime("%H:%M") - else: - ctime = ctime.strftime("%b%d") - else: - ctime = '' - cputime = time.strftime("%M:%S", - time.localtime(sum(pinfo['cpu_times']))) - try: - user = p.username() - except Error: - user = '' - if _WINDOWS and '\\' in user: - user = user.split('\\')[1] - vms = pinfo['memory_info'] and \ - int(pinfo['memory_info'].vms / 1024) or '?' - rss = pinfo['memory_info'] and \ - int(pinfo['memory_info'].rss / 1024) or '?' - memp = pinfo['memory_percent'] and \ - round(pinfo['memory_percent'], 1) or '?' - print(templ % ( - user[:10], - pinfo['pid'], - pinfo['cpu_percent'], - memp, - vms, - rss, - pinfo.get('terminal', '') or '?', - ctime, - cputime, - pinfo['name'].strip() or '?')) - - -del memoize, division -if sys.version_info < (3, 0): - del num - -if __name__ == "__main__": - test() diff --git a/python/psutil/psutil/_common.py b/python/psutil/psutil/_common.py deleted file mode 100644 index e9acf595d..000000000 --- a/python/psutil/psutil/_common.py +++ /dev/null @@ -1,246 +0,0 @@ -# /usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Common objects shared by all _ps* modules.""" - -from __future__ import division -import errno -import functools -import os -import socket -import stat -import sys -from collections import namedtuple -from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM -try: - import threading -except ImportError: - import dummy_threading as threading - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -# --- constants - -AF_INET6 = getattr(socket, 'AF_INET6', None) -AF_UNIX = getattr(socket, 'AF_UNIX', None) - -STATUS_RUNNING = "running" -STATUS_SLEEPING = "sleeping" -STATUS_DISK_SLEEP = "disk-sleep" -STATUS_STOPPED = "stopped" -STATUS_TRACING_STOP = "tracing-stop" -STATUS_ZOMBIE = "zombie" -STATUS_DEAD = "dead" -STATUS_WAKE_KILL = "wake-kill" -STATUS_WAKING = "waking" -STATUS_IDLE = "idle" # BSD -STATUS_LOCKED = "locked" # BSD -STATUS_WAITING = "waiting" # BSD - -CONN_ESTABLISHED = "ESTABLISHED" -CONN_SYN_SENT = "SYN_SENT" -CONN_SYN_RECV = "SYN_RECV" -CONN_FIN_WAIT1 = "FIN_WAIT1" -CONN_FIN_WAIT2 = "FIN_WAIT2" -CONN_TIME_WAIT = "TIME_WAIT" -CONN_CLOSE = "CLOSE" -CONN_CLOSE_WAIT = "CLOSE_WAIT" -CONN_LAST_ACK = "LAST_ACK" -CONN_LISTEN = "LISTEN" -CONN_CLOSING = "CLOSING" -CONN_NONE = "NONE" - -if enum is None: - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 -else: - class NicDuplex(enum.IntEnum): - NIC_DUPLEX_FULL = 2 - NIC_DUPLEX_HALF = 1 - NIC_DUPLEX_UNKNOWN = 0 - - globals().update(NicDuplex.__members__) - - -# --- functions - -def usage_percent(used, total, _round=None): - """Calculate percentage usage of 'used' against 'total'.""" - try: - ret = (used / total) * 100 - except ZeroDivisionError: - ret = 0 - if _round is not None: - return round(ret, _round) - else: - return ret - - -def memoize(fun): - """A simple memoize decorator for functions supporting (hashable) - positional arguments. - It also provides a cache_clear() function for clearing the cache: - - >>> @memoize - ... def foo() - ... return 1 - ... - >>> foo() - 1 - >>> foo.cache_clear() - >>> - """ - @functools.wraps(fun) - def wrapper(*args, **kwargs): - key = (args, frozenset(sorted(kwargs.items()))) - lock.acquire() - try: - try: - return cache[key] - except KeyError: - ret = cache[key] = fun(*args, **kwargs) - finally: - lock.release() - return ret - - def cache_clear(): - """Clear cache.""" - lock.acquire() - try: - cache.clear() - finally: - lock.release() - - lock = threading.RLock() - cache = {} - wrapper.cache_clear = cache_clear - return wrapper - - -def isfile_strict(path): - """Same as os.path.isfile() but does not swallow EACCES / EPERM - exceptions, see: - http://mail.python.org/pipermail/python-dev/2012-June/120787.html - """ - try: - st = os.stat(path) - except OSError as err: - if err.errno in (errno.EPERM, errno.EACCES): - raise - return False - else: - return stat.S_ISREG(st.st_mode) - - -def sockfam_to_enum(num): - """Convert a numeric socket family value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - try: - return socket.AddressFamily(num) - except (ValueError, AttributeError): - return num - - -def socktype_to_enum(num): - """Convert a numeric socket type value to an IntEnum member. - If it's not a known member, return the numeric value itself. - """ - if enum is None: - return num - try: - return socket.AddressType(num) - except (ValueError, AttributeError): - return num - - -# --- Process.connections() 'kind' parameter mapping - -conn_tmap = { - "all": ([AF_INET, AF_INET6, AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - "tcp": ([AF_INET, AF_INET6], [SOCK_STREAM]), - "tcp4": ([AF_INET], [SOCK_STREAM]), - "udp": ([AF_INET, AF_INET6], [SOCK_DGRAM]), - "udp4": ([AF_INET], [SOCK_DGRAM]), - "inet": ([AF_INET, AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), - "inet4": ([AF_INET], [SOCK_STREAM, SOCK_DGRAM]), - "inet6": ([AF_INET6], [SOCK_STREAM, SOCK_DGRAM]), -} - -if AF_INET6 is not None: - conn_tmap.update({ - "tcp6": ([AF_INET6], [SOCK_STREAM]), - "udp6": ([AF_INET6], [SOCK_DGRAM]), - }) - -if AF_UNIX is not None: - conn_tmap.update({ - "unix": ([AF_UNIX], [SOCK_STREAM, SOCK_DGRAM]), - }) - -del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM - - -# --- namedtuples for psutil.* system-related functions - -# psutil.swap_memory() -sswap = namedtuple('sswap', ['total', 'used', 'free', 'percent', 'sin', - 'sout']) -# psutil.disk_usage() -sdiskusage = namedtuple('sdiskusage', ['total', 'used', 'free', 'percent']) -# psutil.disk_io_counters() -sdiskio = namedtuple('sdiskio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes', - 'read_time', 'write_time']) -# psutil.disk_partitions() -sdiskpart = namedtuple('sdiskpart', ['device', 'mountpoint', 'fstype', 'opts']) -# psutil.net_io_counters() -snetio = namedtuple('snetio', ['bytes_sent', 'bytes_recv', - 'packets_sent', 'packets_recv', - 'errin', 'errout', - 'dropin', 'dropout']) -# psutil.users() -suser = namedtuple('suser', ['name', 'terminal', 'host', 'started']) -# psutil.net_connections() -sconn = namedtuple('sconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status', 'pid']) -# psutil.net_if_addrs() -snic = namedtuple('snic', ['family', 'address', 'netmask', 'broadcast']) -# psutil.net_if_stats() -snicstats = namedtuple('snicstats', ['isup', 'duplex', 'speed', 'mtu']) - - -# --- namedtuples for psutil.Process methods - -# psutil.Process.memory_info() -pmem = namedtuple('pmem', ['rss', 'vms']) -# psutil.Process.cpu_times() -pcputimes = namedtuple('pcputimes', ['user', 'system']) -# psutil.Process.open_files() -popenfile = namedtuple('popenfile', ['path', 'fd']) -# psutil.Process.threads() -pthread = namedtuple('pthread', ['id', 'user_time', 'system_time']) -# psutil.Process.uids() -puids = namedtuple('puids', ['real', 'effective', 'saved']) -# psutil.Process.gids() -pgids = namedtuple('pgids', ['real', 'effective', 'saved']) -# psutil.Process.io_counters() -pio = namedtuple('pio', ['read_count', 'write_count', - 'read_bytes', 'write_bytes']) -# psutil.Process.ionice() -pionice = namedtuple('pionice', ['ioclass', 'value']) -# psutil.Process.ctx_switches() -pctxsw = namedtuple('pctxsw', ['voluntary', 'involuntary']) -# psutil.Process.connections() -pconn = namedtuple('pconn', ['fd', 'family', 'type', 'laddr', 'raddr', - 'status']) diff --git a/python/psutil/psutil/_compat.py b/python/psutil/psutil/_compat.py deleted file mode 100644 index 38744a84a..000000000 --- a/python/psutil/psutil/_compat.py +++ /dev/null @@ -1,189 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Module which provides compatibility with older Python versions.""" - -import collections -import functools -import sys - -__all__ = ["PY3", "long", "xrange", "unicode", "callable", "lru_cache"] - -PY3 = sys.version_info[0] == 3 - -if PY3: - long = int - xrange = range - unicode = str - - def u(s): - return s -else: - long = long - xrange = xrange - unicode = unicode - - def u(s): - return unicode(s, "unicode_escape") - - -# removed in 3.0, reintroduced in 3.2 -try: - callable = callable -except NameError: - def callable(obj): - return any("__call__" in klass.__dict__ for klass in type(obj).__mro__) - - -# --- stdlib additions - - -# py 3.2 functools.lru_cache -# Taken from: http://code.activestate.com/recipes/578078 -# Credit: Raymond Hettinger -try: - from functools import lru_cache -except ImportError: - try: - from threading import RLock - except ImportError: - from dummy_threading import RLock - - _CacheInfo = collections.namedtuple( - "CacheInfo", ["hits", "misses", "maxsize", "currsize"]) - - class _HashedSeq(list): - __slots__ = 'hashvalue' - - def __init__(self, tup, hash=hash): - self[:] = tup - self.hashvalue = hash(tup) - - def __hash__(self): - return self.hashvalue - - def _make_key(args, kwds, typed, - kwd_mark=(object(), ), - fasttypes=set((int, str, frozenset, type(None))), - sorted=sorted, tuple=tuple, type=type, len=len): - key = args - if kwds: - sorted_items = sorted(kwds.items()) - key += kwd_mark - for item in sorted_items: - key += item - if typed: - key += tuple(type(v) for v in args) - if kwds: - key += tuple(type(v) for k, v in sorted_items) - elif len(key) == 1 and type(key[0]) in fasttypes: - return key[0] - return _HashedSeq(key) - - def lru_cache(maxsize=100, typed=False): - """Least-recently-used cache decorator, see: - http://docs.python.org/3/library/functools.html#functools.lru_cache - """ - def decorating_function(user_function): - cache = dict() - stats = [0, 0] - HITS, MISSES = 0, 1 - make_key = _make_key - cache_get = cache.get - _len = len - lock = RLock() - root = [] - root[:] = [root, root, None, None] - nonlocal_root = [root] - PREV, NEXT, KEY, RESULT = 0, 1, 2, 3 - if maxsize == 0: - def wrapper(*args, **kwds): - result = user_function(*args, **kwds) - stats[MISSES] += 1 - return result - elif maxsize is None: - def wrapper(*args, **kwds): - key = make_key(args, kwds, typed) - result = cache_get(key, root) - if result is not root: - stats[HITS] += 1 - return result - result = user_function(*args, **kwds) - cache[key] = result - stats[MISSES] += 1 - return result - else: - def wrapper(*args, **kwds): - if kwds or typed: - key = make_key(args, kwds, typed) - else: - key = args - lock.acquire() - try: - link = cache_get(key) - if link is not None: - root, = nonlocal_root - link_prev, link_next, key, result = link - link_prev[NEXT] = link_next - link_next[PREV] = link_prev - last = root[PREV] - last[NEXT] = root[PREV] = link - link[PREV] = last - link[NEXT] = root - stats[HITS] += 1 - return result - finally: - lock.release() - result = user_function(*args, **kwds) - lock.acquire() - try: - root, = nonlocal_root - if key in cache: - pass - elif _len(cache) >= maxsize: - oldroot = root - oldroot[KEY] = key - oldroot[RESULT] = result - root = nonlocal_root[0] = oldroot[NEXT] - oldkey = root[KEY] - root[KEY] = root[RESULT] = None - del cache[oldkey] - cache[key] = oldroot - else: - last = root[PREV] - link = [last, root, key, result] - last[NEXT] = root[PREV] = cache[key] = link - stats[MISSES] += 1 - finally: - lock.release() - return result - - def cache_info(): - """Report cache statistics""" - lock.acquire() - try: - return _CacheInfo(stats[HITS], stats[MISSES], maxsize, - len(cache)) - finally: - lock.release() - - def cache_clear(): - """Clear the cache and cache statistics""" - lock.acquire() - try: - cache.clear() - root = nonlocal_root[0] - root[:] = [root, root, None, None] - stats[:] = [0, 0] - finally: - lock.release() - - wrapper.__wrapped__ = user_function - wrapper.cache_info = cache_info - wrapper.cache_clear = cache_clear - return functools.update_wrapper(wrapper, user_function) - - return decorating_function diff --git a/python/psutil/psutil/_psbsd.py b/python/psutil/psutil/_psbsd.py deleted file mode 100644 index db54a02e1..000000000 --- a/python/psutil/psutil/_psbsd.py +++ /dev/null @@ -1,455 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""FreeBSD platform implementation.""" - -import errno -import functools -import os -import xml.etree.ElementTree as ET -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_bsd as cext -from . import _psutil_posix as cext_posix -from ._common import conn_tmap, usage_percent, sockfam_to_enum -from ._common import socktype_to_enum - - -__extra__all__ = [] - -# --- constants - -PROC_STATUSES = { - cext.SSTOP: _common.STATUS_STOPPED, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SRUN: _common.STATUS_RUNNING, - cext.SIDL: _common.STATUS_IDLE, - cext.SWAIT: _common.STATUS_WAITING, - cext.SLOCK: _common.STATUS_LOCKED, - cext.SZOMB: _common.STATUS_ZOMBIE, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -# extend base mem ntuple with BSD-specific memory metrics -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached', 'shared', 'wired']) -scputimes = namedtuple( - 'scputimes', ['user', 'nice', 'system', 'idle', 'irq']) -pextmem = namedtuple('pextmem', ['rss', 'vms', 'text', 'data', 'stack']) -pmmap_grouped = namedtuple( - 'pmmap_grouped', 'path rss, private, ref_count, shadow_count') -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr, perms path rss, private, ref_count, shadow_count') - -# set later from __init__.py -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - total, free, active, inactive, wired, cached, buffers, shared = mem - avail = inactive + cached + free - used = active + wired + cached - percent = usage_percent((total - avail), total, _round=1) - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached, shared, wired) - - -def swap_memory(): - """System swap memory as (total, used, free, sin, sout) namedtuple.""" - total, used, free, sin, sout = [x * PAGESIZE for x in cext.swap_mem()] - percent = usage_percent(used, total, _round=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -def cpu_times(): - """Return system per-CPU times as a namedtuple""" - user, nice, system, idle, irq = cext.cpu_times() - return scputimes(user, nice, system, idle, irq) - - -if hasattr(cext, "per_cpu_times"): - def per_cpu_times(): - """Return system CPU times as a namedtuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle, irq = cpu_t - item = scputimes(user, nice, system, idle, irq) - ret.append(item) - return ret -else: - # XXX - # Ok, this is very dirty. - # On FreeBSD < 8 we cannot gather per-cpu information, see: - # https://github.com/giampaolo/psutil/issues/226 - # If num cpus > 1, on first call we return single cpu times to avoid a - # crash at psutil import time. - # Next calls will fail with NotImplementedError - def per_cpu_times(): - if cpu_count_logical() == 1: - return [cpu_times()] - if per_cpu_times.__called__: - raise NotImplementedError("supported only starting from FreeBSD 8") - per_cpu_times.__called__ = True - return [cpu_times()] - - per_cpu_times.__called__ = False - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - # From the C module we'll get an XML string similar to this: - # http://manpages.ubuntu.com/manpages/precise/man4/smp.4freebsd.html - # We may get None in case "sysctl kern.sched.topology_spec" - # is not supported on this BSD version, in which case we'll mimic - # os.cpu_count() and return None. - ret = None - s = cext.cpu_count_phys() - if s is not None: - # get rid of padding chars appended at the end of the string - index = s.rfind("</groups>") - if index != -1: - s = s[:index + 9] - root = ET.fromstring(s) - try: - ret = len(root.findall('group/children/group/cpu')) or None - finally: - # needed otherwise it will memleak - root.clear() - if not ret: - # If logical CPUs are 1 it's obvious we'll have only 1 - # physical CPU. - if cpu_count_logical() == 1: - return 1 - return ret - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def disk_partitions(all=False): - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if not os.path.isabs(device) or not os.path.exists(device): - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -def users(): - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp = item - if tty == '~': - continue # reboot or shutdown - nt = _common.suser(user, tty or None, hostname, tstamp) - retlist.append(nt) - return retlist - - -def net_connections(kind): - if kind not in _common.conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - ret = set() - rawlist = cext.net_connections() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - # TODO: apply filter at C level - if fam in families and type in types: - try: - status = TCP_STATUSES[status] - except KeyError: - # XXX: Not sure why this happens. I saw this occurring - # with IPv6 sockets opened by 'vim'. Those sockets - # have a very short lifetime so maybe the kernel - # can't initialize their status? - status = TCP_STATUSES[cext.PSUTIL_CONN_NONE] - fam = sockfam_to_enum(fam) - type = socktype_to_enum(type) - nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - isup, duplex, speed, mtu = cext_posix.net_if_stats(name) - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -pids = cext.pids -pid_exists = _psposix.pid_exists -disk_usage = _psposix.disk_usage -net_io_counters = cext.net_io_counters -disk_io_counters = cext.disk_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - # support for private module import - if (NoSuchProcess is None or AccessDenied is None or - ZombieProcess is None): - raise - if err.errno == errno.ESRCH: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - if err.errno in (errno.EPERM, errno.EACCES): - raise AccessDenied(self.pid, self._name) - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - def name(self): - return cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - return cext.proc_exe(self.pid) - - @wrap_exceptions - def cmdline(self): - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def terminal(self): - tty_nr = cext.proc_tty_nr(self.pid) - tmap = _psposix._get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def ppid(self): - return cext.proc_ppid(self.pid) - - @wrap_exceptions - def uids(self): - real, effective, saved = cext.proc_uids(self.pid) - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - real, effective, saved = cext.proc_gids(self.pid) - return _common.pgids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - user, system = cext.proc_cpu_times(self.pid) - return _common.pcputimes(user, system) - - @wrap_exceptions - def memory_info(self): - rss, vms = cext.proc_memory_info(self.pid)[:2] - return _common.pmem(rss, vms) - - @wrap_exceptions - def memory_info_ex(self): - return pextmem(*cext.proc_memory_info(self.pid)) - - @wrap_exceptions - def create_time(self): - return cext.proc_create_time(self.pid) - - @wrap_exceptions - def num_threads(self): - return cext.proc_num_threads(self.pid) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid)) - - @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) - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - fam = sockfam_to_enum(fam) - type = socktype_to_enum(type) - status = TCP_STATUSES[status] - nt = _common.pconn(fd, fam, type, laddr, raddr, status) - ret.append(nt) - return ret - - @wrap_exceptions - def wait(self, timeout=None): - try: - return _psposix.wait_pid(self.pid, timeout) - except _psposix.TimeoutExpired: - # support for private module import - if TimeoutExpired is None: - raise - raise TimeoutExpired(timeout, self.pid, self._name) - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = cext.proc_status(self.pid) - if code in PROC_STATUSES: - return PROC_STATUSES[code] - # XXX is this legit? will we even ever get here? - return "?" - - @wrap_exceptions - def io_counters(self): - rc, wc, rb, wb = cext.proc_io_counters(self.pid) - return _common.pio(rc, wc, rb, wb) - - nt_mmap_grouped = namedtuple( - 'mmap', 'path rss, private, ref_count, shadow_count') - nt_mmap_ext = namedtuple( - 'mmap', 'addr, perms path rss, private, ref_count, shadow_count') - - # FreeBSD < 8 does not support functions based on kinfo_getfile() - # and kinfo_getvmmap() - if hasattr(cext, 'proc_open_files'): - - @wrap_exceptions - def open_files(self): - """Return files opened by process as a list of namedtuples.""" - rawlist = cext.proc_open_files(self.pid) - return [_common.popenfile(path, fd) for path, fd in rawlist] - - @wrap_exceptions - def cwd(self): - """Return process current working directory.""" - # sometimes we get an empty string, in which case we turn - # it into None - return cext.proc_cwd(self.pid) or None - - @wrap_exceptions - def memory_maps(self): - return cext.proc_memory_maps(self.pid) - - @wrap_exceptions - def num_fds(self): - """Return the number of file descriptors opened by this process.""" - return cext.proc_num_fds(self.pid) - - else: - def _not_implemented(self): - raise NotImplementedError("supported only starting from FreeBSD 8") - - open_files = _not_implemented - proc_cwd = _not_implemented - memory_maps = _not_implemented - num_fds = _not_implemented - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - # Pre-emptively check if CPUs are valid because the C - # function has a weird behavior in case of invalid CPUs, - # see: https://github.com/giampaolo/psutil/issues/586 - allcpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in allcpus: - raise ValueError("invalid CPU #%i (choose between %s)" - % (cpu, allcpus)) - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except OSError as err: - # 'man cpuset_setaffinity' about EDEADLK: - # <<the call would leave a thread without a valid CPU to run - # on because the set does not overlap with the thread's - # anonymous mask>> - if err.errno in (errno.EINVAL, errno.EDEADLK): - for cpu in cpus: - if cpu not in allcpus: - raise ValueError("invalid CPU #%i (choose between %s)" - % (cpu, allcpus)) - raise diff --git a/python/psutil/psutil/_pslinux.py b/python/psutil/psutil/_pslinux.py deleted file mode 100644 index 7eb25f519..000000000 --- a/python/psutil/psutil/_pslinux.py +++ /dev/null @@ -1,1206 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Linux platform implementation.""" - -from __future__ import division - -import base64 -import errno -import functools -import os -import re -import socket -import struct -import sys -import warnings -from collections import namedtuple, defaultdict - -from . import _common -from . import _psposix -from . import _psutil_linux as cext -from . import _psutil_posix as cext_posix -from ._common import isfile_strict, usage_percent -from ._common import NIC_DUPLEX_FULL, NIC_DUPLEX_HALF, NIC_DUPLEX_UNKNOWN -from ._compat import PY3, long - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -__extra__all__ = [ - # io prio constants - "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE", - "IOPRIO_CLASS_IDLE", - # connection status constants - "CONN_ESTABLISHED", "CONN_SYN_SENT", "CONN_SYN_RECV", "CONN_FIN_WAIT1", - "CONN_FIN_WAIT2", "CONN_TIME_WAIT", "CONN_CLOSE", "CONN_CLOSE_WAIT", - "CONN_LAST_ACK", "CONN_LISTEN", "CONN_CLOSING", ] - -# --- constants - -HAS_PRLIMIT = hasattr(cext, "linux_prlimit") - -# RLIMIT_* constants, not guaranteed to be present on all kernels -if HAS_PRLIMIT: - for name in dir(cext): - if name.startswith('RLIM'): - __extra__all__.append(name) - -# Number of clock ticks per second -CLOCK_TICKS = os.sysconf("SC_CLK_TCK") -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -BOOT_TIME = None # set later -DEFAULT_ENCODING = sys.getdefaultencoding() -if enum is None: - AF_LINK = socket.AF_PACKET -else: - AddressFamily = enum.IntEnum('AddressFamily', - {'AF_LINK': socket.AF_PACKET}) - AF_LINK = AddressFamily.AF_LINK - -# ioprio_* constants http://linux.die.net/man/2/ioprio_get -if enum is None: - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 -else: - class IOPriority(enum.IntEnum): - IOPRIO_CLASS_NONE = 0 - IOPRIO_CLASS_RT = 1 - IOPRIO_CLASS_BE = 2 - IOPRIO_CLASS_IDLE = 3 - - globals().update(IOPriority.__members__) - -# taken from /fs/proc/array.c -PROC_STATUSES = { - "R": _common.STATUS_RUNNING, - "S": _common.STATUS_SLEEPING, - "D": _common.STATUS_DISK_SLEEP, - "T": _common.STATUS_STOPPED, - "t": _common.STATUS_TRACING_STOP, - "Z": _common.STATUS_ZOMBIE, - "X": _common.STATUS_DEAD, - "x": _common.STATUS_DEAD, - "K": _common.STATUS_WAKE_KILL, - "W": _common.STATUS_WAKING -} - -# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h -TCP_STATUSES = { - "01": _common.CONN_ESTABLISHED, - "02": _common.CONN_SYN_SENT, - "03": _common.CONN_SYN_RECV, - "04": _common.CONN_FIN_WAIT1, - "05": _common.CONN_FIN_WAIT2, - "06": _common.CONN_TIME_WAIT, - "07": _common.CONN_CLOSE, - "08": _common.CONN_CLOSE_WAIT, - "09": _common.CONN_LAST_ACK, - "0A": _common.CONN_LISTEN, - "0B": _common.CONN_CLOSING -} - -# set later from __init__.py -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# --- named tuples - -def _get_cputimes_fields(): - """Return a namedtuple of variable fields depending on the - CPU times available on this Linux kernel version which may be: - (user, nice, system, idle, iowait, irq, softirq, [steal, [guest, - [guest_nice]]]) - """ - with open('/proc/stat', 'rb') as f: - values = f.readline().split()[1:] - fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq'] - vlen = len(values) - if vlen >= 8: - # Linux >= 2.6.11 - fields.append('steal') - if vlen >= 9: - # Linux >= 2.6.24 - fields.append('guest') - if vlen >= 10: - # Linux >= 3.2.0 - fields.append('guest_nice') - return fields - - -scputimes = namedtuple('scputimes', _get_cputimes_fields()) - -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'buffers', 'cached']) - -pextmem = namedtuple('pextmem', 'rss vms shared text lib data dirty') - -pmmap_grouped = namedtuple( - 'pmmap_grouped', ['path', 'rss', 'size', 'pss', 'shared_clean', - 'shared_dirty', 'private_clean', 'private_dirty', - 'referenced', 'anonymous', 'swap']) - -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) - - -# --- system memory - -def virtual_memory(): - total, free, buffers, shared, _, _ = cext.linux_sysinfo() - cached = active = inactive = None - with open('/proc/meminfo', 'rb') as f: - for line in f: - if line.startswith(b"Cached:"): - cached = int(line.split()[1]) * 1024 - elif line.startswith(b"Active:"): - active = int(line.split()[1]) * 1024 - elif line.startswith(b"Inactive:"): - inactive = int(line.split()[1]) * 1024 - if (cached is not None and - active is not None and - inactive is not None): - break - else: - # we might get here when dealing with exotic Linux flavors, see: - # https://github.com/giampaolo/psutil/issues/313 - msg = "'cached', 'active' and 'inactive' memory stats couldn't " \ - "be determined and were set to 0" - warnings.warn(msg, RuntimeWarning) - cached = active = inactive = 0 - avail = free + buffers + cached - used = total - free - percent = usage_percent((total - avail), total, _round=1) - return svmem(total, avail, percent, used, free, - active, inactive, buffers, cached) - - -def swap_memory(): - _, _, _, _, total, free = cext.linux_sysinfo() - used = total - free - percent = usage_percent(used, total, _round=1) - # get pgin/pgouts - with open("/proc/vmstat", "rb") as f: - sin = sout = None - for line in f: - # values are expressed in 4 kilo bytes, we want bytes instead - if line.startswith(b'pswpin'): - sin = int(line.split(b' ')[1]) * 4 * 1024 - elif line.startswith(b'pswpout'): - sout = int(line.split(b' ')[1]) * 4 * 1024 - if sin is not None and sout is not None: - break - else: - # we might get here when dealing with exotic Linux flavors, see: - # https://github.com/giampaolo/psutil/issues/313 - msg = "'sin' and 'sout' swap memory stats couldn't " \ - "be determined and were set to 0" - warnings.warn(msg, RuntimeWarning) - sin = sout = 0 - return _common.sswap(total, used, free, percent, sin, sout) - - -# --- CPUs - -def cpu_times(): - """Return a named tuple representing the following system-wide - CPU times: - (user, nice, system, idle, iowait, irq, softirq [steal, [guest, - [guest_nice]]]) - Last 3 fields may not be available on all Linux kernel versions. - """ - with open('/proc/stat', 'rb') as f: - values = f.readline().split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - return scputimes(*fields) - - -def per_cpu_times(): - """Return a list of namedtuple representing the CPU times - for every CPU available on the system. - """ - cpus = [] - with open('/proc/stat', 'rb') as f: - # get rid of the first line which refers to system wide CPU stats - f.readline() - for line in f: - if line.startswith(b'cpu'): - values = line.split() - fields = values[1:len(scputimes._fields) + 1] - fields = [float(x) / CLOCK_TICKS for x in fields] - entry = scputimes(*fields) - cpus.append(entry) - return cpus - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # as a second fallback we try to parse /proc/cpuinfo - num = 0 - with open('/proc/cpuinfo', 'rb') as f: - for line in f: - if line.lower().startswith(b'processor'): - num += 1 - - # unknown format (e.g. amrel/sparc architectures), see: - # https://github.com/giampaolo/psutil/issues/200 - # try to parse /proc/stat as a last resort - if num == 0: - search = re.compile('cpu\d') - with open('/proc/stat', 'rt') as f: - for line in f: - line = line.split(' ')[0] - if search.match(line): - num += 1 - - if num == 0: - # mimic os.cpu_count() - return None - return num - - -def cpu_count_physical(): - """Return the number of physical cores in the system.""" - mapping = {} - current_info = {} - with open('/proc/cpuinfo', 'rb') as f: - for line in f: - line = line.strip().lower() - if not line: - # new section - if (b'physical id' in current_info and - b'cpu cores' in current_info): - mapping[current_info[b'physical id']] = \ - current_info[b'cpu cores'] - current_info = {} - else: - # ongoing section - if (line.startswith(b'physical id') or - line.startswith(b'cpu cores')): - key, value = line.split(b'\t:', 1) - current_info[key] = int(value) - - # mimic os.cpu_count() - return sum(mapping.values()) or None - - -# --- other system functions - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp, user_process = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname == ':0.0' or hostname == ':0': - hostname = 'localhost' - nt = _common.suser(user, tty or None, hostname, tstamp) - retlist.append(nt) - return retlist - - -def boot_time(): - """Return the system boot time expressed in seconds since the epoch.""" - global BOOT_TIME - with open('/proc/stat', 'rb') as f: - for line in f: - if line.startswith(b'btime'): - ret = float(line.strip().split()[1]) - BOOT_TIME = ret - return ret - raise RuntimeError("line 'btime' not found in /proc/stat") - - -# --- processes - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir(b'/proc') if x.isdigit()] - - -def pid_exists(pid): - """Check For the existence of a unix pid.""" - return _psposix.pid_exists(pid) - - -# --- network - -class Connections: - """A wrapper on top of /proc/net/* files, retrieving per-process - and system-wide open connections (TCP, UDP, UNIX) similarly to - "netstat -an". - - Note: in case of UNIX sockets we're only able to determine the - local endpoint/path, not the one it's connected to. - According to [1] it would be possible but not easily. - - [1] http://serverfault.com/a/417946 - """ - - def __init__(self): - tcp4 = ("tcp", socket.AF_INET, socket.SOCK_STREAM) - tcp6 = ("tcp6", socket.AF_INET6, socket.SOCK_STREAM) - udp4 = ("udp", socket.AF_INET, socket.SOCK_DGRAM) - udp6 = ("udp6", socket.AF_INET6, socket.SOCK_DGRAM) - unix = ("unix", socket.AF_UNIX, None) - self.tmap = { - "all": (tcp4, tcp6, udp4, udp6, unix), - "tcp": (tcp4, tcp6), - "tcp4": (tcp4,), - "tcp6": (tcp6,), - "udp": (udp4, udp6), - "udp4": (udp4,), - "udp6": (udp6,), - "unix": (unix,), - "inet": (tcp4, tcp6, udp4, udp6), - "inet4": (tcp4, udp4), - "inet6": (tcp6, udp6), - } - - def get_proc_inodes(self, pid): - inodes = defaultdict(list) - for fd in os.listdir("/proc/%s/fd" % pid): - try: - inode = os.readlink("/proc/%s/fd/%s" % (pid, fd)) - except OSError as err: - # ENOENT == file which is gone in the meantime; - # os.stat('/proc/%s' % self.pid) will be done later - # to force NSP (if it's the case) - if err.errno in (errno.ENOENT, errno.ESRCH): - continue - elif err.errno == errno.EINVAL: - # not a link - continue - else: - raise - else: - if inode.startswith('socket:['): - # the process is using a socket - inode = inode[8:][:-1] - inodes[inode].append((pid, int(fd))) - return inodes - - def get_all_inodes(self): - inodes = {} - for pid in pids(): - try: - inodes.update(self.get_proc_inodes(pid)) - except OSError as err: - # os.listdir() is gonna raise a lot of access denied - # exceptions in case of unprivileged user; that's fine - # as we'll just end up returning a connection with PID - # and fd set to None anyway. - # Both netstat -an and lsof does the same so it's - # unlikely we can do any better. - # ENOENT just means a PID disappeared on us. - if err.errno not in ( - errno.ENOENT, errno.ESRCH, errno.EPERM, errno.EACCES): - raise - return inodes - - def decode_address(self, addr, family): - """Accept an "ip:port" address as displayed in /proc/net/* - and convert it into a human readable form, like: - - "0500000A:0016" -> ("10.0.0.5", 22) - "0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521) - - The IP address portion is a little or big endian four-byte - hexadecimal number; that is, the least significant byte is listed - first, so we need to reverse the order of the bytes to convert it - to an IP address. - The port is represented as a two-byte hexadecimal number. - - Reference: - http://linuxdevcenter.com/pub/a/linux/2000/11/16/LinuxAdmin.html - """ - ip, port = addr.split(':') - port = int(port, 16) - # this usually refers to a local socket in listen mode with - # no end-points connected - if not port: - return () - if PY3: - ip = ip.encode('ascii') - if family == socket.AF_INET: - # see: https://github.com/giampaolo/psutil/issues/201 - if sys.byteorder == 'little': - ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1]) - else: - ip = socket.inet_ntop(family, base64.b16decode(ip)) - else: # IPv6 - # old version - let's keep it, just in case... - # ip = ip.decode('hex') - # return socket.inet_ntop(socket.AF_INET6, - # ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4))) - ip = base64.b16decode(ip) - # see: https://github.com/giampaolo/psutil/issues/201 - if sys.byteorder == 'little': - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('>4I', *struct.unpack('<4I', ip))) - else: - ip = socket.inet_ntop( - socket.AF_INET6, - struct.pack('<4I', *struct.unpack('<4I', ip))) - return (ip, port) - - def process_inet(self, file, family, type_, inodes, filter_pid=None): - """Parse /proc/net/tcp* and /proc/net/udp* files.""" - if file.endswith('6') and not os.path.exists(file): - # IPv6 not supported - return - with open(file, 'rt') as f: - f.readline() # skip the first line - for line in f: - try: - _, laddr, raddr, status, _, _, _, _, _, inode = \ - line.split()[:10] - except ValueError: - raise RuntimeError( - "error while parsing %s; malformed line %r" % ( - file, line)) - if inode in inodes: - # # We assume inet sockets are unique, so we error - # # out if there are multiple references to the - # # same inode. We won't do this for UNIX sockets. - # if len(inodes[inode]) > 1 and family != socket.AF_UNIX: - # raise ValueError("ambiguos inode with multiple " - # "PIDs references") - pid, fd = inodes[inode][0] - else: - pid, fd = None, -1 - if filter_pid is not None and filter_pid != pid: - continue - else: - if type_ == socket.SOCK_STREAM: - status = TCP_STATUSES[status] - else: - status = _common.CONN_NONE - laddr = self.decode_address(laddr, family) - raddr = self.decode_address(raddr, family) - yield (fd, family, type_, laddr, raddr, status, pid) - - def process_unix(self, file, family, inodes, filter_pid=None): - """Parse /proc/net/unix files.""" - with open(file, 'rt') as f: - f.readline() # skip the first line - for line in f: - tokens = line.split() - try: - _, _, _, _, type_, _, inode = tokens[0:7] - except ValueError: - raise RuntimeError( - "error while parsing %s; malformed line %r" % ( - file, line)) - if inode in inodes: - # With UNIX sockets we can have a single inode - # referencing many file descriptors. - pairs = inodes[inode] - else: - pairs = [(None, -1)] - for pid, fd in pairs: - if filter_pid is not None and filter_pid != pid: - continue - else: - if len(tokens) == 8: - path = tokens[-1] - else: - path = "" - type_ = int(type_) - raddr = None - status = _common.CONN_NONE - yield (fd, family, type_, path, raddr, status, pid) - - def retrieve(self, kind, pid=None): - if kind not in self.tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in self.tmap]))) - if pid is not None: - inodes = self.get_proc_inodes(pid) - if not inodes: - # no connections for this process - return [] - else: - inodes = self.get_all_inodes() - ret = set() - for f, family, type_ in self.tmap[kind]: - if family in (socket.AF_INET, socket.AF_INET6): - ls = self.process_inet( - "/proc/net/%s" % f, family, type_, inodes, filter_pid=pid) - else: - ls = self.process_unix( - "/proc/net/%s" % f, family, inodes, filter_pid=pid) - for fd, family, type_, laddr, raddr, status, bound_pid in ls: - if pid: - conn = _common.pconn(fd, family, type_, laddr, raddr, - status) - else: - conn = _common.sconn(fd, family, type_, laddr, raddr, - status, bound_pid) - ret.add(conn) - return list(ret) - - -_connections = Connections() - - -def net_connections(kind='inet'): - """Return system-wide open connections.""" - return _connections.retrieve(kind) - - -def net_io_counters(): - """Return network I/O statistics for every network interface - installed on the system as a dict of raw tuples. - """ - with open("/proc/net/dev", "rt") as f: - lines = f.readlines() - retdict = {} - for line in lines[2:]: - colon = line.rfind(':') - assert colon > 0, repr(line) - name = line[:colon].strip() - fields = line[colon + 1:].strip().split() - bytes_recv = int(fields[0]) - packets_recv = int(fields[1]) - errin = int(fields[2]) - dropin = int(fields[3]) - bytes_sent = int(fields[8]) - packets_sent = int(fields[9]) - errout = int(fields[10]) - dropout = int(fields[11]) - retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv, - errin, errout, dropin, dropout) - return retdict - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - duplex_map = {cext.DUPLEX_FULL: NIC_DUPLEX_FULL, - cext.DUPLEX_HALF: NIC_DUPLEX_HALF, - cext.DUPLEX_UNKNOWN: NIC_DUPLEX_UNKNOWN} - names = net_io_counters().keys() - ret = {} - for name in names: - isup, duplex, speed, mtu = cext.net_if_stats(name) - duplex = duplex_map[duplex] - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -net_if_addrs = cext_posix.net_if_addrs - - -# --- disks - -def disk_io_counters(): - """Return disk I/O statistics for every disk installed on the - system as a dict of raw tuples. - """ - # man iostat states that sectors are equivalent with blocks and - # have a size of 512 bytes since 2.4 kernels. This value is - # needed to calculate the amount of disk I/O in bytes. - SECTOR_SIZE = 512 - - # determine partitions we want to look for - partitions = [] - with open("/proc/partitions", "rt") as f: - lines = f.readlines()[2:] - for line in reversed(lines): - _, _, _, name = line.split() - if name[-1].isdigit(): - # we're dealing with a partition (e.g. 'sda1'); 'sda' will - # also be around but we want to omit it - partitions.append(name) - else: - if not partitions or not partitions[-1].startswith(name): - # we're dealing with a disk entity for which no - # partitions have been defined (e.g. 'sda' but - # 'sda1' was not around), see: - # https://github.com/giampaolo/psutil/issues/338 - partitions.append(name) - # - retdict = {} - with open("/proc/diskstats", "rt") as f: - lines = f.readlines() - for line in lines: - # http://www.mjmwired.net/kernel/Documentation/iostats.txt - fields = line.split() - if len(fields) > 7: - _, _, name, reads, _, rbytes, rtime, writes, _, wbytes, wtime = \ - fields[:11] - else: - # from kernel 2.6.0 to 2.6.25 - _, _, name, reads, rbytes, writes, wbytes = fields - rtime, wtime = 0, 0 - if name in partitions: - rbytes = int(rbytes) * SECTOR_SIZE - wbytes = int(wbytes) * SECTOR_SIZE - reads = int(reads) - writes = int(writes) - rtime = int(rtime) - wtime = int(wtime) - retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime) - return retdict - - -def disk_partitions(all=False): - """Return mounted disk partitions as a list of namedtuples""" - fstypes = set() - with open("/proc/filesystems", "r") as f: - for line in f: - line = line.strip() - if not line.startswith("nodev"): - fstypes.add(line.strip()) - else: - # ignore all lines starting with "nodev" except "nodev zfs" - fstype = line.split("\t")[1] - if fstype == "zfs": - fstypes.add("zfs") - - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if device == '' or fstype not in fstypes: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -disk_usage = _psposix.disk_usage - - -# --- decorators - -def wrap_exceptions(fun): - """Decorator which translates bare OSError and IOError exceptions - into NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except EnvironmentError as err: - # support for private module import - if NoSuchProcess is None or AccessDenied is None: - raise - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if err.errno in (errno.ENOENT, errno.ESRCH): - raise NoSuchProcess(self.pid, self._name) - if err.errno in (errno.EPERM, errno.EACCES): - raise AccessDenied(self.pid, self._name) - raise - return wrapper - - -def wrap_exceptions_w_zombie(fun): - """Same as above but also handles zombies.""" - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return wrap_exceptions(fun)(self) - except NoSuchProcess: - if not pid_exists(self.pid): - raise - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - return wrapper - - -class Process(object): - """Linux process implementation.""" - - __slots__ = ["pid", "_name", "_ppid"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - def name(self): - fname = "/proc/%s/stat" % self.pid - kw = dict(encoding=DEFAULT_ENCODING) if PY3 else dict() - with open(fname, "rt", **kw) as f: - data = f.read() - # XXX - gets changed later and probably needs refactoring - return data[data.find('(') + 1:data.rfind(')')] - - def exe(self): - try: - exe = os.readlink("/proc/%s/exe" % self.pid) - except OSError as err: - if err.errno in (errno.ENOENT, errno.ESRCH): - # no such file error; might be raised also if the - # path actually exists for system processes with - # low pids (about 0-20) - if os.path.lexists("/proc/%s" % self.pid): - return "" - else: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - if err.errno in (errno.EPERM, errno.EACCES): - raise AccessDenied(self.pid, self._name) - raise - - # readlink() might return paths containing null bytes ('\x00'). - # Certain names have ' (deleted)' appended. Usually this is - # bogus as the file actually exists. Either way that's not - # important as we don't want to discriminate executables which - # have been deleted. - exe = exe.split('\x00')[0] - if exe.endswith(' (deleted)') and not os.path.exists(exe): - exe = exe[:-10] - return exe - - @wrap_exceptions - def cmdline(self): - fname = "/proc/%s/cmdline" % self.pid - kw = dict(encoding=DEFAULT_ENCODING) if PY3 else dict() - with open(fname, "rt", **kw) as f: - data = f.read() - if data.endswith('\x00'): - data = data[:-1] - return [x for x in data.split('\x00')] - - @wrap_exceptions - def terminal(self): - tmap = _psposix._get_terminal_map() - with open("/proc/%s/stat" % self.pid, 'rb') as f: - tty_nr = int(f.read().split(b' ')[6]) - try: - return tmap[tty_nr] - except KeyError: - return None - - if os.path.exists('/proc/%s/io' % os.getpid()): - @wrap_exceptions - def io_counters(self): - fname = "/proc/%s/io" % self.pid - with open(fname, 'rb') as f: - rcount = wcount = rbytes = wbytes = None - for line in f: - if rcount is None and line.startswith(b"syscr"): - rcount = int(line.split()[1]) - elif wcount is None and line.startswith(b"syscw"): - wcount = int(line.split()[1]) - elif rbytes is None and line.startswith(b"read_bytes"): - rbytes = int(line.split()[1]) - elif wbytes is None and line.startswith(b"write_bytes"): - wbytes = int(line.split()[1]) - for x in (rcount, wcount, rbytes, wbytes): - if x is None: - raise NotImplementedError( - "couldn't read all necessary info from %r" % fname) - return _common.pio(rcount, wcount, rbytes, wbytes) - else: - def io_counters(self): - raise NotImplementedError("couldn't find /proc/%s/io (kernel " - "too old?)" % self.pid) - - @wrap_exceptions - def cpu_times(self): - with open("/proc/%s/stat" % self.pid, 'rb') as f: - st = f.read().strip() - # ignore the first two values ("pid (exe)") - st = st[st.find(b')') + 2:] - values = st.split(b' ') - utime = float(values[11]) / CLOCK_TICKS - stime = float(values[12]) / CLOCK_TICKS - return _common.pcputimes(utime, stime) - - @wrap_exceptions - def wait(self, timeout=None): - try: - return _psposix.wait_pid(self.pid, timeout) - except _psposix.TimeoutExpired: - # support for private module import - if TimeoutExpired is None: - raise - raise TimeoutExpired(timeout, self.pid, self._name) - - @wrap_exceptions - def create_time(self): - with open("/proc/%s/stat" % self.pid, 'rb') as f: - st = f.read().strip() - # ignore the first two values ("pid (exe)") - st = st[st.rfind(b')') + 2:] - values = st.split(b' ') - # According to documentation, starttime is in field 21 and the - # unit is jiffies (clock ticks). - # We first divide it for clock ticks and then add uptime returning - # seconds since the epoch, in UTC. - # Also use cached value if available. - bt = BOOT_TIME or boot_time() - return (float(values[19]) / CLOCK_TICKS) + bt - - @wrap_exceptions - def memory_info(self): - with open("/proc/%s/statm" % self.pid, 'rb') as f: - vms, rss = f.readline().split()[:2] - return _common.pmem(int(rss) * PAGESIZE, - int(vms) * PAGESIZE) - - @wrap_exceptions - def memory_info_ex(self): - # ============================================================ - # | FIELD | DESCRIPTION | AKA | TOP | - # ============================================================ - # | rss | resident set size | | RES | - # | vms | total program size | size | VIRT | - # | shared | shared pages (from shared mappings) | | SHR | - # | text | text ('code') | trs | CODE | - # | lib | library (unused in Linux 2.6) | lrs | | - # | data | data + stack | drs | DATA | - # | dirty | dirty pages (unused in Linux 2.6) | dt | | - # ============================================================ - with open("/proc/%s/statm" % self.pid, "rb") as f: - vms, rss, shared, text, lib, data, dirty = \ - [int(x) * PAGESIZE for x in f.readline().split()[:7]] - return pextmem(rss, vms, shared, text, lib, data, dirty) - - if os.path.exists('/proc/%s/smaps' % os.getpid()): - - @wrap_exceptions - def memory_maps(self): - """Return process's mapped memory regions as a list of named tuples. - Fields are explained in 'man proc'; here is an updated (Apr 2012) - version: http://goo.gl/fmebo - """ - with open("/proc/%s/smaps" % self.pid, "rt") as f: - first_line = f.readline() - current_block = [first_line] - - def get_blocks(): - data = {} - for line in f: - fields = line.split(None, 5) - if not fields[0].endswith(':'): - # new block section - yield (current_block.pop(), data) - current_block.append(line) - else: - try: - data[fields[0]] = int(fields[1]) * 1024 - except ValueError: - if fields[0].startswith('VmFlags:'): - # see issue #369 - continue - else: - raise ValueError("don't know how to inte" - "rpret line %r" % line) - yield (current_block.pop(), data) - - ls = [] - if first_line: # smaps file can be empty - for header, data in get_blocks(): - hfields = header.split(None, 5) - try: - addr, perms, offset, dev, inode, path = hfields - except ValueError: - addr, perms, offset, dev, inode, path = \ - hfields + [''] - if not path: - path = '[anon]' - else: - path = path.strip() - ls.append(( - addr, perms, path, - data['Rss:'], - data.get('Size:', 0), - data.get('Pss:', 0), - data.get('Shared_Clean:', 0), - data.get('Shared_Dirty:', 0), - data.get('Private_Clean:', 0), - data.get('Private_Dirty:', 0), - data.get('Referenced:', 0), - data.get('Anonymous:', 0), - data.get('Swap:', 0) - )) - return ls - - else: - def memory_maps(self): - msg = "couldn't find /proc/%s/smaps; kernel < 2.6.14 or " \ - "CONFIG_MMU kernel configuration option is not enabled" \ - % self.pid - raise NotImplementedError(msg) - - @wrap_exceptions_w_zombie - def cwd(self): - # readlink() might return paths containing null bytes causing - # problems when used with other fs-related functions (os.*, - # open(), ...) - path = os.readlink("/proc/%s/cwd" % self.pid) - return path.replace('\x00', '') - - @wrap_exceptions - def num_ctx_switches(self): - vol = unvol = None - with open("/proc/%s/status" % self.pid, "rb") as f: - for line in f: - if line.startswith(b"voluntary_ctxt_switches"): - vol = int(line.split()[1]) - elif line.startswith(b"nonvoluntary_ctxt_switches"): - unvol = int(line.split()[1]) - if vol is not None and unvol is not None: - return _common.pctxsw(vol, unvol) - raise NotImplementedError( - "'voluntary_ctxt_switches' and 'nonvoluntary_ctxt_switches'" - "fields were not found in /proc/%s/status; the kernel is " - "probably older than 2.6.23" % self.pid) - - @wrap_exceptions - def num_threads(self): - with open("/proc/%s/status" % self.pid, "rb") as f: - for line in f: - if line.startswith(b"Threads:"): - return int(line.split()[1]) - raise NotImplementedError("line not found") - - @wrap_exceptions - def threads(self): - thread_ids = os.listdir("/proc/%s/task" % self.pid) - thread_ids.sort() - retlist = [] - hit_enoent = False - for thread_id in thread_ids: - fname = "/proc/%s/task/%s/stat" % (self.pid, thread_id) - try: - with open(fname, 'rb') as f: - st = f.read().strip() - except IOError as err: - if err.errno == errno.ENOENT: - # no such file or directory; it means thread - # disappeared on us - hit_enoent = True - continue - raise - # ignore the first two values ("pid (exe)") - st = st[st.find(b')') + 2:] - values = st.split(b' ') - utime = float(values[11]) / CLOCK_TICKS - stime = float(values[12]) / CLOCK_TICKS - ntuple = _common.pthread(int(thread_id), utime, stime) - retlist.append(ntuple) - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return retlist - - @wrap_exceptions - def nice_get(self): - # with open('/proc/%s/stat' % self.pid, 'r') as f: - # data = f.read() - # return int(data.split()[18]) - - # Use C implementation - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def cpu_affinity_get(self): - return cext.proc_cpu_affinity_get(self.pid) - - @wrap_exceptions - def cpu_affinity_set(self, cpus): - try: - cext.proc_cpu_affinity_set(self.pid, cpus) - except OSError as err: - if err.errno == errno.EINVAL: - allcpus = tuple(range(len(per_cpu_times()))) - for cpu in cpus: - if cpu not in allcpus: - raise ValueError("invalid CPU #%i (choose between %s)" - % (cpu, allcpus)) - raise - - # only starting from kernel 2.6.13 - if hasattr(cext, "proc_ioprio_get"): - - @wrap_exceptions - def ionice_get(self): - ioclass, value = cext.proc_ioprio_get(self.pid) - if enum is not None: - ioclass = IOPriority(ioclass) - return _common.pionice(ioclass, value) - - @wrap_exceptions - def ionice_set(self, ioclass, value): - if value is not None: - if not PY3 and not isinstance(value, (int, long)): - msg = "value argument is not an integer (gor %r)" % value - raise TypeError(msg) - if not 0 <= value <= 8: - raise ValueError( - "value argument range expected is between 0 and 8") - - if ioclass in (IOPRIO_CLASS_NONE, None): - if value: - msg = "can't specify value with IOPRIO_CLASS_NONE " \ - "(got %r)" % value - raise ValueError(msg) - ioclass = IOPRIO_CLASS_NONE - value = 0 - elif ioclass == IOPRIO_CLASS_IDLE: - if value: - msg = "can't specify value with IOPRIO_CLASS_IDLE " \ - "(got %r)" % value - raise ValueError(msg) - value = 0 - elif ioclass in (IOPRIO_CLASS_RT, IOPRIO_CLASS_BE): - if value is None: - # TODO: add comment explaining why this is 4 (?) - value = 4 - else: - # otherwise we would get OSError(EVINAL) - raise ValueError("invalid ioclass argument %r" % ioclass) - - return cext.proc_ioprio_set(self.pid, ioclass, value) - - if HAS_PRLIMIT: - @wrap_exceptions - def rlimit(self, resource, limits=None): - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. We should never get here though as - # PID 0 is not supported on Linux. - if self.pid == 0: - raise ValueError("can't use prlimit() against PID 0 process") - try: - if limits is None: - # get - return cext.linux_prlimit(self.pid, resource) - else: - # set - if len(limits) != 2: - raise ValueError( - "second argument must be a (soft, hard) tuple, " - "got %s" % repr(limits)) - soft, hard = limits - cext.linux_prlimit(self.pid, resource, soft, hard) - except OSError as err: - if err.errno == errno.ENOSYS and pid_exists(self.pid): - # I saw this happening on Travis: - # https://travis-ci.org/giampaolo/psutil/jobs/51368273 - raise ZombieProcess(self.pid, self._name, self._ppid) - else: - raise - - @wrap_exceptions - def status(self): - with open("/proc/%s/status" % self.pid, 'rb') as f: - for line in f: - if line.startswith(b"State:"): - letter = line.split()[1] - if PY3: - letter = letter.decode() - # XXX is '?' legit? (we're not supposed to return - # it anyway) - return PROC_STATUSES.get(letter, '?') - - @wrap_exceptions - def open_files(self): - retlist = [] - files = os.listdir("/proc/%s/fd" % self.pid) - hit_enoent = False - for fd in files: - file = "/proc/%s/fd/%s" % (self.pid, fd) - try: - file = os.readlink(file) - except OSError as err: - # ENOENT == file which is gone in the meantime - if err.errno in (errno.ENOENT, errno.ESRCH): - hit_enoent = True - continue - elif err.errno == errno.EINVAL: - # not a link - continue - else: - raise - else: - # If file is not an absolute path there's no way - # to tell whether it's a regular file or not, - # so we skip it. A regular file is always supposed - # to be absolutized though. - if file.startswith('/') and isfile_strict(file): - ntuple = _common.popenfile(file, int(fd)) - retlist.append(ntuple) - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - ret = _connections.retrieve(kind, self.pid) - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return ret - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("/proc/%s/fd" % self.pid)) - - @wrap_exceptions - def ppid(self): - fpath = "/proc/%s/status" % self.pid - with open(fpath, 'rb') as f: - for line in f: - if line.startswith(b"PPid:"): - # PPid: nnnn - return int(line.split()[1]) - raise NotImplementedError("line 'PPid' not found in %s" % fpath) - - @wrap_exceptions - def uids(self): - fpath = "/proc/%s/status" % self.pid - with open(fpath, 'rb') as f: - for line in f: - if line.startswith(b'Uid:'): - _, real, effective, saved, fs = line.split() - return _common.puids(int(real), int(effective), int(saved)) - raise NotImplementedError("line 'Uid' not found in %s" % fpath) - - @wrap_exceptions - def gids(self): - fpath = "/proc/%s/status" % self.pid - with open(fpath, 'rb') as f: - for line in f: - if line.startswith(b'Gid:'): - _, real, effective, saved, fs = line.split() - return _common.pgids(int(real), int(effective), int(saved)) - raise NotImplementedError("line 'Gid' not found in %s" % fpath) diff --git a/python/psutil/psutil/_psosx.py b/python/psutil/psutil/_psosx.py deleted file mode 100644 index 41875fe40..000000000 --- a/python/psutil/psutil/_psosx.py +++ /dev/null @@ -1,363 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""OSX platform implementation.""" - -import errno -import functools -import os -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_osx as cext -from . import _psutil_posix as cext_posix -from ._common import conn_tmap, usage_percent, isfile_strict -from ._common import sockfam_to_enum, socktype_to_enum - - -__extra__all__ = [] - -# --- constants - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -AF_LINK = cext_posix.AF_LINK - -# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RECEIVED: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -PROC_STATUSES = { - cext.SIDL: _common.STATUS_IDLE, - cext.SRUN: _common.STATUS_RUNNING, - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SZOMB: _common.STATUS_ZOMBIE, -} - -scputimes = namedtuple('scputimes', ['user', 'nice', 'system', 'idle']) - -svmem = namedtuple( - 'svmem', ['total', 'available', 'percent', 'used', 'free', - 'active', 'inactive', 'wired']) - -pextmem = namedtuple('pextmem', ['rss', 'vms', 'pfaults', 'pageins']) - -pmmap_grouped = namedtuple( - 'pmmap_grouped', - 'path rss private swapped dirtied ref_count shadow_depth') - -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) - -# set later from __init__.py -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - - -# --- functions - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - total, active, inactive, wired, free = cext.virtual_mem() - avail = inactive + free - used = active + inactive + wired - percent = usage_percent((total - avail), total, _round=1) - return svmem(total, avail, percent, used, free, - active, inactive, wired) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - total, used, free, sin, sout = cext.swap_mem() - percent = usage_percent(used, total, _round=1) - return _common.sswap(total, used, free, percent, sin, sout) - - -def cpu_times(): - """Return system CPU times as a namedtuple.""" - user, nice, system, idle = cext.cpu_times() - return scputimes(user, nice, system, idle) - - -def per_cpu_times(): - """Return system CPU times as a named tuple""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, nice, system, idle = cpu_t - item = scputimes(user, nice, system, idle) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def disk_partitions(all=False): - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - if not os.path.isabs(device) or not os.path.exists(device): - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -def users(): - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, tty, hostname, tstamp = item - if tty == '~': - continue # reboot or shutdown - if not tstamp: - continue - nt = _common.suser(user, tty or None, hostname or None, tstamp) - retlist.append(nt) - return retlist - - -def net_connections(kind='inet'): - # Note: on OSX this will fail with AccessDenied unless - # the process is owned by root. - ret = [] - for pid in pids(): - try: - cons = Process(pid).connections(kind) - except NoSuchProcess: - continue - else: - if cons: - for c in cons: - c = list(c) + [pid] - ret.append(_common.sconn(*c)) - return ret - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - names = net_io_counters().keys() - ret = {} - for name in names: - isup, duplex, speed, mtu = cext_posix.net_if_stats(name) - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -pids = cext.pids -pid_exists = _psposix.pid_exists -disk_usage = _psposix.disk_usage -net_io_counters = cext.net_io_counters -disk_io_counters = cext.disk_io_counters -net_if_addrs = cext_posix.net_if_addrs - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError exceptions into - NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - # support for private module import - if (NoSuchProcess is None or AccessDenied is None or - ZombieProcess is None): - raise - if err.errno == errno.ESRCH: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - if err.errno in (errno.EPERM, errno.EACCES): - raise AccessDenied(self.pid, self._name) - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - def name(self): - return cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - return cext.proc_exe(self.pid) - - @wrap_exceptions - def cmdline(self): - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - return cext.proc_cmdline(self.pid) - - @wrap_exceptions - def ppid(self): - return cext.proc_ppid(self.pid) - - @wrap_exceptions - def cwd(self): - return cext.proc_cwd(self.pid) - - @wrap_exceptions - def uids(self): - real, effective, saved = cext.proc_uids(self.pid) - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - real, effective, saved = cext.proc_gids(self.pid) - return _common.pgids(real, effective, saved) - - @wrap_exceptions - def terminal(self): - tty_nr = cext.proc_tty_nr(self.pid) - tmap = _psposix._get_terminal_map() - try: - return tmap[tty_nr] - except KeyError: - return None - - @wrap_exceptions - def memory_info(self): - rss, vms = cext.proc_memory_info(self.pid)[:2] - return _common.pmem(rss, vms) - - @wrap_exceptions - def memory_info_ex(self): - rss, vms, pfaults, pageins = cext.proc_memory_info(self.pid) - return pextmem(rss, vms, pfaults * PAGESIZE, pageins * PAGESIZE) - - @wrap_exceptions - def cpu_times(self): - user, system = cext.proc_cpu_times(self.pid) - return _common.pcputimes(user, system) - - @wrap_exceptions - def create_time(self): - return cext.proc_create_time(self.pid) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid)) - - @wrap_exceptions - def num_threads(self): - return cext.proc_num_threads(self.pid) - - @wrap_exceptions - def open_files(self): - if self.pid == 0: - return [] - files = [] - rawlist = cext.proc_open_files(self.pid) - for path, fd in rawlist: - if isfile_strict(path): - ntuple = _common.popenfile(path, fd) - files.append(ntuple) - return files - - @wrap_exceptions - def connections(self, kind='inet'): - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - rawlist = cext.proc_connections(self.pid, families, types) - ret = [] - for item in rawlist: - fd, fam, type, laddr, raddr, status = item - status = TCP_STATUSES[status] - fam = sockfam_to_enum(fam) - type = socktype_to_enum(type) - nt = _common.pconn(fd, fam, type, laddr, raddr, status) - ret.append(nt) - return ret - - @wrap_exceptions - def num_fds(self): - if self.pid == 0: - return 0 - return cext.proc_num_fds(self.pid) - - @wrap_exceptions - def wait(self, timeout=None): - try: - return _psposix.wait_pid(self.pid, timeout) - except _psposix.TimeoutExpired: - # support for private module import - if TimeoutExpired is None: - raise - raise TimeoutExpired(timeout, self.pid, self._name) - - @wrap_exceptions - def nice_get(self): - return cext_posix.getpriority(self.pid) - - @wrap_exceptions - def nice_set(self, value): - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def status(self): - code = cext.proc_status(self.pid) - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @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) - return retlist - - @wrap_exceptions - def memory_maps(self): - return cext.proc_memory_maps(self.pid) diff --git a/python/psutil/psutil/_psposix.py b/python/psutil/psutil/_psposix.py deleted file mode 100644 index 5bb16a386..000000000 --- a/python/psutil/psutil/_psposix.py +++ /dev/null @@ -1,156 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Routines common to all posix systems.""" - -import errno -import glob -import os -import sys -import time - -from ._common import sdiskusage, usage_percent, memoize -from ._compat import PY3, unicode - - -class TimeoutExpired(Exception): - pass - - -def pid_exists(pid): - """Check whether pid exists in the current process table.""" - if pid == 0: - # According to "man 2 kill" PID 0 has a special meaning: - # it refers to <<every process in the process group of the - # calling process>> so we don't want to go any further. - # If we get here it means this UNIX platform *does* have - # a process with id 0. - return True - try: - os.kill(pid, 0) - except OSError as err: - if err.errno == errno.ESRCH: - # ESRCH == No such process - return False - elif err.errno == errno.EPERM: - # EPERM clearly means there's a process to deny access to - return True - else: - # According to "man 2 kill" possible error values are - # (EINVAL, EPERM, ESRCH) therefore we should never get - # here. If we do let's be explicit in considering this - # an error. - raise err - else: - return True - - -def wait_pid(pid, timeout=None): - """Wait for process with pid 'pid' to terminate and return its - exit status code as an integer. - - If pid is not a children of os.getpid() (current process) just - waits until the process disappears and return None. - - If pid does not exist at all return None immediately. - - Raise TimeoutExpired on timeout expired. - """ - def check_timeout(delay): - if timeout is not None: - if timer() >= stop_at: - raise TimeoutExpired() - time.sleep(delay) - return min(delay * 2, 0.04) - - timer = getattr(time, 'monotonic', time.time) - if timeout is not None: - def waitcall(): - return os.waitpid(pid, os.WNOHANG) - stop_at = timer() + timeout - else: - def waitcall(): - return os.waitpid(pid, 0) - - delay = 0.0001 - while True: - try: - retpid, status = waitcall() - except OSError as err: - if err.errno == errno.EINTR: - delay = check_timeout(delay) - continue - elif err.errno == errno.ECHILD: - # This has two meanings: - # - pid is not a child of os.getpid() in which case - # we keep polling until it's gone - # - pid never existed in the first place - # In both cases we'll eventually return None as we - # can't determine its exit status code. - while True: - if pid_exists(pid): - delay = check_timeout(delay) - else: - return - else: - raise - else: - if retpid == 0: - # WNOHANG was used, pid is still running - delay = check_timeout(delay) - continue - # process exited due to a signal; return the integer of - # that signal - if os.WIFSIGNALED(status): - return os.WTERMSIG(status) - # process exited using exit(2) system call; return the - # integer exit(2) system call has been called with - elif os.WIFEXITED(status): - return os.WEXITSTATUS(status) - else: - # should never happen - raise RuntimeError("unknown process exit status") - - -def disk_usage(path): - """Return disk usage associated with path.""" - try: - st = os.statvfs(path) - except UnicodeEncodeError: - if not PY3 and isinstance(path, unicode): - # this is a bug with os.statvfs() and unicode on - # Python 2, see: - # - https://github.com/giampaolo/psutil/issues/416 - # - http://bugs.python.org/issue18695 - try: - path = path.encode(sys.getfilesystemencoding()) - except UnicodeEncodeError: - pass - st = os.statvfs(path) - else: - raise - free = (st.f_bavail * st.f_frsize) - total = (st.f_blocks * st.f_frsize) - used = (st.f_blocks - st.f_bfree) * st.f_frsize - percent = usage_percent(used, total, _round=1) - # NB: the percentage is -5% than what shown by df due to - # reserved blocks that we are currently not considering: - # http://goo.gl/sWGbH - return sdiskusage(total, used, free, percent) - - -@memoize -def _get_terminal_map(): - ret = {} - ls = glob.glob('/dev/tty*') + glob.glob('/dev/pts/*') - for name in ls: - assert name not in ret - try: - ret[os.stat(name).st_rdev] = name - except OSError as err: - if err.errno != errno.ENOENT: - raise - return ret diff --git a/python/psutil/psutil/_pssunos.py b/python/psutil/psutil/_pssunos.py deleted file mode 100644 index bc35a718c..000000000 --- a/python/psutil/psutil/_pssunos.py +++ /dev/null @@ -1,553 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Sun OS Solaris platform implementation.""" - -import errno -import os -import socket -import subprocess -import sys -from collections import namedtuple - -from . import _common -from . import _psposix -from . import _psutil_posix as cext_posix -from . import _psutil_sunos as cext -from ._common import isfile_strict, socktype_to_enum, sockfam_to_enum -from ._common import usage_percent -from ._compat import PY3 - - -__extra__all__ = ["CONN_IDLE", "CONN_BOUND"] - -PAGE_SIZE = os.sysconf('SC_PAGE_SIZE') -AF_LINK = cext_posix.AF_LINK - -CONN_IDLE = "IDLE" -CONN_BOUND = "BOUND" - -PROC_STATUSES = { - cext.SSLEEP: _common.STATUS_SLEEPING, - cext.SRUN: _common.STATUS_RUNNING, - cext.SZOMB: _common.STATUS_ZOMBIE, - cext.SSTOP: _common.STATUS_STOPPED, - cext.SIDL: _common.STATUS_IDLE, - cext.SONPROC: _common.STATUS_RUNNING, # same as run - cext.SWAIT: _common.STATUS_WAITING, -} - -TCP_STATUSES = { - cext.TCPS_ESTABLISHED: _common.CONN_ESTABLISHED, - cext.TCPS_SYN_SENT: _common.CONN_SYN_SENT, - cext.TCPS_SYN_RCVD: _common.CONN_SYN_RECV, - cext.TCPS_FIN_WAIT_1: _common.CONN_FIN_WAIT1, - cext.TCPS_FIN_WAIT_2: _common.CONN_FIN_WAIT2, - cext.TCPS_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.TCPS_CLOSED: _common.CONN_CLOSE, - cext.TCPS_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.TCPS_LAST_ACK: _common.CONN_LAST_ACK, - cext.TCPS_LISTEN: _common.CONN_LISTEN, - cext.TCPS_CLOSING: _common.CONN_CLOSING, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, - cext.TCPS_IDLE: CONN_IDLE, # sunos specific - cext.TCPS_BOUND: CONN_BOUND, # sunos specific -} - -scputimes = namedtuple('scputimes', ['user', 'system', 'idle', 'iowait']) -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -pextmem = namedtuple('pextmem', ['rss', 'vms']) -pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss', 'anon', 'locked']) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) - -# set later from __init__.py -NoSuchProcess = None -ZombieProcess = None -AccessDenied = None -TimeoutExpired = None - -# --- functions - -disk_io_counters = cext.disk_io_counters -net_io_counters = cext.net_io_counters -disk_usage = _psposix.disk_usage -net_if_addrs = cext_posix.net_if_addrs - - -def virtual_memory(): - # we could have done this with kstat, but imho this is good enough - total = os.sysconf('SC_PHYS_PAGES') * PAGE_SIZE - # note: there's no difference on Solaris - free = avail = os.sysconf('SC_AVPHYS_PAGES') * PAGE_SIZE - used = total - free - percent = usage_percent(used, total, _round=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - sin, sout = cext.swap_mem() - # XXX - # we are supposed to get total/free by doing so: - # http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/ - # usr/src/cmd/swap/swap.c - # ...nevertheless I can't manage to obtain the same numbers as 'swap' - # cmdline utility, so let's parse its output (sigh!) - p = subprocess.Popen(['/usr/bin/env', 'PATH=/usr/sbin:/sbin:%s' % - os.environ['PATH'], 'swap', '-l', '-k'], - stdout=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout = stdout.decode(sys.stdout.encoding) - if p.returncode != 0: - raise RuntimeError("'swap -l -k' failed (retcode=%s)" % p.returncode) - - lines = stdout.strip().split('\n')[1:] - if not lines: - raise RuntimeError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - t = t.replace('K', '') - f = f.replace('K', '') - total += int(int(t) * 1024) - free += int(int(f) * 1024) - used = total - free - percent = usage_percent(used, total, _round=1) - return _common.sswap(total, used, free, percent, - sin * PAGE_SIZE, sout * PAGE_SIZE) - - -def pids(): - """Returns a list of PIDs currently running on the system.""" - return [int(x) for x in os.listdir('/proc') if x.isdigit()] - - -def pid_exists(pid): - """Check for the existence of a unix pid.""" - return _psposix.pid_exists(pid) - - -def cpu_times(): - """Return system-wide CPU times as a named tuple""" - ret = cext.per_cpu_times() - return scputimes(*[sum(x) for x in zip(*ret)]) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples""" - ret = cext.per_cpu_times() - return [scputimes(*x) for x in ret] - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - try: - return os.sysconf("SC_NPROCESSORS_ONLN") - except ValueError: - # mimic os.cpu_count() behavior - return None - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - localhost = (':0.0', ':0') - for item in rawlist: - user, tty, hostname, tstamp, user_process = item - # note: the underlying C function includes entries about - # system boot, run level and others. We might want - # to use them in the future. - if not user_process: - continue - if hostname in localhost: - hostname = 'localhost' - nt = _common.suser(user, tty, hostname, tstamp) - retlist.append(nt) - return retlist - - -def disk_partitions(all=False): - """Return system disk partitions.""" - # TODO - the filtering logic should be better checked so that - # it tries to reflect 'df' as much as possible - retlist = [] - partitions = cext.disk_partitions() - for partition in partitions: - device, mountpoint, fstype, opts = partition - if device == 'none': - device = '' - if not all: - # Differently from, say, Linux, we don't have a list of - # common fs types so the best we can do, AFAIK, is to - # filter by filesystem having a total size > 0. - if not disk_usage(mountpoint).total: - continue - ntuple = _common.sdiskpart(device, mountpoint, fstype, opts) - retlist.append(ntuple) - return retlist - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - Only INET sockets are returned (UNIX are not). - """ - cmap = _common.conn_tmap.copy() - if _pid == -1: - cmap.pop('unix', 0) - if kind not in cmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in cmap]))) - families, types = _common.conn_tmap[kind] - rawlist = cext.net_connections(_pid, families, types) - ret = set() - for item in rawlist: - fd, fam, type_, laddr, raddr, status, pid = item - if fam not in families: - continue - if type_ not in types: - continue - status = TCP_STATUSES[status] - fam = sockfam_to_enum(fam) - type_ = socktype_to_enum(type_) - if _pid == -1: - nt = _common.sconn(fd, fam, type_, laddr, raddr, status, pid) - else: - nt = _common.pconn(fd, fam, type_, laddr, raddr, status) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - """Get NIC stats (isup, duplex, speed, mtu).""" - ret = cext.net_if_stats() - for name, items in ret.items(): - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def wrap_exceptions(fun): - """Call callable into a try/except clause and translate ENOENT, - EACCES and EPERM in NoSuchProcess or AccessDenied exceptions. - """ - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except EnvironmentError as err: - # support for private module import - if (NoSuchProcess is None or AccessDenied is None or - ZombieProcess is None): - raise - # ENOENT (no such file or directory) gets raised on open(). - # ESRCH (no such process) can get raised on read() if - # process is gone in meantime. - if err.errno in (errno.ENOENT, errno.ESRCH): - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: - raise ZombieProcess(self.pid, self._name, self._ppid) - if err.errno in (errno.EPERM, errno.EACCES): - raise AccessDenied(self.pid, self._name) - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - def name(self): - # note: max len == 15 - return cext.proc_name_and_args(self.pid)[0] - - @wrap_exceptions - def exe(self): - # Will be guess later from cmdline but we want to explicitly - # invoke cmdline here in order to get an AccessDenied - # exception if the user has not enough privileges. - self.cmdline() - return "" - - @wrap_exceptions - def cmdline(self): - return cext.proc_name_and_args(self.pid)[1].split(' ') - - @wrap_exceptions - def create_time(self): - return cext.proc_basic_info(self.pid)[3] - - @wrap_exceptions - def num_threads(self): - return cext.proc_basic_info(self.pid)[5] - - @wrap_exceptions - def nice_get(self): - # For some reason getpriority(3) return ESRCH (no such process) - # for certain low-pid processes, no matter what (even as root). - # The process actually exists though, as it has a name, - # creation time, etc. - # The best thing we can do here appears to be raising AD. - # Note: tested on Solaris 11; on Open Solaris 5 everything is - # fine. - try: - return cext_posix.getpriority(self.pid) - except EnvironmentError as err: - # 48 is 'operation not supported' but errno does not expose - # it. It occurs for low system pids. - if err.errno in (errno.ENOENT, errno.ESRCH, 48): - if pid_exists(self.pid): - raise AccessDenied(self.pid, self._name) - raise - - @wrap_exceptions - def nice_set(self, value): - if self.pid in (2, 3): - # Special case PIDs: internally setpriority(3) return ESRCH - # (no such process), no matter what. - # The process actually exists though, as it has a name, - # creation time, etc. - raise AccessDenied(self.pid, self._name) - return cext_posix.setpriority(self.pid, value) - - @wrap_exceptions - def ppid(self): - return cext.proc_basic_info(self.pid)[0] - - @wrap_exceptions - def uids(self): - real, effective, saved, _, _, _ = cext.proc_cred(self.pid) - return _common.puids(real, effective, saved) - - @wrap_exceptions - def gids(self): - _, _, _, real, effective, saved = cext.proc_cred(self.pid) - return _common.puids(real, effective, saved) - - @wrap_exceptions - def cpu_times(self): - user, system = cext.proc_cpu_times(self.pid) - return _common.pcputimes(user, system) - - @wrap_exceptions - def terminal(self): - hit_enoent = False - tty = wrap_exceptions( - cext.proc_basic_info(self.pid)[0]) - if tty != cext.PRNODEV: - for x in (0, 1, 2, 255): - try: - return os.readlink('/proc/%d/path/%d' % (self.pid, x)) - except OSError as err: - if err.errno == errno.ENOENT: - hit_enoent = True - continue - raise - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - - @wrap_exceptions - def cwd(self): - # /proc/PID/path/cwd may not be resolved by readlink() even if - # it exists (ls shows it). If that's the case and the process - # is still alive return None (we can return None also on BSD). - # Reference: http://goo.gl/55XgO - try: - return os.readlink("/proc/%s/path/cwd" % self.pid) - except OSError as err: - if err.errno == errno.ENOENT: - os.stat("/proc/%s" % self.pid) - return None - raise - - @wrap_exceptions - def memory_info(self): - ret = cext.proc_basic_info(self.pid) - rss, vms = ret[1] * 1024, ret[2] * 1024 - return _common.pmem(rss, vms) - - # it seems Solaris uses rss and vms only - memory_info_ex = memory_info - - @wrap_exceptions - def status(self): - code = cext.proc_basic_info(self.pid)[6] - # XXX is '?' legit? (we're not supposed to return it anyway) - return PROC_STATUSES.get(code, '?') - - @wrap_exceptions - def threads(self): - ret = [] - tids = os.listdir('/proc/%d/lwp' % self.pid) - hit_enoent = False - for tid in tids: - tid = int(tid) - try: - utime, stime = cext.query_process_thread( - self.pid, tid) - except EnvironmentError as err: - # ENOENT == thread gone in meantime - if err.errno == errno.ENOENT: - hit_enoent = True - continue - raise - else: - nt = _common.pthread(tid, utime, stime) - ret.append(nt) - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return ret - - @wrap_exceptions - def open_files(self): - retlist = [] - hit_enoent = False - pathdir = '/proc/%d/path' % self.pid - for fd in os.listdir('/proc/%d/fd' % self.pid): - path = os.path.join(pathdir, fd) - if os.path.islink(path): - try: - file = os.readlink(path) - except OSError as err: - # ENOENT == file which is gone in the meantime - if err.errno == errno.ENOENT: - hit_enoent = True - continue - raise - else: - if isfile_strict(file): - retlist.append(_common.popenfile(file, int(fd))) - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return retlist - - def _get_unix_sockets(self, pid): - """Get UNIX sockets used by process by parsing 'pfiles' output.""" - # TODO: rewrite this in C (...but the damn netstat source code - # does not include this part! Argh!!) - cmd = "pfiles %s" % pid - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - stdout, stderr = p.communicate() - if PY3: - stdout, stderr = [x.decode(sys.stdout.encoding) - for x in (stdout, stderr)] - if p.returncode != 0: - if 'permission denied' in stderr.lower(): - raise AccessDenied(self.pid, self._name) - if 'no such process' in stderr.lower(): - raise NoSuchProcess(self.pid, self._name) - raise RuntimeError("%r command error\n%s" % (cmd, stderr)) - - lines = stdout.split('\n')[2:] - for i, line in enumerate(lines): - line = line.lstrip() - if line.startswith('sockname: AF_UNIX'): - path = line.split(' ', 2)[2] - type = lines[i - 2].strip() - if type == 'SOCK_STREAM': - type = socket.SOCK_STREAM - elif type == 'SOCK_DGRAM': - type = socket.SOCK_DGRAM - else: - type = -1 - yield (-1, socket.AF_UNIX, type, path, "", _common.CONN_NONE) - - @wrap_exceptions - def connections(self, kind='inet'): - ret = net_connections(kind, _pid=self.pid) - # The underlying C implementation retrieves all OS connections - # 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 ret: - os.stat('/proc/%s' % self.pid) # will raise NSP if process is gone - - # UNIX sockets - if kind in ('all', 'unix'): - ret.extend([_common.pconn(*conn) for conn in - self._get_unix_sockets(self.pid)]) - return ret - - nt_mmap_grouped = namedtuple('mmap', 'path rss anon locked') - nt_mmap_ext = namedtuple('mmap', 'addr perms path rss anon locked') - - @wrap_exceptions - def memory_maps(self): - def toaddr(start, end): - return '%s-%s' % (hex(start)[2:].strip('L'), - hex(end)[2:].strip('L')) - - retlist = [] - rawlist = cext.proc_memory_maps(self.pid) - hit_enoent = False - for item in rawlist: - addr, addrsize, perm, name, rss, anon, locked = item - addr = toaddr(addr, addrsize) - if not name.startswith('['): - try: - name = os.readlink('/proc/%s/path/%s' % (self.pid, name)) - except OSError as err: - if err.errno == errno.ENOENT: - # sometimes the link may not be resolved by - # readlink() even if it exists (ls shows it). - # If that's the case we just return the - # unresolved link path. - # This seems an incosistency with /proc similar - # to: http://goo.gl/55XgO - name = '/proc/%s/path/%s' % (self.pid, name) - hit_enoent = True - else: - raise - retlist.append((addr, perm, name, rss, anon, locked)) - if hit_enoent: - # raise NSP if the process disappeared on us - os.stat('/proc/%s' % self.pid) - return retlist - - @wrap_exceptions - def num_fds(self): - return len(os.listdir("/proc/%s/fd" % self.pid)) - - @wrap_exceptions - def num_ctx_switches(self): - return _common.pctxsw(*cext.proc_num_ctx_switches(self.pid)) - - @wrap_exceptions - def wait(self, timeout=None): - try: - return _psposix.wait_pid(self.pid, timeout) - except _psposix.TimeoutExpired: - # support for private module import - if TimeoutExpired is None: - raise - raise TimeoutExpired(timeout, self.pid, self._name) diff --git a/python/psutil/psutil/_psutil_bsd.c b/python/psutil/psutil/_psutil_bsd.c deleted file mode 100644 index 7b6e56173..000000000 --- a/python/psutil/psutil/_psutil_bsd.c +++ /dev/null @@ -1,2296 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * FreeBSD platform-specific module methods for _psutil_bsd - */ - - -#include <Python.h> -#include <assert.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#include <signal.h> -#include <fcntl.h> -#include <paths.h> -#include <sys/types.h> -#include <sys/sysctl.h> -#include <sys/param.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <sys/file.h> -#include <sys/cpuset.h> -#include <net/route.h> - -#include <sys/socket.h> -#include <sys/socketvar.h> // for struct xsocket -#include <sys/un.h> -#include <sys/unpcb.h> -#include <sys/sockio.h> -// for xinpcb struct -#include <netinet/in.h> -#include <netinet/in_systm.h> -#include <netinet/ip.h> -#include <netinet/in_pcb.h> -#include <netinet/tcp_var.h> // for struct xtcpcb -#include <netinet/tcp_fsm.h> // for TCP connection states -#include <arpa/inet.h> // for inet_ntop() - -#if __FreeBSD_version < 900000 -#include <utmp.h> // system users -#else -#include <utmpx.h> -#endif -#include <devstat.h> // get io counters -#include <sys/vmmeter.h> // needed for vmtotal struct -#include <libutil.h> // process open files, shared libs (kinfo_getvmmap) -#include <sys/mount.h> - -#include <net/if.h> // net io counters -#include <net/if_dl.h> -#include <net/route.h> -#include <net/if_media.h> - -#include <netinet/in.h> // process open files/connections -#include <sys/un.h> - -#include "_psutil_bsd.h" -#include "_psutil_common.h" -#include "arch/bsd/process_info.h" - - -// convert a timeval struct to a double -#define TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - - -/* - * Utility function which fills a kinfo_proc struct based on process pid - */ -static int -psutil_kinfo_proc(const pid_t pid, struct kinfo_proc *proc) -{ - int mib[4]; - size_t size; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - - size = sizeof(struct kinfo_proc); - - if (sysctl((int *)mib, 4, proc, &size, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - // sysctl stores 0 in the size if we can't find the process information. - if (size == 0) { - NoSuchProcess(); - return -1; - } - return 0; -} - - -/* - * Set exception to AccessDenied if pid exists else NoSuchProcess. - */ -void -psutil_raise_ad_or_nsp(long pid) { - if (psutil_pid_exists(pid) == 0) - NoSuchProcess(); - else - AccessDenied(); -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) -{ - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *retlist = PyList_New(0); - PyObject *pid = NULL; - - if (retlist == NULL) - return NULL; - if (psutil_get_proc_list(&proclist, &num_processes) != 0) { - PyErr_SetString(PyExc_RuntimeError, - "failed to retrieve process list."); - goto error; - } - - if (num_processes > 0) { - orig_address = proclist; // save so we can free it after we're done - for (idx = 0; idx < num_processes; idx++) { - pid = Py_BuildValue("i", proclist->ki_pid); - if (!pid) - goto error; - if (PyList_Append(retlist, pid)) - goto error; - Py_DECREF(pid); - proclist++; - } - free(orig_address); - } - - return retlist; - -error: - Py_XDECREF(pid); - Py_DECREF(retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) -{ - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval boottime; - size_t len = sizeof(boottime); - - if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return Py_BuildValue("d", (double)boottime.tv_sec); -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("s", kp.ki_comm); -} - - -/* - * Return process pathname executable. - * Thanks to Robert N. M. Watson: - * http://fxr.googlebit.com/source/usr.bin/procstat/procstat_bin.c?v=8-CURRENT - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) -{ - long pid; - char pathname[PATH_MAX]; - int error; - int mib[4]; - size_t size; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = pid; - - size = sizeof(pathname); - error = sysctl(mib, 4, pathname, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (size == 0 || strlen(pathname) == 0) { - if (psutil_pid_exists(pid) == 0) - return NoSuchProcess(); - else - strcpy(pathname, ""); - } - return Py_BuildValue("s", pathname); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) -{ - long pid; - PyObject *arglist = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // get the commandline, defined in arch/bsd/process_info.c - arglist = psutil_get_arg_list(pid); - - // psutil_get_arg_list() returns NULL only if psutil_cmd_args - // failed with ESRCH (no process with that PID) - if (NULL == arglist) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("N", arglist); -} - - -/* - * Return process parent pid from kinfo_proc as a Python integer. - */ -static PyObject * -psutil_proc_ppid(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.ki_ppid); -} - - -/* - * Return process status as a Python integer. - */ -static PyObject * -psutil_proc_status(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("i", (int)kp.ki_stat); -} - - -/* - * Return process real, effective and saved user ids from kinfo_proc - * as a Python tuple. - */ -static PyObject * -psutil_proc_uids(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("lll", - (long)kp.ki_ruid, - (long)kp.ki_uid, - (long)kp.ki_svuid); -} - - -/* - * Return process real, effective and saved group ids from kinfo_proc - * as a Python tuple. - */ -static PyObject * -psutil_proc_gids(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("lll", - (long)kp.ki_rgid, - (long)kp.ki_groups[0], - (long)kp.ki_svuid); -} - - -/* - * Return process real, effective and saved group ids from kinfo_proc - * as a Python tuple. - */ -static PyObject * -psutil_proc_tty_nr(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("i", kp.ki_tdev); -} - - -/* - * Return the number of context switches performed by process as a tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("(ll)", - kp.ki_rusage.ru_nvcsw, - kp.ki_rusage.ru_nivcsw); -} - - -/* - * Return number of threads used by process as a Python integer. - */ -static PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.ki_numthreads); -} - - -/* - * Retrieves all threads used by process returning a list of tuples - * including thread id, user time and system time. - * Thanks to Robert N. M. Watson: - * http://fxr.googlebit.com/source/usr.bin/procstat/ - * procstat_threads.c?v=8-CURRENT - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) -{ - long pid; - int mib[4]; - struct kinfo_proc *kip = NULL; - struct kinfo_proc *kipp = NULL; - int error; - unsigned int i; - size_t size; - PyObject *retList = PyList_New(0); - PyObject *pyTuple = NULL; - - if (retList == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - // we need to re-query for thread information, so don't use *kipp - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID | KERN_PROC_INC_THREAD; - mib[3] = pid; - - size = 0; - error = sysctl(mib, 4, NULL, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess(); - goto error; - } - - kip = malloc(size); - if (kip == NULL) { - PyErr_NoMemory(); - goto error; - } - - error = sysctl(mib, 4, kip, &size, NULL, 0); - if (error == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - if (size == 0) { - NoSuchProcess(); - goto error; - } - - for (i = 0; i < size / sizeof(*kipp); i++) { - kipp = &kip[i]; - pyTuple = Py_BuildValue("Idd", - kipp->ki_tid, - TV2DOUBLE(kipp->ki_rusage.ru_utime), - TV2DOUBLE(kipp->ki_rusage.ru_stime)); - if (pyTuple == NULL) - goto error; - if (PyList_Append(retList, pyTuple)) - goto error; - Py_DECREF(pyTuple); - } - free(kip); - return retList; - -error: - Py_XDECREF(pyTuple); - Py_DECREF(retList); - if (kip != NULL) - free(kip); - return NULL; -} - - -/* - * Return a Python tuple (user_time, kernel_time) - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) -{ - long pid; - double user_t, sys_t; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - // convert from microseconds to seconds - user_t = TV2DOUBLE(kp.ki_rusage.ru_utime); - sys_t = TV2DOUBLE(kp.ki_rusage.ru_stime); - return Py_BuildValue("(dd)", user_t, sys_t); -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with OSX - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) -{ - int mib[2]; - int ncpu; - size_t len; - - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); -} - - -/* - * Return an XML string from which we'll determine the number of - * physical CPU cores in the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) -{ - void *topology = NULL; - size_t size = 0; - PyObject *py_str; - - if (sysctlbyname("kern.sched.topology_spec", NULL, &size, NULL, 0)) - goto error; - - topology = malloc(size); - if (!topology) { - PyErr_NoMemory(); - return NULL; - } - - if (sysctlbyname("kern.sched.topology_spec", topology, &size, NULL, 0)) - goto error; - - py_str = Py_BuildValue("s", topology); - free(topology); - return py_str; - -error: - if (topology != NULL) - free(topology); - Py_RETURN_NONE; -} - - -/* - * Return a Python float indicating the process create time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_proc_create_time(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("d", TV2DOUBLE(kp.ki_start)); -} - - -/* - * Return a Python float indicating the process create time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - // there's apparently no way to determine bytes count, hence return -1. - return Py_BuildValue("(llll)", - kp.ki_rusage.ru_inblock, - kp.ki_rusage.ru_oublock, - -1, - -1); -} - - -/* - * Return extended memory info for a process as a Python tuple. - */ -static PyObject * -psutil_proc_memory_info(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("(lllll)", - ptoa(kp.ki_rssize), // rss - (long)kp.ki_size, // vms - ptoa(kp.ki_tsize), // text - ptoa(kp.ki_dsize), // data - ptoa(kp.ki_ssize)); // stack -} - - -/* - * Return virtual memory usage statistics. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) -{ - unsigned int total, active, inactive, wired, cached, free; - size_t size = sizeof(total); - struct vmtotal vm; - int mib[] = {CTL_VM, VM_METER}; - long pagesize = getpagesize(); -#if __FreeBSD_version > 702101 - long buffers; -#else - int buffers; -#endif - size_t buffers_size = sizeof(buffers); - - if (sysctlbyname("vm.stats.vm.v_page_count", &total, &size, NULL, 0)) - goto error; - if (sysctlbyname("vm.stats.vm.v_active_count", &active, &size, NULL, 0)) - goto error; - if (sysctlbyname("vm.stats.vm.v_inactive_count", - &inactive, &size, NULL, 0)) - goto error; - if (sysctlbyname("vm.stats.vm.v_wire_count", &wired, &size, NULL, 0)) - goto error; - if (sysctlbyname("vm.stats.vm.v_cache_count", &cached, &size, NULL, 0)) - goto error; - if (sysctlbyname("vm.stats.vm.v_free_count", &free, &size, NULL, 0)) - goto error; - if (sysctlbyname("vfs.bufspace", &buffers, &buffers_size, NULL, 0)) - goto error; - - size = sizeof(vm); - if (sysctl(mib, 2, &vm, &size, NULL, 0) != 0) - goto error; - - return Py_BuildValue("KKKKKKKK", - (unsigned long long) total * pagesize, - (unsigned long long) free * pagesize, - (unsigned long long) active * pagesize, - (unsigned long long) inactive * pagesize, - (unsigned long long) wired * pagesize, - (unsigned long long) cached * pagesize, - (unsigned long long) buffers, - (unsigned long long) (vm.t_vmshr + vm.t_rmshr) * pagesize // shared - ); - -error: - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -#ifndef _PATH_DEVNULL -#define _PATH_DEVNULL "/dev/null" -#endif - -/* - * Return swap memory stats (see 'swapinfo' cmdline tool) - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) -{ - kvm_t *kd; - struct kvm_swap kvmsw[1]; - unsigned int swapin, swapout, nodein, nodeout; - size_t size = sizeof(unsigned int); - - kd = kvm_open(NULL, _PATH_DEVNULL, NULL, O_RDONLY, "kvm_open failed"); - if (kd == NULL) { - PyErr_SetString(PyExc_RuntimeError, "kvm_open failed"); - return NULL; - } - - if (kvm_getswapinfo(kd, kvmsw, 1, 0) < 0) { - kvm_close(kd); - PyErr_SetString(PyExc_RuntimeError, "kvm_getswapinfo failed"); - return NULL; - } - - kvm_close(kd); - - if (sysctlbyname("vm.stats.vm.v_swapin", &swapin, &size, NULL, 0) == -1) - goto sbn_error; - if (sysctlbyname("vm.stats.vm.v_swapout", &swapout, &size, NULL, 0) == -1) - goto sbn_error; - if (sysctlbyname("vm.stats.vm.v_vnodein", &nodein, &size, NULL, 0) == -1) - goto sbn_error; - if (sysctlbyname("vm.stats.vm.v_vnodeout", &nodeout, &size, NULL, 0) == -1) - goto sbn_error; - - return Py_BuildValue("(iiiII)", - kvmsw[0].ksw_total, // total - kvmsw[0].ksw_used, // used - kvmsw[0].ksw_total - kvmsw[0].ksw_used, // free - swapin + swapout, // swap in - nodein + nodeout); // swap out - -sbn_error: - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) -{ - long cpu_time[CPUSTATES]; - size_t size; - - size = sizeof(cpu_time); - - if (sysctlbyname("kern.cp_time", &cpu_time, &size, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - return Py_BuildValue("(ddddd)", - (double)cpu_time[CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[CP_INTR] / CLOCKS_PER_SEC - ); -} - - -/* - * XXX - * These functions are available on FreeBSD 8 only. - * In the upper python layer we do various tricks to avoid crashing - * and/or to provide alternatives where possible. - */ - - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -/* - * Return files opened by process as a list of (path, fd) tuples. - * TODO: this is broken as it may report empty paths. 'procstat' - * utility has the same problem see: - * https://github.com/giampaolo/psutil/issues/595 - */ -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) -{ - long pid; - int i, cnt; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - struct kinfo_proc kipp; - PyObject *retList = PyList_New(0); - PyObject *tuple = NULL; - - if (retList == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_ad_or_nsp(pid); - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - if ((kif->kf_type == KF_TYPE_VNODE) && - (kif->kf_vnode_type == KF_VTYPE_VREG)) - { - tuple = Py_BuildValue("(si)", kif->kf_path, kif->kf_fd); - if (tuple == NULL) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - } - } - free(freep); - return retList; - -error: - Py_XDECREF(tuple); - Py_DECREF(retList); - if (freep != NULL) - free(freep); - return NULL; -} - - -/* - * Return files opened by process as a list of (path, fd) tuples - */ -static PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) -{ - long pid; - int cnt; - - struct kinfo_file *freep; - struct kinfo_proc kipp; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_kinfo_proc(pid, &kipp) == -1) - return NULL; - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_ad_or_nsp(pid); - return NULL; - } - free(freep); - - return Py_BuildValue("i", cnt); -} - - -/* - * Return process current working directory. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) -{ - long pid; - PyObject *path = NULL; - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - struct kinfo_proc kipp; - - int i, cnt; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kipp) == -1) - goto error; - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_ad_or_nsp(pid); - goto error; - } - - for (i = 0; i < cnt; i++) { - kif = &freep[i]; - if (kif->kf_fd == KF_FD_TYPE_CWD) { - path = Py_BuildValue("s", kif->kf_path); - if (!path) - goto error; - break; - } - } - /* - * For lower pids it seems we can't retrieve any information - * (lsof can't do that it either). Since this happens even - * as root we return an empty string instead of AccessDenied. - */ - if (path == NULL) - path = Py_BuildValue("s", ""); - free(freep); - return path; - -error: - Py_XDECREF(path); - if (freep != NULL) - free(freep); - return NULL; -} - - -// The tcplist fetching and walking is borrowed from netstat/inet.c. -static char * -psutil_fetch_tcplist(void) -{ - char *buf; - size_t len; - - for (;;) { - if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (sysctlbyname("net.inet.tcp.pcblist", buf, &len, NULL, 0) < 0) { - free(buf); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - return buf; - } -} - -static int -psutil_sockaddr_port(int family, struct sockaddr_storage *ss) -{ - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (sin->sin_port); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (sin6->sin6_port); - } -} - -static void * -psutil_sockaddr_addr(int family, struct sockaddr_storage *ss) -{ - struct sockaddr_in6 *sin6; - struct sockaddr_in *sin; - - if (family == AF_INET) { - sin = (struct sockaddr_in *)ss; - return (&sin->sin_addr); - } - else { - sin6 = (struct sockaddr_in6 *)ss; - return (&sin6->sin6_addr); - } -} - -static socklen_t -psutil_sockaddr_addrlen(int family) -{ - if (family == AF_INET) - return (sizeof(struct in_addr)); - else - return (sizeof(struct in6_addr)); -} - -static int -psutil_sockaddr_matches(int family, int port, void *pcb_addr, - struct sockaddr_storage *ss) -{ - if (psutil_sockaddr_port(family, ss) != port) - return (0); - return (memcmp(psutil_sockaddr_addr(family, ss), pcb_addr, - psutil_sockaddr_addrlen(family)) == 0); -} - -static struct tcpcb * -psutil_search_tcplist(char *buf, struct kinfo_file *kif) -{ - struct tcpcb *tp; - struct inpcb *inp; - struct xinpgen *xig, *oxig; - struct xsocket *so; - - oxig = xig = (struct xinpgen *)buf; - for (xig = (struct xinpgen *)((char *)xig + xig->xig_len); - xig->xig_len > sizeof(struct xinpgen); - xig = (struct xinpgen *)((char *)xig + xig->xig_len)) { - tp = &((struct xtcpcb *)xig)->xt_tp; - inp = &((struct xtcpcb *)xig)->xt_inp; - so = &((struct xtcpcb *)xig)->xt_socket; - - if (so->so_type != kif->kf_sock_type || - so->xso_family != kif->kf_sock_domain || - so->xso_protocol != kif->kf_sock_protocol) - continue; - - if (kif->kf_sock_domain == AF_INET) { - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_lport, &inp->inp_laddr, - &kif->kf_sa_local)) - continue; - if (!psutil_sockaddr_matches( - AF_INET, inp->inp_fport, &inp->inp_faddr, - &kif->kf_sa_peer)) - continue; - } else { - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_lport, &inp->in6p_laddr, - &kif->kf_sa_local)) - continue; - if (!psutil_sockaddr_matches( - AF_INET6, inp->inp_fport, &inp->in6p_faddr, - &kif->kf_sa_peer)) - continue; - } - - return (tp); - } - return NULL; -} - - -// a signaler for connections without an actual status -static int PSUTIL_CONN_NONE = 128; - -/* - * Return connections opened by process. - */ -static PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) -{ - long pid; - int i, cnt; - - struct kinfo_file *freep = NULL; - struct kinfo_file *kif; - char *tcplist = NULL; - struct tcpcb *tcp; - - PyObject *retList = PyList_New(0); - PyObject *tuple = NULL; - PyObject *laddr = NULL; - PyObject *raddr = NULL; - PyObject *af_filter = NULL; - PyObject *type_filter = NULL; - PyObject *_family = NULL; - PyObject *_type = NULL; - - if (retList == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) - goto error; - if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - freep = kinfo_getfile(pid, &cnt); - if (freep == NULL) { - psutil_raise_ad_or_nsp(pid); - goto error; - } - - tcplist = psutil_fetch_tcplist(); - if (tcplist == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < cnt; i++) { - int lport, rport, state; - char lip[200], rip[200]; - char path[PATH_MAX]; - int inseq; - tuple = NULL; - laddr = NULL; - raddr = NULL; - - kif = &freep[i]; - if (kif->kf_type == KF_TYPE_SOCKET) { - // apply filters - _family = PyLong_FromLong((long)kif->kf_sock_domain); - inseq = PySequence_Contains(af_filter, _family); - Py_DECREF(_family); - if (inseq == 0) - continue; - _type = PyLong_FromLong((long)kif->kf_sock_type); - inseq = PySequence_Contains(type_filter, _type); - Py_DECREF(_type); - if (inseq == 0) - continue; - // IPv4 / IPv6 socket - if ((kif->kf_sock_domain == AF_INET) || - (kif->kf_sock_domain == AF_INET6)) { - // fill status - state = PSUTIL_CONN_NONE; - if (kif->kf_sock_type == SOCK_STREAM) { - tcp = psutil_search_tcplist(tcplist, kif); - if (tcp != NULL) - state = (int)tcp->t_state; - } - - // build addr and port - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, - &kif->kf_sa_local), - lip, - sizeof(lip)); - inet_ntop( - kif->kf_sock_domain, - psutil_sockaddr_addr(kif->kf_sock_domain, - &kif->kf_sa_peer), - rip, - sizeof(rip)); - lport = htons(psutil_sockaddr_port(kif->kf_sock_domain, - &kif->kf_sa_local)); - rport = htons(psutil_sockaddr_port(kif->kf_sock_domain, - &kif->kf_sa_peer)); - - // construct python tuple/list - laddr = Py_BuildValue("(si)", lip, lport); - if (!laddr) - goto error; - if (rport != 0) - raddr = Py_BuildValue("(si)", rip, rport); - else - raddr = Py_BuildValue("()"); - if (!raddr) - goto error; - tuple = Py_BuildValue("(iiiNNi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - laddr, - raddr, - state); - if (!tuple) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - } - // UNIX socket - else if (kif->kf_sock_domain == AF_UNIX) { - struct sockaddr_un *sun; - - sun = (struct sockaddr_un *)&kif->kf_sa_local; - snprintf( - path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - - tuple = Py_BuildValue("(iiisOi)", - kif->kf_fd, - kif->kf_sock_domain, - kif->kf_sock_type, - path, - Py_None, - PSUTIL_CONN_NONE); - if (!tuple) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - Py_INCREF(Py_None); - } - } - } - free(freep); - free(tcplist); - return retList; - -error: - Py_XDECREF(tuple); - Py_XDECREF(laddr); - Py_XDECREF(raddr); - Py_DECREF(retList); - if (freep != NULL) - free(freep); - if (tcplist != NULL) - free(tcplist); - return NULL; -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) -{ - static int maxcpus; - int mib[2]; - int ncpu; - size_t len; - size_t size; - int i; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - // retrieve maxcpus value - size = sizeof(maxcpus); - if (sysctlbyname("kern.smp.maxcpus", &maxcpus, &size, NULL, 0) < 0) { - Py_DECREF(py_retlist); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - long cpu_time[maxcpus][CPUSTATES]; - - // retrieve the number of cpus - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // per-cpu info - size = sizeof(cpu_time); - if (sysctlbyname("kern.cp_times", &cpu_time, &size, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < ncpu; i++) { - py_cputime = Py_BuildValue( - "(ddddd)", - (double)cpu_time[i][CP_USER] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_NICE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_SYS] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_IDLE] / CLOCKS_PER_SEC, - (double)cpu_time[i][CP_INTR] / CLOCKS_PER_SEC); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - return NULL; -} - - -// remove spaces from string -void remove_spaces(char *str) { - char *p1 = str; - char *p2 = str; - do - while (*p2 == ' ') - p2++; - while ((*p1++ = *p2++)); -} - - -/* - * Return a list of tuples for every process memory maps. - * 'procstat' cmdline utility has been used as an example. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) -{ - long pid; - int ptrwidth; - int i, cnt; - char addr[1000]; - char perms[4]; - const char *path; - struct kinfo_proc kp; - struct kinfo_vmentry *freep = NULL; - struct kinfo_vmentry *kve; - ptrwidth = 2 * sizeof(void *); - PyObject *pytuple = NULL; - PyObject *retlist = PyList_New(0); - - if (retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (psutil_kinfo_proc(pid, &kp) == -1) - goto error; - - freep = kinfo_getvmmap(pid, &cnt); - if (freep == NULL) { - psutil_raise_ad_or_nsp(pid); - goto error; - } - for (i = 0; i < cnt; i++) { - pytuple = NULL; - kve = &freep[i]; - addr[0] = '\0'; - perms[0] = '\0'; - sprintf(addr, "%#*jx-%#*jx", ptrwidth, (uintmax_t)kve->kve_start, - ptrwidth, (uintmax_t)kve->kve_end); - remove_spaces(addr); - strlcat(perms, kve->kve_protection & KVME_PROT_READ ? "r" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_WRITE ? "w" : "-", - sizeof(perms)); - strlcat(perms, kve->kve_protection & KVME_PROT_EXEC ? "x" : "-", - sizeof(perms)); - - if (strlen(kve->kve_path) == 0) { - switch (kve->kve_type) { - case KVME_TYPE_NONE: - path = "[none]"; - break; - case KVME_TYPE_DEFAULT: - path = "[default]"; - break; - case KVME_TYPE_VNODE: - path = "[vnode]"; - break; - case KVME_TYPE_SWAP: - path = "[swap]"; - break; - case KVME_TYPE_DEVICE: - path = "[device]"; - break; - case KVME_TYPE_PHYS: - path = "[phys]"; - break; - case KVME_TYPE_DEAD: - path = "[dead]"; - break; - case KVME_TYPE_SG: - path = "[sg]"; - break; - case KVME_TYPE_UNKNOWN: - path = "[unknown]"; - break; - default: - path = "[?]"; - break; - } - } - else { - path = kve->kve_path; - } - - pytuple = Py_BuildValue("sssiiii", - addr, // "start-end" address - perms, // "rwx" permissions - path, // path - kve->kve_resident, // rss - kve->kve_private_resident, // private - kve->kve_ref_count, // ref count - kve->kve_shadow_count); // shadow count - if (!pytuple) - goto error; - if (PyList_Append(retlist, pytuple)) - goto error; - Py_DECREF(pytuple); - } - free(freep); - return retlist; - -error: - Py_XDECREF(pytuple); - Py_DECREF(retlist); - if (freep != NULL) - free(freep); - return NULL; -} -#endif - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) -{ - int num; - int i; - long len; - uint64_t flags; - char opts[200]; - struct statfs *fs = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS - num = getfsstat(NULL, 0, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS - num = getfsstat(fs, len, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - py_tuple = NULL; - opts[0] = 0; - flags = fs[i].f_flags; - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_SUIDDIR) - strlcat(opts, ",suiddir", sizeof(opts)); - if (flags & MNT_SOFTDEP) - strlcat(opts, ",softdep", sizeof(opts)); - if (flags & MNT_NOSYMFOLLOW) - strlcat(opts, ",nosymfollow", sizeof(opts)); - if (flags & MNT_GJOURNAL) - strlcat(opts, ",gjournal", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_ACLS) - strlcat(opts, ",acls", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_NOCLUSTERR) - strlcat(opts, ",noclusterr", sizeof(opts)); - if (flags & MNT_NOCLUSTERW) - strlcat(opts, ",noclusterw", sizeof(opts)); - if (flags & MNT_NFS4ACLS) - strlcat(opts, ",nfs4acls", sizeof(opts)); - - py_tuple = Py_BuildValue("(ssss)", - fs[i].f_mntfromname, // device - fs[i].f_mntonname, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) -{ - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - size_t len; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST; // operation - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - py_ifc_info = NULL; - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO) { - struct if_msghdr *if2m = (struct if_msghdr *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - // XXX: ignore usbus interfaces: - // http://lists.freebsd.org/pipermail/freebsd-current/ - // 2011-October/028752.html - // 'ifconfig -a' doesn't show them, nor do we. - if (strncmp(ifc_name, "usbus", 5) == 0) - continue; - - py_ifc_info = Py_BuildValue("(kkkkkkki)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, - 0); // dropout not supported - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) -{ - int i; - struct statinfo stats; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - if (devstat_checkversion(NULL) < 0) { - PyErr_Format(PyExc_RuntimeError, "devstat_checkversion() failed"); - goto error; - } - - stats.dinfo = (struct devinfo *)malloc(sizeof(struct devinfo)); - if (stats.dinfo == NULL) { - PyErr_NoMemory(); - goto error; - } - bzero(stats.dinfo, sizeof(struct devinfo)); - - if (devstat_getdevs(NULL, &stats) == -1) { - PyErr_Format(PyExc_RuntimeError, "devstat_getdevs() failed"); - goto error; - } - - for (i = 0; i < stats.dinfo->numdevs; i++) { - py_disk_info = NULL; - struct devstat current; - char disk_name[128]; - current = stats.dinfo->devices[i]; - snprintf(disk_name, sizeof(disk_name), "%s%d", - current.device_name, - current.unit_number); - - py_disk_info = Py_BuildValue( - "(KKKKLL)", - current.operations[DEVSTAT_READ], // no reads - current.operations[DEVSTAT_WRITE], // no writes - current.bytes[DEVSTAT_READ], // bytes read - current.bytes[DEVSTAT_WRITE], // bytes written - (long long)devstat_compute_etime( - ¤t.duration[DEVSTAT_READ], NULL), // r time - (long long)devstat_compute_etime( - ¤t.duration[DEVSTAT_WRITE], NULL)); // w time - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - - if (stats.dinfo->mem_ptr) - free(stats.dinfo->mem_ptr); - free(stats.dinfo); - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (stats.dinfo != NULL) - free(stats.dinfo); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) -{ - PyObject *ret_list = PyList_New(0); - PyObject *tuple = NULL; - - if (ret_list == NULL) - return NULL; - -#if __FreeBSD_version < 900000 - struct utmp ut; - FILE *fp; - - fp = fopen(_PATH_UTMP, "r"); - if (fp == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - while (fread(&ut, sizeof(ut), 1, fp) == 1) { - if (*ut.ut_name == '\0') - continue; - tuple = Py_BuildValue( - "(sssf)", - ut.ut_name, // username - ut.ut_line, // tty - ut.ut_host, // hostname - (float)ut.ut_time); // start time - if (!tuple) { - fclose(fp); - goto error; - } - if (PyList_Append(ret_list, tuple)) { - fclose(fp); - goto error; - } - Py_DECREF(tuple); - } - - fclose(fp); -#else - struct utmpx *utx; - - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - tuple = Py_BuildValue( - "(sssf)", - utx->ut_user, // username - utx->ut_line, // tty - utx->ut_host, // hostname - (float)utx->ut_tv.tv_sec // start time - ); - - if (!tuple) { - endutxent(); - goto error; - } - if (PyList_Append(ret_list, tuple)) { - endutxent(); - goto error; - } - Py_DECREF(tuple); - } - - endutxent(); -#endif - return ret_list; - -error: - Py_XDECREF(tuple); - Py_DECREF(ret_list); - return NULL; -} - - - -/* - * System-wide open connections. - */ - -#define HASHSIZE 1009 -static struct xfile *psutil_xfiles; -static int psutil_nxfiles; - -int -psutil_populate_xfiles() -{ - size_t len; - - if ((psutil_xfiles = malloc(len = sizeof *psutil_xfiles)) == NULL) { - PyErr_NoMemory(); - return 0; - } - while (sysctlbyname("kern.file", psutil_xfiles, &len, 0, 0) == -1) { - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - return 0; - } - len *= 2; - if ((psutil_xfiles = realloc(psutil_xfiles, len)) == NULL) { - PyErr_NoMemory(); - return 0; - } - } - if (len > 0 && psutil_xfiles->xf_size != sizeof *psutil_xfiles) { - PyErr_Format(PyExc_RuntimeError, "struct xfile size mismatch"); - return 0; - } - psutil_nxfiles = len / sizeof *psutil_xfiles; - return 1; -} - -int -psutil_get_pid_from_sock(int sock_hash) -{ - struct xfile *xf; - int hash, n; - for (xf = psutil_xfiles, n = 0; n < psutil_nxfiles; ++n, ++xf) { - if (xf->xf_data == NULL) - continue; - hash = (int)((uintptr_t)xf->xf_data % HASHSIZE); - if (sock_hash == hash) - return xf->xf_pid; - } - return -1; -} - - -// Reference: -// https://gitorious.org/freebsd/freebsd/source/ -// f1d6f4778d2044502209708bc167c05f9aa48615:usr.bin/sockstat/sockstat.c -int psutil_gather_inet(int proto, PyObject *py_retlist) -{ - struct xinpgen *xig, *exig; - struct xinpcb *xip; - struct xtcpcb *xtp; - struct inpcb *inp; - struct xsocket *so; - const char *varname = NULL; - size_t len, bufsize; - void *buf; - int hash; - int retry; - int type; - - PyObject *tuple = NULL; - PyObject *laddr = NULL; - PyObject *raddr = NULL; - - switch (proto) { - case IPPROTO_TCP: - varname = "net.inet.tcp.pcblist"; - type = SOCK_STREAM; - break; - case IPPROTO_UDP: - varname = "net.inet.udp.pcblist"; - type = SOCK_DGRAM; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) - continue; // XXX - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xig = (struct xinpgen *)buf; - exig = (struct xinpgen *)(void *)((char *)buf + len - sizeof *exig); - if (xig->xig_len != sizeof *xig || exig->xig_len != sizeof *exig) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xig->xig_gen != exig->xig_gen && retry--); - - - for (;;) { - int lport, rport, pid, status, family; - - xig = (struct xinpgen *)(void *)((char *)xig + xig->xig_len); - if (xig >= exig) - break; - - switch (proto) { - case IPPROTO_TCP: - xtp = (struct xtcpcb *)xig; - if (xtp->xt_len != sizeof *xtp) { - PyErr_Format(PyExc_RuntimeError, - "struct xtcpcb size mismatch"); - goto error; - } - inp = &xtp->xt_inp; - so = &xtp->xt_socket; - status = xtp->xt_tp.t_state; - break; - case IPPROTO_UDP: - xip = (struct xinpcb *)xig; - if (xip->xi_len != sizeof *xip) { - PyErr_Format(PyExc_RuntimeError, - "struct xinpcb size mismatch"); - goto error; - } - inp = &xip->xi_inp; - so = &xip->xi_socket; - status = PSUTIL_CONN_NONE; - break; - default: - PyErr_Format(PyExc_RuntimeError, "invalid proto"); - goto error; - } - - char lip[200], rip[200]; - - hash = (int)((uintptr_t)so->xso_so % HASHSIZE); - pid = psutil_get_pid_from_sock(hash); - if (pid < 0) - continue; - lport = ntohs(inp->inp_lport); - rport = ntohs(inp->inp_fport); - - if (inp->inp_vflag & INP_IPV4) { - family = AF_INET; - inet_ntop(AF_INET, &inp->inp_laddr.s_addr, lip, sizeof(lip)); - inet_ntop(AF_INET, &inp->inp_faddr.s_addr, rip, sizeof(rip)); - } - else if (inp->inp_vflag & INP_IPV6) { - family = AF_INET6; - inet_ntop(AF_INET6, &inp->in6p_laddr.s6_addr, lip, sizeof(lip)); - inet_ntop(AF_INET6, &inp->in6p_faddr.s6_addr, rip, sizeof(rip)); - } - - // construct python tuple/list - laddr = Py_BuildValue("(si)", lip, lport); - if (!laddr) - goto error; - if (rport != 0) - raddr = Py_BuildValue("(si)", rip, rport); - else - raddr = Py_BuildValue("()"); - if (!raddr) - goto error; - tuple = Py_BuildValue("(iiiNNii)", -1, family, type, laddr, raddr, - status, pid); - if (!tuple) - goto error; - if (PyList_Append(py_retlist, tuple)) - goto error; - Py_DECREF(tuple); - } - - free(buf); - return 1; - -error: - Py_XDECREF(tuple); - Py_XDECREF(laddr); - Py_XDECREF(raddr); - free(buf); - return 0; -} - - -int psutil_gather_unix(int proto, PyObject *py_retlist) -{ - struct xunpgen *xug, *exug; - struct xunpcb *xup; - const char *varname = NULL; - const char *protoname = NULL; - size_t len; - size_t bufsize; - void *buf; - int hash; - int retry; - int pid; - struct sockaddr_un *sun; - char path[PATH_MAX]; - - PyObject *tuple = NULL; - PyObject *laddr = NULL; - PyObject *raddr = NULL; - - switch (proto) { - case SOCK_STREAM: - varname = "net.local.stream.pcblist"; - protoname = "stream"; - break; - case SOCK_DGRAM: - varname = "net.local.dgram.pcblist"; - protoname = "dgram"; - break; - } - - buf = NULL; - bufsize = 8192; - retry = 5; - - do { - for (;;) { - buf = realloc(buf, bufsize); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - len = bufsize; - if (sysctlbyname(varname, buf, &len, NULL, 0) == 0) - break; - if (errno != ENOMEM) { - PyErr_SetFromErrno(0); - goto error; - } - bufsize *= 2; - } - xug = (struct xunpgen *)buf; - exug = (struct xunpgen *)(void *) - ((char *)buf + len - sizeof *exug); - if (xug->xug_len != sizeof *xug || exug->xug_len != sizeof *exug) { - PyErr_Format(PyExc_RuntimeError, "struct xinpgen size mismatch"); - goto error; - } - } while (xug->xug_gen != exug->xug_gen && retry--); - - for (;;) { - xug = (struct xunpgen *)(void *)((char *)xug + xug->xug_len); - if (xug >= exug) - break; - xup = (struct xunpcb *)xug; - if (xup->xu_len != sizeof *xup) - goto error; - - hash = (int)((uintptr_t) xup->xu_socket.xso_so % HASHSIZE); - pid = psutil_get_pid_from_sock(hash); - if (pid < 0) - continue; - - sun = (struct sockaddr_un *)&xup->xu_addr; - snprintf(path, sizeof(path), "%.*s", - (int)(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))), - sun->sun_path); - - tuple = Py_BuildValue("(iiisOii)", -1, AF_UNIX, proto, path, Py_None, - PSUTIL_CONN_NONE, pid); - if (!tuple) - goto error; - if (PyList_Append(py_retlist, tuple)) - goto error; - Py_DECREF(tuple); - Py_INCREF(Py_None); - } - - free(buf); - return 1; - -error: - Py_XDECREF(tuple); - Py_XDECREF(laddr); - Py_XDECREF(raddr); - free(buf); - return 0; -} - - -/* - * Return system-wide open connections. - */ -static PyObject* -psutil_net_connections(PyObject* self, PyObject* args) -{ - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (psutil_populate_xfiles() != 1) - goto error; - if (psutil_gather_inet(IPPROTO_TCP, py_retlist) == 0) - goto error; - if (psutil_gather_inet(IPPROTO_UDP, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_STREAM, py_retlist) == 0) - goto error; - if (psutil_gather_unix(SOCK_DGRAM, py_retlist) == 0) - goto error; - - free(psutil_xfiles); - return py_retlist; - -error: - Py_DECREF(py_retlist); - free(psutil_xfiles); - return NULL; -} - - -/* - * Get process CPU affinity. - * Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - */ -static PyObject* -psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args) -{ - long pid; - int ret; - int i; - cpuset_t mask; - PyObject* py_retlist; - PyObject* py_cpu_num; - - if (!PyArg_ParseTuple(args, "i", &pid)) - return NULL; - ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(mask), &mask); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - py_retlist = PyList_New(0); - if (py_retlist == NULL) - return NULL; - - for (i = 0; i < CPU_SETSIZE; i++) { - if (CPU_ISSET(i, &mask)) { - py_cpu_num = Py_BuildValue("i", i); - if (py_cpu_num == NULL) - goto error; - if (PyList_Append(py_retlist, py_cpu_num)) - goto error; - } - } - - return py_retlist; - -error: - Py_XDECREF(py_cpu_num); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * Set process CPU affinity. - * Reference: http://sources.freebsd.org/RELENG_9/src/usr.bin/cpuset/cpuset.c - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) -{ - long pid; - int i; - int seq_len; - int ret; - cpuset_t cpu_set; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) - return NULL; - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - return NULL; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - - // calculate the mask - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if (value == -1 && PyErr_Occurred()) - goto error; - CPU_SET(value, &cpu_set); - } - - // set affinity - ret = cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, pid, - sizeof(cpu_set), &cpu_set); - if (ret != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- per-process functions - - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Return connections opened by process"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return process pathname executable"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_ppid", psutil_proc_ppid, METH_VARARGS, - "Return process ppid as an integer"}, - {"proc_uids", psutil_proc_uids, METH_VARARGS, - "Return process real effective and saved user ids as a Python tuple"}, - {"proc_gids", psutil_proc_gids, METH_VARARGS, - "Return process real effective and saved group ids as a Python tuple"}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return tuple of user/kern time for the given PID"}, - {"proc_create_time", psutil_proc_create_time, METH_VARARGS, - "Return a float indicating the process create time expressed in " - "seconds since the epoch"}, - {"proc_memory_info", psutil_proc_memory_info, METH_VARARGS, - "Return extended memory info for a process as a Python tuple."}, - {"proc_num_threads", psutil_proc_num_threads, METH_VARARGS, - "Return number of threads used by process"}, - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Return the number of context switches performed by process"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads"}, - {"proc_status", psutil_proc_status, METH_VARARGS, - "Return process status as an integer"}, - {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, - "Return process IO counters"}, - {"proc_tty_nr", psutil_proc_tty_nr, METH_VARARGS, - "Return process tty (terminal) number"}, - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of (path, fd) tuples"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of tuples for every process's memory map"}, - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of file descriptors opened by this process"}, -#endif - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return an XML string to determine the number physical CPUs."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory usage statistics"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return swap mem stats"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, -#endif - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O information"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide open connections."}, - - {NULL, NULL, 0, NULL} -}; - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_bsd_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_bsd_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef - moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_bsd", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_bsd_traverse, - psutil_bsd_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_bsd(void) - -#else -#define INITERROR return - -void init_psutil_bsd(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_bsd", PsutilMethods); -#endif - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - // process status constants - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - PyModule_AddIntConstant(module, "SSLEEP", SSLEEP); - PyModule_AddIntConstant(module, "SRUN", SRUN); - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SWAIT", SWAIT); - PyModule_AddIntConstant(module, "SLOCK", SLOCK); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - // connection status constants - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_bsd.h b/python/psutil/psutil/_psutil_bsd.h deleted file mode 100644 index 803957dac..000000000 --- a/python/psutil/psutil/_psutil_bsd.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -// --- per-process functions - -static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args); -static PyObject* psutil_proc_connections(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args); -static PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -static PyObject* psutil_proc_gids(PyObject* self, PyObject* args); -static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -static PyObject* psutil_proc_name(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -static PyObject* psutil_proc_ppid(PyObject* self, PyObject* args); -static PyObject* psutil_proc_status(PyObject* self, PyObject* args); -static PyObject* psutil_proc_threads(PyObject* self, PyObject* args); -static PyObject* psutil_proc_tty_nr(PyObject* self, PyObject* args); -static PyObject* psutil_proc_uids(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); -#endif - -// --- system-related functions - -static PyObject* psutil_boot_time(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); -static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_pids(PyObject* self, PyObject* args); -static PyObject* psutil_swap_mem(PyObject* self, PyObject* args); -static PyObject* psutil_users(PyObject* self, PyObject* args); -static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); - -#if defined(__FreeBSD_version) && __FreeBSD_version >= 800000 -static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -#endif diff --git a/python/psutil/psutil/_psutil_common.c b/python/psutil/psutil/_psutil_common.c deleted file mode 100644 index 1c530d4df..000000000 --- a/python/psutil/psutil/_psutil_common.c +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Routines common to all platforms. - */ - -#include <Python.h> - - -/* - * Set OSError(errno=ESRCH, strerror="No such process") Python exception. - */ -PyObject * -NoSuchProcess(void) { - PyObject *exc; - char *msg = strerror(ESRCH); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", ESRCH, msg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} - - -/* - * Set OSError(errno=EACCES, strerror="Permission denied") Python exception. - */ -PyObject * -AccessDenied(void) { - PyObject *exc; - char *msg = strerror(EACCES); - exc = PyObject_CallFunction(PyExc_OSError, "(is)", EACCES, msg); - PyErr_SetObject(PyExc_OSError, exc); - Py_XDECREF(exc); - return NULL; -} diff --git a/python/psutil/psutil/_psutil_common.h b/python/psutil/psutil/_psutil_common.h deleted file mode 100644 index 43021a72d..000000000 --- a/python/psutil/psutil/_psutil_common.h +++ /dev/null @@ -1,10 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -PyObject* AccessDenied(void); -PyObject* NoSuchProcess(void); diff --git a/python/psutil/psutil/_psutil_linux.c b/python/psutil/psutil/_psutil_linux.c deleted file mode 100644 index a3bf5643c..000000000 --- a/python/psutil/psutil/_psutil_linux.c +++ /dev/null @@ -1,689 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Linux-specific functions. - */ - -#ifndef _GNU_SOURCE - #define _GNU_SOURCE 1 -#endif -#include <Python.h> -#include <errno.h> -#include <stdlib.h> -#include <mntent.h> -#include <features.h> -#include <utmp.h> -#include <sched.h> -#include <linux/version.h> -#include <sys/syscall.h> -#include <sys/sysinfo.h> -#include <sys/ioctl.h> -#include <sys/socket.h> -#include <linux/sockios.h> -#include <linux/if.h> -#include <linux/ethtool.h> - -#include "_psutil_linux.h" - -/* The minimum number of CPUs allocated in a cpu_set_t */ -static const int NCPUS_START = sizeof(unsigned long) * CHAR_BIT; - -// Linux >= 2.6.13 -#define PSUTIL_HAVE_IOPRIO defined(__NR_ioprio_get) && defined(__NR_ioprio_set) - -// Linux >= 2.6.36 (supposedly) and glibc >= 13 -#define PSUTIL_HAVE_PRLIMIT \ - (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36)) && \ - (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 13) && \ - defined(__NR_prlimit64) - -#if PSUTIL_HAVE_PRLIMIT - #define _FILE_OFFSET_BITS 64 - #include <time.h> - #include <sys/resource.h> -#endif - - -#if PSUTIL_HAVE_IOPRIO -enum { - IOPRIO_WHO_PROCESS = 1, -}; - -// May happen on old RedHat versions, see: -// https://github.com/giampaolo/psutil/issues/607 -#ifndef DUPLEX_UNKNOWN - #define DUPLEX_UNKNOWN 0xff -#endif - -static inline int -ioprio_get(int which, int who) -{ - return syscall(__NR_ioprio_get, which, who); -} - -static inline int -ioprio_set(int which, int who, int ioprio) -{ - return syscall(__NR_ioprio_set, which, who, ioprio); -} - -#define IOPRIO_CLASS_SHIFT 13 -#define IOPRIO_PRIO_MASK ((1UL << IOPRIO_CLASS_SHIFT) - 1) - -#define IOPRIO_PRIO_CLASS(mask) ((mask) >> IOPRIO_CLASS_SHIFT) -#define IOPRIO_PRIO_DATA(mask) ((mask) & IOPRIO_PRIO_MASK) -#define IOPRIO_PRIO_VALUE(class, data) (((class) << IOPRIO_CLASS_SHIFT) | data) - - -/* - * Return a (ioclass, iodata) Python tuple representing process I/O priority. - */ -static PyObject * -psutil_proc_ioprio_get(PyObject *self, PyObject *args) -{ - long pid; - int ioprio, ioclass, iodata; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - ioprio = ioprio_get(IOPRIO_WHO_PROCESS, pid); - if (ioprio == -1) - return PyErr_SetFromErrno(PyExc_OSError); - ioclass = IOPRIO_PRIO_CLASS(ioprio); - iodata = IOPRIO_PRIO_DATA(ioprio); - return Py_BuildValue("ii", ioclass, iodata); -} - - -/* - * A wrapper around ioprio_set(); sets process I/O priority. - * ioclass can be either IOPRIO_CLASS_RT, IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE - * or 0. iodata goes from 0 to 7 depending on ioclass specified. - */ -static PyObject * -psutil_proc_ioprio_set(PyObject *self, PyObject *args) -{ - long pid; - int ioprio, ioclass, iodata; - int retval; - - if (! PyArg_ParseTuple(args, "lii", &pid, &ioclass, &iodata)) - return NULL; - ioprio = IOPRIO_PRIO_VALUE(ioclass, iodata); - retval = ioprio_set(IOPRIO_WHO_PROCESS, pid, ioprio); - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} -#endif - - -#if PSUTIL_HAVE_PRLIMIT -/* - * A wrapper around prlimit(2); sets process resource limits. - * This can be used for both get and set, in which case extra - * 'soft' and 'hard' args must be provided. - */ -static PyObject * -psutil_linux_prlimit(PyObject *self, PyObject *args) -{ - long pid; - int ret, resource; - struct rlimit old, new; - struct rlimit *newp = NULL; - PyObject *soft = NULL; - PyObject *hard = NULL; - - if (! PyArg_ParseTuple(args, "li|OO", &pid, &resource, &soft, &hard)) - return NULL; - - // get - if (soft == NULL && hard == NULL) { - ret = prlimit(pid, resource, NULL, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); -#if defined(PSUTIL_HAVE_LONG_LONG) - if (sizeof(old.rlim_cur) > sizeof(long)) { - return Py_BuildValue("LL", - (PY_LONG_LONG)old.rlim_cur, - (PY_LONG_LONG)old.rlim_max); - } -#endif - return Py_BuildValue("ll", (long)old.rlim_cur, (long)old.rlim_max); - } - - // set - else { -#if defined(PSUTIL_HAVE_LARGEFILE_SUPPORT) - new.rlim_cur = PyLong_AsLongLong(soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLongLong(hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#else - new.rlim_cur = PyLong_AsLong(soft); - if (new.rlim_cur == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; - new.rlim_max = PyLong_AsLong(hard); - if (new.rlim_max == (rlim_t) - 1 && PyErr_Occurred()) - return NULL; -#endif - newp = &new; - ret = prlimit(pid, resource, newp, &old); - if (ret == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; - } -} -#endif - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) -{ - FILE *file = NULL; - struct mntent *entry; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - // MOUNTED constant comes from mntent.h and it's == '/etc/mtab' - Py_BEGIN_ALLOW_THREADS - file = setmntent(MOUNTED, "r"); - Py_END_ALLOW_THREADS - if ((file == 0) || (file == NULL)) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, MOUNTED); - goto error; - } - - while ((entry = getmntent(file))) { - if (entry == NULL) { - PyErr_Format(PyExc_RuntimeError, "getmntent() failed"); - goto error; - } - py_tuple = Py_BuildValue("(ssss)", - entry->mnt_fsname, // device - entry->mnt_dir, // mount point - entry->mnt_type, // fs type - entry->mnt_opts); // options - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - endmntent(file); - return py_retlist; - -error: - if (file != NULL) - endmntent(file); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - - -/* - * A wrapper around sysinfo(), return system memory usage statistics. - */ -static PyObject * -psutil_linux_sysinfo(PyObject *self, PyObject *args) -{ - struct sysinfo info; - - if (sysinfo(&info) != 0) - return PyErr_SetFromErrno(PyExc_OSError); - // note: boot time might also be determined from here - return Py_BuildValue( - "(KKKKKK)", - (unsigned long long)info.totalram * info.mem_unit, // total - (unsigned long long)info.freeram * info.mem_unit, // free - (unsigned long long)info.bufferram * info.mem_unit, // buffer - (unsigned long long)info.sharedram * info.mem_unit, // shared - (unsigned long long)info.totalswap * info.mem_unit, // swap tot - (unsigned long long)info.freeswap * info.mem_unit); // swap free -} - - -/* - * Return process CPU affinity as a Python list - * The dual implementation exists because of: - * https://github.com/giampaolo/psutil/issues/536 - */ - -#ifdef CPU_ALLOC - -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) -{ - int cpu, ncpus, count, cpucount_s; - long pid; - size_t setsize; - cpu_set_t *mask = NULL; - PyObject *res = NULL; - - if (!PyArg_ParseTuple(args, "i", &pid)) - return NULL; - ncpus = NCPUS_START; - while (1) { - setsize = CPU_ALLOC_SIZE(ncpus); - mask = CPU_ALLOC(ncpus); - if (mask == NULL) - return PyErr_NoMemory(); - if (sched_getaffinity(pid, setsize, mask) == 0) - break; - CPU_FREE(mask); - if (errno != EINVAL) - return PyErr_SetFromErrno(PyExc_OSError); - if (ncpus > INT_MAX / 2) { - PyErr_SetString(PyExc_OverflowError, "could not allocate " - "a large enough CPU set"); - return NULL; - } - ncpus = ncpus * 2; - } - - res = PyList_New(0); - if (res == NULL) - goto error; - - cpucount_s = CPU_COUNT_S(setsize, mask); - for (cpu = 0, count = cpucount_s; count; cpu++) { - if (CPU_ISSET_S(cpu, setsize, mask)) { -#if PY_MAJOR_VERSION >= 3 - PyObject *cpu_num = PyLong_FromLong(cpu); -#else - PyObject *cpu_num = PyInt_FromLong(cpu); -#endif - if (cpu_num == NULL) - goto error; - if (PyList_Append(res, cpu_num)) { - Py_DECREF(cpu_num); - goto error; - } - Py_DECREF(cpu_num); - --count; - } - } - CPU_FREE(mask); - return res; - -error: - if (mask) - CPU_FREE(mask); - Py_XDECREF(res); - return NULL; -} -#else - - -/* - * Alternative implementation in case CPU_ALLOC is not defined. - */ -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) -{ - cpu_set_t cpuset; - unsigned int len = sizeof(cpu_set_t); - long pid; - int i; - PyObject* py_retlist = NULL; - PyObject *py_cpu_num = NULL; - - if (!PyArg_ParseTuple(args, "i", &pid)) - return NULL; - CPU_ZERO(&cpuset); - if (sched_getaffinity(pid, len, &cpuset) < 0) - return PyErr_SetFromErrno(PyExc_OSError); - - py_retlist = PyList_New(0); - if (py_retlist == NULL) - goto error; - for (i = 0; i < CPU_SETSIZE; ++i) { - if (CPU_ISSET(i, &cpuset)) { - py_cpu_num = Py_BuildValue("i", i); - if (py_cpu_num == NULL) - goto error; - if (PyList_Append(py_retlist, py_cpu_num)) - goto error; - Py_DECREF(py_cpu_num); - } - } - - return py_retlist; - -error: - Py_XDECREF(py_cpu_num); - Py_DECREF(py_retlist); - return NULL; -} -#endif - -/* - * Set process CPU affinity; expects a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) -{ - cpu_set_t cpu_set; - size_t len; - long pid; - int i, seq_len; - PyObject *py_cpu_set; - PyObject *py_cpu_seq = NULL; - - if (!PyArg_ParseTuple(args, "lO", &pid, &py_cpu_set)) - return NULL; - - if (!PySequence_Check(py_cpu_set)) { - PyErr_Format(PyExc_TypeError, "sequence argument expected, got %s", - Py_TYPE(py_cpu_set)->tp_name); - goto error; - } - - py_cpu_seq = PySequence_Fast(py_cpu_set, "expected a sequence or integer"); - if (!py_cpu_seq) - goto error; - seq_len = PySequence_Fast_GET_SIZE(py_cpu_seq); - CPU_ZERO(&cpu_set); - for (i = 0; i < seq_len; i++) { - PyObject *item = PySequence_Fast_GET_ITEM(py_cpu_seq, i); -#if PY_MAJOR_VERSION >= 3 - long value = PyLong_AsLong(item); -#else - long value = PyInt_AsLong(item); -#endif - if (value == -1 && PyErr_Occurred()) - goto error; - CPU_SET(value, &cpu_set); - } - - len = sizeof(cpu_set); - if (sched_setaffinity(pid, len, &cpu_set)) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - Py_DECREF(py_cpu_seq); - Py_RETURN_NONE; - -error: - if (py_cpu_seq != NULL) - Py_DECREF(py_cpu_seq); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) -{ - PyObject *ret_list = PyList_New(0); - PyObject *tuple = NULL; - PyObject *user_proc = NULL; - struct utmp *ut; - - if (ret_list == NULL) - return NULL; - setutent(); - while (NULL != (ut = getutent())) { - tuple = NULL; - user_proc = NULL; - if (ut->ut_type == USER_PROCESS) - user_proc = Py_True; - else - user_proc = Py_False; - tuple = Py_BuildValue( - "(sssfO)", - ut->ut_user, // username - ut->ut_line, // tty - ut->ut_host, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - user_proc // (bool) user process - ); - if (! tuple) - goto error; - if (PyList_Append(ret_list, tuple)) - goto error; - Py_DECREF(tuple); - } - endutent(); - return ret_list; - -error: - Py_XDECREF(tuple); - Py_XDECREF(user_proc); - Py_DECREF(ret_list); - endutent(); - return NULL; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) -{ - char *nic_name; - int sock = 0; - int ret; - int duplex; - int speed; - int mtu; - struct ifreq ifr; - struct ethtool_cmd ethcmd; - PyObject *py_is_up = NULL; - PyObject *py_ret = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // is up? - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - if ((ifr.ifr_flags & IFF_UP) != 0) - py_is_up = Py_True; - else - py_is_up = Py_False; - Py_INCREF(py_is_up); - - // MTU - ret = ioctl(sock, SIOCGIFMTU, &ifr); - if (ret == -1) - goto error; - mtu = ifr.ifr_mtu; - - // duplex and speed - memset(ðcmd, 0, sizeof ethcmd); - ethcmd.cmd = ETHTOOL_GSET; - ifr.ifr_data = (caddr_t)ðcmd; - ret = ioctl(sock, SIOCETHTOOL, &ifr); - - if (ret != -1) { - duplex = ethcmd.duplex; - speed = ethcmd.speed; - } - else { - if (errno == EOPNOTSUPP) { - // we typically get here in case of wi-fi cards - duplex = DUPLEX_UNKNOWN; - speed = 0; - } - else { - goto error; - } - } - - close(sock); - py_ret = Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu); - if (!py_ret) - goto error; - Py_DECREF(py_is_up); - return py_ret; - -error: - Py_XDECREF(py_is_up); - if (sock != 0) - close(sock); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * Define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- per-process functions - -#if PSUTIL_HAVE_IOPRIO - {"proc_ioprio_get", psutil_proc_ioprio_get, METH_VARARGS, - "Get process I/O priority"}, - {"proc_ioprio_set", psutil_proc_ioprio_set, METH_VARARGS, - "Set process I/O priority"}, -#endif - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a Python long (the bitmask)."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity; expects a bitmask."}, - - // --- system related functions - - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk mounted partitions as a list of tuples including " - "device, mount point and filesystem type"}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats (isup, duplex, speed, mtu)"}, - - // --- linux specific - - {"linux_sysinfo", psutil_linux_sysinfo, METH_VARARGS, - "A wrapper around sysinfo(), return system memory usage statistics"}, -#if PSUTIL_HAVE_PRLIMIT - {"linux_prlimit", psutil_linux_prlimit, METH_VARARGS, - "Get or set process resource limits."}, -#endif - - - {NULL, NULL, 0, NULL} -}; - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_linux_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_linux_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef - moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_linux", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_linux_traverse, - psutil_linux_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_linux(void) - -#else -#define INITERROR return - -void init_psutil_linux(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_linux", PsutilMethods); -#endif - - - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); -#if PSUTIL_HAVE_PRLIMIT - PyModule_AddIntConstant(module, "RLIM_INFINITY", RLIM_INFINITY); - PyModule_AddIntConstant(module, "RLIMIT_AS", RLIMIT_AS); - PyModule_AddIntConstant(module, "RLIMIT_CORE", RLIMIT_CORE); - PyModule_AddIntConstant(module, "RLIMIT_CPU", RLIMIT_CPU); - PyModule_AddIntConstant(module, "RLIMIT_DATA", RLIMIT_DATA); - PyModule_AddIntConstant(module, "RLIMIT_FSIZE", RLIMIT_FSIZE); - PyModule_AddIntConstant(module, "RLIMIT_LOCKS", RLIMIT_LOCKS); - PyModule_AddIntConstant(module, "RLIMIT_MEMLOCK", RLIMIT_MEMLOCK); - PyModule_AddIntConstant(module, "RLIMIT_NOFILE", RLIMIT_NOFILE); - PyModule_AddIntConstant(module, "RLIMIT_NPROC", RLIMIT_NPROC); - PyModule_AddIntConstant(module, "RLIMIT_RSS", RLIMIT_RSS); - PyModule_AddIntConstant(module, "RLIMIT_STACK", RLIMIT_STACK); -#ifdef RLIMIT_MSGQUEUE - PyModule_AddIntConstant(module, "RLIMIT_MSGQUEUE", RLIMIT_MSGQUEUE); -#endif -#ifdef RLIMIT_NICE - PyModule_AddIntConstant(module, "RLIMIT_NICE", RLIMIT_NICE); -#endif -#ifdef RLIMIT_RTPRIO - PyModule_AddIntConstant(module, "RLIMIT_RTPRIO", RLIMIT_RTPRIO); -#endif -#ifdef RLIMIT_RTTIME - PyModule_AddIntConstant(module, "RLIMIT_RTTIME", RLIMIT_RTTIME); -#endif -#ifdef RLIMIT_SIGPENDING - PyModule_AddIntConstant(module, "RLIMIT_SIGPENDING", RLIMIT_SIGPENDING); -#endif -#endif - PyModule_AddIntConstant(module, "DUPLEX_HALF", DUPLEX_HALF); - PyModule_AddIntConstant(module, "DUPLEX_FULL", DUPLEX_FULL); - PyModule_AddIntConstant(module, "DUPLEX_UNKNOWN", DUPLEX_UNKNOWN); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_linux.h b/python/psutil/psutil/_psutil_linux.h deleted file mode 100644 index ec6a33871..000000000 --- a/python/psutil/psutil/_psutil_linux.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -// process - -static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); -static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_ioprio_get(PyObject* self, PyObject* args); - -// system - -static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); -static PyObject* psutil_linux_sysinfo(PyObject* self, PyObject* args); -static PyObject* psutil_users(PyObject* self, PyObject* args); -static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args); diff --git a/python/psutil/psutil/_psutil_osx.c b/python/psutil/psutil/_psutil_osx.c deleted file mode 100644 index 3ebf8ff27..000000000 --- a/python/psutil/psutil/_psutil_osx.c +++ /dev/null @@ -1,1808 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * OS X platform-specific module methods for _psutil_osx - */ - -#include <Python.h> -#include <assert.h> -#include <errno.h> -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <utmpx.h> -#include <sys/sysctl.h> -#include <sys/vmmeter.h> -#include <libproc.h> -#include <sys/proc_info.h> -#include <netinet/tcp_fsm.h> -#include <arpa/inet.h> -#include <net/if_dl.h> -#include <pwd.h> - -#include <mach/mach.h> -#include <mach/task.h> -#include <mach/mach_init.h> -#include <mach/host_info.h> -#include <mach/mach_host.h> -#include <mach/mach_traps.h> -#include <mach/mach_vm.h> -#include <mach/shared_region.h> - -#include <mach-o/loader.h> - -#include <CoreFoundation/CoreFoundation.h> -#include <IOKit/IOKitLib.h> -#include <IOKit/storage/IOBlockStorageDriver.h> -#include <IOKit/storage/IOMedia.h> -#include <IOKit/IOBSD.h> - -#include "_psutil_osx.h" -#include "_psutil_common.h" -#include "arch/osx/process_info.h" - - -/* - * A wrapper around host_statistics() invoked with HOST_VM_INFO. - */ -int -psutil_sys_vminfo(vm_statistics_data_t *vmstat) -{ - kern_return_t ret; - mach_msg_type_number_t count = sizeof(*vmstat) / sizeof(integer_t); - mach_port_t mport = mach_host_self(); - - ret = host_statistics(mport, HOST_VM_INFO, (host_info_t)vmstat, &count); - if (ret != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, - "host_statistics() failed: %s", mach_error_string(ret)); - return 0; - } - mach_port_deallocate(mach_task_self(), mport); - return 1; -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) -{ - kinfo_proc *proclist = NULL; - kinfo_proc *orig_address = NULL; - size_t num_processes; - size_t idx; - PyObject *pid = NULL; - PyObject *retlist = PyList_New(0); - - if (retlist == NULL) - return NULL; - - if (psutil_get_proc_list(&proclist, &num_processes) != 0) { - PyErr_SetString(PyExc_RuntimeError, - "failed to retrieve process list."); - goto error; - } - - if (num_processes > 0) { - // save the address of proclist so we can free it later - orig_address = proclist; - for (idx = 0; idx < num_processes; idx++) { - pid = Py_BuildValue("i", proclist->kp_proc.p_pid); - if (!pid) - goto error; - if (PyList_Append(retlist, pid)) - goto error; - Py_DECREF(pid); - proclist++; - } - free(orig_address); - } - return retlist; - -error: - Py_XDECREF(pid); - Py_DECREF(retlist); - if (orig_address != NULL) - free(orig_address); - return NULL; -} - - -/* - * Return process name from kinfo_proc as a Python string. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("s", kp.kp_proc.p_comm); -} - - -/* - * Return process current working directory. - */ -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) -{ - long pid; - struct proc_vnodepathinfo pathinfo; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - if (! psutil_proc_pidinfo(pid, PROC_PIDVNODEPATHINFO, &pathinfo, - sizeof(pathinfo))) - { - return NULL; - } - return Py_BuildValue("s", pathinfo.pvi_cdir.vip_path); -} - - -/* - * Return path of the process executable. - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) -{ - long pid; - char buf[PATH_MAX]; - int ret; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - ret = proc_pidpath(pid, &buf, sizeof(buf)); - if (ret == 0) { - if (! psutil_pid_exists(pid)) - return NoSuchProcess(); - else - return AccessDenied(); - } - return Py_BuildValue("s", buf); -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) -{ - long pid; - PyObject *arglist = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // get the commandline, defined in arch/osx/process_info.c - arglist = psutil_get_arg_list(pid); - return arglist; -} - - -/* - * Return process parent pid from kinfo_proc as a Python integer. - */ -static PyObject * -psutil_proc_ppid(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("l", (long)kp.kp_eproc.e_ppid); -} - - -/* - * Return process real uid from kinfo_proc as a Python integer. - */ -static PyObject * -psutil_proc_uids(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("lll", - (long)kp.kp_eproc.e_pcred.p_ruid, - (long)kp.kp_eproc.e_ucred.cr_uid, - (long)kp.kp_eproc.e_pcred.p_svuid); -} - - -/* - * Return process real group id from ki_comm as a Python integer. - */ -static PyObject * -psutil_proc_gids(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("lll", - (long)kp.kp_eproc.e_pcred.p_rgid, - (long)kp.kp_eproc.e_ucred.cr_groups[0], - (long)kp.kp_eproc.e_pcred.p_svgid); -} - - -/* - * Return process controlling terminal number as an integer. - */ -static PyObject * -psutil_proc_tty_nr(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("i", kp.kp_eproc.e_tdev); -} - - -/* - * Return a list of tuples for every process memory maps. - * 'procstat' cmdline utility has been used as an example. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) -{ - char buf[PATH_MAX]; - char addr_str[34]; - char perms[8]; - int pagesize = getpagesize(); - long pid; - kern_return_t err = KERN_SUCCESS; - mach_port_t task = MACH_PORT_NULL; - uint32_t depth = 1; - vm_address_t address = 0; - vm_size_t size = 0; - - PyObject *py_tuple = NULL; - PyObject *py_list = PyList_New(0); - - if (py_list == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - err = task_for_pid(mach_task_self(), pid, &task); - - if (err != KERN_SUCCESS) { - if (! psutil_pid_exists(pid)) { - NoSuchProcess(); - } - else { - // pid exists, so return AccessDenied error since task_for_pid() - // failed - AccessDenied(); - } - goto error; - } - - while (1) { - py_tuple = NULL; - struct vm_region_submap_info_64 info; - mach_msg_type_number_t count = VM_REGION_SUBMAP_INFO_COUNT_64; - - err = vm_region_recurse_64(task, &address, &size, &depth, - (vm_region_info_64_t)&info, &count); - if (err == KERN_INVALID_ADDRESS) - break; - if (info.is_submap) { - depth++; - } - else { - // Free/Reset the char[]s to avoid weird paths - memset(buf, 0, sizeof(buf)); - memset(addr_str, 0, sizeof(addr_str)); - memset(perms, 0, sizeof(perms)); - - sprintf(addr_str, "%016lx-%016lx", address, address + size); - sprintf(perms, "%c%c%c/%c%c%c", - (info.protection & VM_PROT_READ) ? 'r' : '-', - (info.protection & VM_PROT_WRITE) ? 'w' : '-', - (info.protection & VM_PROT_EXECUTE) ? 'x' : '-', - (info.max_protection & VM_PROT_READ) ? 'r' : '-', - (info.max_protection & VM_PROT_WRITE) ? 'w' : '-', - (info.max_protection & VM_PROT_EXECUTE) ? 'x' : '-'); - - err = proc_regionfilename(pid, address, buf, sizeof(buf)); - - if (info.share_mode == SM_COW && info.ref_count == 1) { - // Treat single reference SM_COW as SM_PRIVATE - info.share_mode = SM_PRIVATE; - } - - if (strlen(buf) == 0) { - switch (info.share_mode) { - // case SM_LARGE_PAGE: - // Treat SM_LARGE_PAGE the same as SM_PRIVATE - // since they are not shareable and are wired. - case SM_COW: - strcpy(buf, "[cow]"); - break; - case SM_PRIVATE: - strcpy(buf, "[prv]"); - break; - case SM_EMPTY: - strcpy(buf, "[nul]"); - break; - case SM_SHARED: - case SM_TRUESHARED: - strcpy(buf, "[shm]"); - break; - case SM_PRIVATE_ALIASED: - strcpy(buf, "[ali]"); - break; - case SM_SHARED_ALIASED: - strcpy(buf, "[s/a]"); - break; - default: - strcpy(buf, "[???]"); - } - } - - py_tuple = Py_BuildValue( - "sssIIIIIH", - addr_str, // "start-end"address - perms, // "rwx" permissions - buf, // path - info.pages_resident * pagesize, // rss - info.pages_shared_now_private * pagesize, // private - info.pages_swapped_out * pagesize, // swapped - info.pages_dirtied * pagesize, // dirtied - info.ref_count, // ref count - info.shadow_depth // shadow depth - ); - if (!py_tuple) - goto error; - if (PyList_Append(py_list, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - - // increment address for the next map/file - address += size; - } - - if (task != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), task); - - return py_list; - -error: - if (task != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), task); - Py_XDECREF(py_tuple); - Py_DECREF(py_list); - return NULL; -} - - -/* - * Return the number of logical CPUs in the system. - * XXX this could be shared with BSD. - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) -{ - int mib[2]; - int ncpu; - size_t len; - mib[0] = CTL_HW; - mib[1] = HW_NCPU; - len = sizeof(ncpu); - - if (sysctl(mib, 2, &ncpu, &len, NULL, 0) == -1) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", ncpu); -} - - -/* - * Return the number of physical CPUs in the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) -{ - int num; - size_t size = sizeof(int); - - if (sysctlbyname("hw.physicalcpu", &num, &size, NULL, 0)) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("i", num); -} - - -#define TV2DOUBLE(t) ((t).tv_sec + (t).tv_usec / 1000000.0) - -/* - * Return a Python tuple (user_time, kernel_time) - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) -{ - long pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) - return NULL; - return Py_BuildValue("(dd)", - (float)pti.pti_total_user / 1000000000.0, - (float)pti.pti_total_system / 1000000000.0); -} - - -/* - * Return a Python float indicating the process create time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_proc_create_time(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("d", TV2DOUBLE(kp.kp_proc.p_starttime)); -} - - -/* - * Return extended memory info about a process. - */ -static PyObject * -psutil_proc_memory_info(PyObject *self, PyObject *args) -{ - long pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) - return NULL; - // Note: determining other memory stats on OSX is a mess: - // http://www.opensource.apple.com/source/top/top-67/libtop.c?txt - // I just give up... - // struct proc_regioninfo pri; - // psutil_proc_pidinfo(pid, PROC_PIDREGIONINFO, &pri, sizeof(pri)) - return Py_BuildValue( - "(KKkk)", - pti.pti_resident_size, // resident memory size (rss) - pti.pti_virtual_size, // virtual memory size (vms) - pti.pti_faults, // number of page faults (pages) - pti.pti_pageins // number of actual pageins (pages) - ); -} - - -/* - * Return number of threads used by process as a Python integer. - */ -static PyObject * -psutil_proc_num_threads(PyObject *self, PyObject *args) -{ - long pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) - return NULL; - return Py_BuildValue("k", pti.pti_threadnum); -} - - -/* - * Return the number of context switches performed by process. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) -{ - long pid; - struct proc_taskinfo pti; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_pidinfo(pid, PROC_PIDTASKINFO, &pti, sizeof(pti))) - return NULL; - // unvoluntary value seems not to be available; - // pti.pti_csw probably refers to the sum of the two (getrusage() - // numbers seems to confirm this theory). - return Py_BuildValue("ki", pti.pti_csw, 0); -} - - -/* - * Return system virtual memory stats - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) -{ - - int mib[2]; - uint64_t total; - size_t len = sizeof(total); - vm_statistics_data_t vm; - int pagesize = getpagesize(); - // physical mem - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - - if (sysctl(mib, 2, &total, &len, NULL, 0)) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format(PyExc_RuntimeError, "sysctl(HW_MEMSIZE) failed"); - return NULL; - } - - // vm - if (!psutil_sys_vminfo(&vm)) - return NULL; - - return Py_BuildValue( - "KKKKK", - total, - (unsigned long long) vm.active_count * pagesize, - (unsigned long long) vm.inactive_count * pagesize, - (unsigned long long) vm.wire_count * pagesize, - (unsigned long long) vm.free_count * pagesize - ); -} - - -/* - * Return stats about swap memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) -{ - int mib[2]; - size_t size; - struct xsw_usage totals; - vm_statistics_data_t vmstat; - int pagesize = getpagesize(); - - mib[0] = CTL_VM; - mib[1] = VM_SWAPUSAGE; - size = sizeof(totals); - if (sysctl(mib, 2, &totals, &size, NULL, 0) == -1) { - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format(PyExc_RuntimeError, "sysctl(VM_SWAPUSAGE) failed"); - return NULL; - } - if (!psutil_sys_vminfo(&vmstat)) - return NULL; - - return Py_BuildValue( - "LLLKK", - totals.xsu_total, - totals.xsu_used, - totals.xsu_avail, - (unsigned long long)vmstat.pageins * pagesize, - (unsigned long long)vmstat.pageouts * pagesize); -} - - -/* - * Return a Python tuple representing user, kernel and idle CPU times - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) -{ - mach_msg_type_number_t count = HOST_CPU_LOAD_INFO_COUNT; - kern_return_t error; - host_cpu_load_info_data_t r_load; - - mach_port_t host_port = mach_host_self(); - error = host_statistics(host_port, HOST_CPU_LOAD_INFO, - (host_info_t)&r_load, &count); - if (error != KERN_SUCCESS) - return PyErr_Format(PyExc_RuntimeError, - "Error in host_statistics(): %s", - mach_error_string(error)); - mach_port_deallocate(mach_task_self(), host_port); - - return Py_BuildValue( - "(dddd)", - (double)r_load.cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)r_load.cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); -} - - -/* - * Return a Python list of tuple representing per-cpu times - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) -{ - natural_t cpu_count; - processor_info_array_t info_array; - mach_msg_type_number_t info_count; - kern_return_t error; - processor_cpu_load_info_data_t *cpu_load_info = NULL; - int i, ret; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - mach_port_t host_port = mach_host_self(); - error = host_processor_info(host_port, PROCESSOR_CPU_LOAD_INFO, - &cpu_count, &info_array, &info_count); - if (error != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, "Error in host_processor_info(): %s", - mach_error_string(error)); - goto error; - } - mach_port_deallocate(mach_task_self(), host_port); - - cpu_load_info = (processor_cpu_load_info_data_t *) info_array; - - for (i = 0; i < cpu_count; i++) { - py_cputime = Py_BuildValue( - "(dddd)", - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_USER] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_NICE] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_SYSTEM] / CLK_TCK, - (double)cpu_load_info[i].cpu_ticks[CPU_STATE_IDLE] / CLK_TCK - ); - if (!py_cputime) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - } - - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (cpu_load_info != NULL) { - ret = vm_deallocate(mach_task_self(), (vm_address_t)info_array, - info_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Return a Python float indicating the system boot time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) -{ - // fetch sysctl "kern.boottime" - static int request[2] = { CTL_KERN, KERN_BOOTTIME }; - struct timeval result; - size_t result_len = sizeof result; - time_t boot_time = 0; - - if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - boot_time = result.tv_sec; - return Py_BuildValue("f", (float)boot_time); -} - - -/* - * Return a list of tuples including device, mount point and fs type - * for all partitions mounted on the system. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) -{ - int num; - int i; - long len; - uint64_t flags; - char opts[400]; - struct statfs *fs = NULL; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - // get the number of mount points - Py_BEGIN_ALLOW_THREADS - num = getfsstat(NULL, 0, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - len = sizeof(*fs) * num; - fs = malloc(len); - if (fs == NULL) { - PyErr_NoMemory(); - goto error; - } - - Py_BEGIN_ALLOW_THREADS - num = getfsstat(fs, len, MNT_NOWAIT); - Py_END_ALLOW_THREADS - if (num == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (i = 0; i < num; i++) { - opts[0] = 0; - flags = fs[i].f_flags; - - // see sys/mount.h - if (flags & MNT_RDONLY) - strlcat(opts, "ro", sizeof(opts)); - else - strlcat(opts, "rw", sizeof(opts)); - if (flags & MNT_SYNCHRONOUS) - strlcat(opts, ",sync", sizeof(opts)); - if (flags & MNT_NOEXEC) - strlcat(opts, ",noexec", sizeof(opts)); - if (flags & MNT_NOSUID) - strlcat(opts, ",nosuid", sizeof(opts)); - if (flags & MNT_UNION) - strlcat(opts, ",union", sizeof(opts)); - if (flags & MNT_ASYNC) - strlcat(opts, ",async", sizeof(opts)); - if (flags & MNT_EXPORTED) - strlcat(opts, ",exported", sizeof(opts)); - if (flags & MNT_QUARANTINE) - strlcat(opts, ",quarantine", sizeof(opts)); - if (flags & MNT_LOCAL) - strlcat(opts, ",local", sizeof(opts)); - if (flags & MNT_QUOTA) - strlcat(opts, ",quota", sizeof(opts)); - if (flags & MNT_ROOTFS) - strlcat(opts, ",rootfs", sizeof(opts)); - if (flags & MNT_DOVOLFS) - strlcat(opts, ",dovolfs", sizeof(opts)); - if (flags & MNT_DONTBROWSE) - strlcat(opts, ",dontbrowse", sizeof(opts)); - if (flags & MNT_IGNORE_OWNERSHIP) - strlcat(opts, ",ignore-ownership", sizeof(opts)); - if (flags & MNT_AUTOMOUNTED) - strlcat(opts, ",automounted", sizeof(opts)); - if (flags & MNT_JOURNALED) - strlcat(opts, ",journaled", sizeof(opts)); - if (flags & MNT_NOUSERXATTR) - strlcat(opts, ",nouserxattr", sizeof(opts)); - if (flags & MNT_DEFWRITE) - strlcat(opts, ",defwrite", sizeof(opts)); - if (flags & MNT_MULTILABEL) - strlcat(opts, ",multilabel", sizeof(opts)); - if (flags & MNT_NOATIME) - strlcat(opts, ",noatime", sizeof(opts)); - if (flags & MNT_UPDATE) - strlcat(opts, ",update", sizeof(opts)); - if (flags & MNT_RELOAD) - strlcat(opts, ",reload", sizeof(opts)); - if (flags & MNT_FORCE) - strlcat(opts, ",force", sizeof(opts)); - if (flags & MNT_CMDFLAGS) - strlcat(opts, ",cmdflags", sizeof(opts)); - - py_tuple = Py_BuildValue( - "(ssss)", fs[i].f_mntfromname, // device - fs[i].f_mntonname, // mount point - fs[i].f_fstypename, // fs type - opts); // options - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - - free(fs); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (fs != NULL) - free(fs); - return NULL; -} - - -/* - * Return process status as a Python integer. - */ -static PyObject * -psutil_proc_status(PyObject *self, PyObject *args) -{ - long pid; - struct kinfo_proc kp; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (psutil_get_kinfo_proc(pid, &kp) == -1) - return NULL; - return Py_BuildValue("i", (int)kp.kp_proc.p_stat); -} - - -/* - * Return process threads - */ -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) -{ - long pid; - int err, j, ret; - kern_return_t kr; - unsigned int info_count = TASK_BASIC_INFO_COUNT; - mach_port_t task = MACH_PORT_NULL; - struct task_basic_info tasks_info; - thread_act_port_array_t thread_list = NULL; - thread_info_data_t thinfo_basic; - thread_basic_info_t basic_info_th; - mach_msg_type_number_t thread_count, thread_info_count; - - PyObject *retList = PyList_New(0); - PyObject *pyTuple = NULL; - - if (retList == NULL) - return NULL; - - // the argument passed should be a process id - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - // task_for_pid() requires special privileges - err = task_for_pid(mach_task_self(), pid, &task); - if (err != KERN_SUCCESS) { - if (! psutil_pid_exists(pid)) - NoSuchProcess(); - else - AccessDenied(); - goto error; - } - - info_count = TASK_BASIC_INFO_COUNT; - err = task_info(task, TASK_BASIC_INFO, (task_info_t)&tasks_info, - &info_count); - if (err != KERN_SUCCESS) { - // errcode 4 is "invalid argument" (access denied) - if (err == 4) { - AccessDenied(); - } - else { - // otherwise throw a runtime error with appropriate error code - PyErr_Format(PyExc_RuntimeError, - "task_info(TASK_BASIC_INFO) failed"); - } - goto error; - } - - err = task_threads(task, &thread_list, &thread_count); - if (err != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, "task_threads() failed"); - goto error; - } - - for (j = 0; j < thread_count; j++) { - pyTuple = NULL; - thread_info_count = THREAD_INFO_MAX; - kr = thread_info(thread_list[j], THREAD_BASIC_INFO, - (thread_info_t)thinfo_basic, &thread_info_count); - if (kr != KERN_SUCCESS) { - PyErr_Format(PyExc_RuntimeError, - "thread_info() with flag THREAD_BASIC_INFO failed"); - goto error; - } - - basic_info_th = (thread_basic_info_t)thinfo_basic; - pyTuple = Py_BuildValue( - "Iff", - j + 1, - (float)basic_info_th->user_time.microseconds / 1000000.0, - (float)basic_info_th->system_time.microseconds / 1000000.0 - ); - if (!pyTuple) - goto error; - if (PyList_Append(retList, pyTuple)) - goto error; - Py_DECREF(pyTuple); - } - - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - - mach_port_deallocate(mach_task_self(), task); - - return retList; - -error: - if (task != MACH_PORT_NULL) - mach_port_deallocate(mach_task_self(), task); - Py_XDECREF(pyTuple); - Py_DECREF(retList); - if (thread_list != NULL) { - ret = vm_deallocate(task, (vm_address_t)thread_list, - thread_count * sizeof(int)); - if (ret != KERN_SUCCESS) - PyErr_WarnEx(PyExc_RuntimeWarning, "vm_deallocate() failed", 2); - } - return NULL; -} - - -/* - * Return process open files as a Python tuple. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/m78fd - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) -{ - long pid; - int pidinfo_result; - int iterations; - int i; - int nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct vnode_fdinfowithpath vi; - - PyObject *retList = PyList_New(0); - PyObject *tuple = NULL; - - if (retList == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) { - // may be be ignored later if errno != 0 - PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDLISTFDS) failed"); - goto error; - } - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, - pidinfo_result); - if (pidinfo_result <= 0) { - // may be be ignored later if errno != 0 - PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDLISTFDS) failed"); - goto error; - } - - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - - for (i = 0; i < iterations; i++) { - tuple = NULL; - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_VNODE) - { - nb = proc_pidfdinfo(pid, - fdp_pointer->proc_fd, - PROC_PIDFDVNODEPATHINFO, - &vi, - sizeof(vi)); - - // --- errors checking - if (nb <= 0) { - if ((errno == ENOENT) || (errno == EBADF)) { - // no such file or directory or bad file descriptor; - // let's assume the file has been closed or removed - continue; - } - // may be be ignored later if errno != 0 - PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed"); - goto error; - } - if (nb < sizeof(vi)) { - PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed " - "(buffer mismatch)"); - goto error; - } - // --- /errors checking - - // --- construct python list - tuple = Py_BuildValue("(si)", - vi.pvip.vip_path, - (int)fdp_pointer->proc_fd); - if (!tuple) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - // --- /construct python list - } - } - - free(fds_pointer); - return retList; - -error: - Py_XDECREF(tuple); - Py_DECREF(retList); - if (fds_pointer != NULL) - free(fds_pointer); - if (errno != 0) - return PyErr_SetFromErrno(PyExc_OSError); - else if (! psutil_pid_exists(pid)) - return NoSuchProcess(); - else - return NULL; // exception has already been set earlier -} - - -// a signaler for connections without an actual status -static int PSUTIL_CONN_NONE = 128; - -/* - * Return process TCP and UDP connections as a list of tuples. - * References: - * - lsof source code: http://goo.gl/SYW79 and http://goo.gl/wNrC0 - * - /usr/include/sys/proc_info.h - */ -static PyObject * -psutil_proc_connections(PyObject *self, PyObject *args) -{ - long pid; - int pidinfo_result; - int iterations; - int i; - int nb; - - struct proc_fdinfo *fds_pointer = NULL; - struct proc_fdinfo *fdp_pointer; - struct socket_fdinfo si; - - PyObject *retList = PyList_New(0); - PyObject *tuple = NULL; - PyObject *laddr = NULL; - PyObject *raddr = NULL; - PyObject *af_filter = NULL; - PyObject *type_filter = NULL; - - if (retList == NULL) - return NULL; - - if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) - goto error; - - if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - if (pid == 0) - return retList; - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - goto error; - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) { - PyErr_NoMemory(); - goto error; - } - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, - pidinfo_result); - - if (pidinfo_result <= 0) - goto error; - iterations = (pidinfo_result / PROC_PIDLISTFD_SIZE); - - for (i = 0; i < iterations; i++) { - tuple = NULL; - laddr = NULL; - raddr = NULL; - errno = 0; - fdp_pointer = &fds_pointer[i]; - - if (fdp_pointer->proc_fdtype == PROX_FDTYPE_SOCKET) - { - nb = proc_pidfdinfo(pid, fdp_pointer->proc_fd, - PROC_PIDFDSOCKETINFO, &si, sizeof(si)); - - // --- errors checking - if (nb <= 0) { - if (errno == EBADF) { - // let's assume socket has been closed - continue; - } - if (errno != 0) - PyErr_SetFromErrno(PyExc_OSError); - else - PyErr_Format( - PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed"); - goto error; - } - if (nb < sizeof(si)) { - PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDFDVNODEPATHINFO) failed " - "(buffer mismatch)"); - goto error; - } - // --- /errors checking - - // - int fd, family, type, lport, rport, state; - char lip[200], rip[200]; - int inseq; - PyObject *_family; - PyObject *_type; - - fd = (int)fdp_pointer->proc_fd; - family = si.psi.soi_family; - type = si.psi.soi_type; - - // apply filters - _family = PyLong_FromLong((long)family); - inseq = PySequence_Contains(af_filter, _family); - Py_DECREF(_family); - if (inseq == 0) - continue; - _type = PyLong_FromLong((long)type); - inseq = PySequence_Contains(type_filter, _type); - Py_DECREF(_type); - if (inseq == 0) - continue; - - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - if ((family == AF_INET) || (family == AF_INET6)) { - if (family == AF_INET) { - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_46.i46a_addr4, - lip, - sizeof(lip)); - inet_ntop(AF_INET, - &si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_faddr. \ - ina_46.i46a_addr4, - rip, - sizeof(rip)); - } - else { - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_laddr.ina_6, - lip, sizeof(lip)); - inet_ntop(AF_INET6, - &si.psi.soi_proto.pri_tcp.tcpsi_ini. \ - insi_faddr.ina_6, - rip, sizeof(rip)); - } - - // check for inet_ntop failures - if (errno != 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_lport); - rport = ntohs(si.psi.soi_proto.pri_tcp.tcpsi_ini.insi_fport); - if (type == SOCK_STREAM) - state = (int)si.psi.soi_proto.pri_tcp.tcpsi_state; - else - state = PSUTIL_CONN_NONE; - - laddr = Py_BuildValue("(si)", lip, lport); - if (!laddr) - goto error; - if (rport != 0) - raddr = Py_BuildValue("(si)", rip, rport); - else - raddr = Py_BuildValue("()"); - if (!raddr) - goto error; - - // construct the python list - tuple = Py_BuildValue("(iiiNNi)", fd, family, type, laddr, - raddr, state); - if (!tuple) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - } - else if (family == AF_UNIX) { - // construct the python list - tuple = Py_BuildValue( - "(iiissi)", - fd, family, type, - si.psi.soi_proto.pri_un.unsi_addr.ua_sun.sun_path, - si.psi.soi_proto.pri_un.unsi_caddr.ua_sun.sun_path, - PSUTIL_CONN_NONE); - if (!tuple) - goto error; - if (PyList_Append(retList, tuple)) - goto error; - Py_DECREF(tuple); - } - } - } - - free(fds_pointer); - return retList; - -error: - Py_XDECREF(tuple); - Py_XDECREF(laddr); - Py_XDECREF(raddr); - Py_DECREF(retList); - - if (fds_pointer != NULL) - free(fds_pointer); - if (errno != 0) - return PyErr_SetFromErrno(PyExc_OSError); - else if (! psutil_pid_exists(pid)) - return NoSuchProcess(); - else - return PyErr_Format(PyExc_RuntimeError, - "proc_pidinfo(PROC_PIDLISTFDS) failed"); -} - - -/* - * Return number of file descriptors opened by process. - */ -static PyObject * -psutil_proc_num_fds(PyObject *self, PyObject *args) -{ - long pid; - int pidinfo_result; - int num; - struct proc_fdinfo *fds_pointer; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); - if (pidinfo_result <= 0) - return PyErr_SetFromErrno(PyExc_OSError); - - fds_pointer = malloc(pidinfo_result); - if (fds_pointer == NULL) - return PyErr_NoMemory(); - pidinfo_result = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fds_pointer, - pidinfo_result); - if (pidinfo_result <= 0) { - free(fds_pointer); - return PyErr_SetFromErrno(PyExc_OSError); - } - - num = (pidinfo_result / PROC_PIDLISTFD_SIZE); - free(fds_pointer); - return Py_BuildValue("i", num); -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) -{ - char *buf = NULL, *lim, *next; - struct if_msghdr *ifm; - int mib[6]; - size_t len; - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - - mib[0] = CTL_NET; // networking subsystem - mib[1] = PF_ROUTE; // type of information - mib[2] = 0; // protocol (IPPROTO_xxx) - mib[3] = 0; // address family - mib[4] = NET_RT_IFLIST2; // operation - mib[5] = 0; - - if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - buf = malloc(len); - if (buf == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - lim = buf + len; - - for (next = buf; next < lim; ) { - ifm = (struct if_msghdr *)next; - next += ifm->ifm_msglen; - - if (ifm->ifm_type == RTM_IFINFO2) { - py_ifc_info = NULL; - struct if_msghdr2 *if2m = (struct if_msghdr2 *)ifm; - struct sockaddr_dl *sdl = (struct sockaddr_dl *)(if2m + 1); - char ifc_name[32]; - - strncpy(ifc_name, sdl->sdl_data, sdl->sdl_nlen); - ifc_name[sdl->sdl_nlen] = 0; - - py_ifc_info = Py_BuildValue( - "(KKKKKKKi)", - if2m->ifm_data.ifi_obytes, - if2m->ifm_data.ifi_ibytes, - if2m->ifm_data.ifi_opackets, - if2m->ifm_data.ifi_ipackets, - if2m->ifm_data.ifi_ierrors, - if2m->ifm_data.ifi_oerrors, - if2m->ifm_data.ifi_iqdrops, - 0); // dropout not supported - - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ifc_name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - else { - continue; - } - } - - free(buf); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (buf != NULL) - free(buf); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) -{ - CFDictionaryRef parent_dict; - CFDictionaryRef props_dict; - CFDictionaryRef stats_dict; - io_registry_entry_t parent; - io_registry_entry_t disk; - io_iterator_t disk_list; - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - - // Get list of disks - if (IOServiceGetMatchingServices(kIOMasterPortDefault, - IOServiceMatching(kIOMediaClass), - &disk_list) != kIOReturnSuccess) { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the list of disks."); - goto error; - } - - // Iterate over disks - while ((disk = IOIteratorNext(disk_list)) != 0) { - py_disk_info = NULL; - parent_dict = NULL; - props_dict = NULL; - stats_dict = NULL; - - if (IORegistryEntryGetParentEntry(disk, kIOServicePlane, &parent) - != kIOReturnSuccess) { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk's parent."); - IOObjectRelease(disk); - goto error; - } - - if (IOObjectConformsTo(parent, "IOBlockStorageDriver")) { - if (IORegistryEntryCreateCFProperties( - disk, - (CFMutableDictionaryRef *) &parent_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the parent's properties."); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - if (IORegistryEntryCreateCFProperties( - parent, - (CFMutableDictionaryRef *) &props_dict, - kCFAllocatorDefault, - kNilOptions - ) != kIOReturnSuccess) - { - PyErr_SetString(PyExc_RuntimeError, - "unable to get the disk properties."); - CFRelease(props_dict); - IOObjectRelease(disk); - IOObjectRelease(parent); - goto error; - } - - const int kMaxDiskNameSize = 64; - CFStringRef disk_name_ref = (CFStringRef)CFDictionaryGetValue( - parent_dict, CFSTR(kIOBSDNameKey)); - char disk_name[kMaxDiskNameSize]; - - CFStringGetCString(disk_name_ref, - disk_name, - kMaxDiskNameSize, - CFStringGetSystemEncoding()); - - stats_dict = (CFDictionaryRef)CFDictionaryGetValue( - props_dict, CFSTR(kIOBlockStorageDriverStatisticsKey)); - - if (stats_dict == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "Unable to get disk stats."); - goto error; - } - - CFNumberRef number; - int64_t reads = 0; - int64_t writes = 0; - int64_t read_bytes = 0; - int64_t write_bytes = 0; - int64_t read_time = 0; - int64_t write_time = 0; - - // Get disk reads/writes - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsReadsKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &reads); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsWritesKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &writes); - } - - // Get disk bytes read/written - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesReadKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_bytes); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsBytesWrittenKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_bytes); - } - - // Get disk time spent reading/writing (nanoseconds) - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalReadTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &read_time); - } - if ((number = (CFNumberRef)CFDictionaryGetValue( - stats_dict, - CFSTR(kIOBlockStorageDriverStatisticsTotalWriteTimeKey)))) - { - CFNumberGetValue(number, kCFNumberSInt64Type, &write_time); - } - - // Read/Write time on OS X comes back in nanoseconds and in psutil - // we've standardized on milliseconds so do the conversion. - py_disk_info = Py_BuildValue( - "(KKKKKK)", - reads, - writes, - read_bytes, - write_bytes, - read_time / 1000 / 1000, - write_time / 1000 / 1000); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, disk_name, py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - - CFRelease(parent_dict); - IOObjectRelease(parent); - CFRelease(props_dict); - IOObjectRelease(disk); - } - } - - IOObjectRelease (disk_list); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - return NULL; -} - - -/* - * Return currently connected users as a list of tuples. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) -{ - struct utmpx *utx; - PyObject *ret_list = PyList_New(0); - PyObject *tuple = NULL; - - if (ret_list == NULL) - return NULL; - while ((utx = getutxent()) != NULL) { - if (utx->ut_type != USER_PROCESS) - continue; - tuple = Py_BuildValue( - "(sssf)", - utx->ut_user, // username - utx->ut_line, // tty - utx->ut_host, // hostname - (float)utx->ut_tv.tv_sec // start time - ); - if (!tuple) { - endutxent(); - goto error; - } - if (PyList_Append(ret_list, tuple)) { - endutxent(); - goto error; - } - Py_DECREF(tuple); - } - - endutxent(); - return ret_list; - -error: - Py_XDECREF(tuple); - Py_DECREF(ret_list); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- per-process functions - - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory."}, - {"proc_ppid", psutil_proc_ppid, METH_VARARGS, - "Return process ppid as an integer"}, - {"proc_uids", psutil_proc_uids, METH_VARARGS, - "Return process real user id as an integer"}, - {"proc_gids", psutil_proc_gids, METH_VARARGS, - "Return process real group id as an integer"}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return tuple of user/kern time for the given PID"}, - {"proc_create_time", psutil_proc_create_time, METH_VARARGS, - "Return a float indicating the process create time expressed in " - "seconds since the epoch"}, - {"proc_memory_info", psutil_proc_memory_info, METH_VARARGS, - "Return memory information about a process"}, - {"proc_num_threads", psutil_proc_num_threads, METH_VARARGS, - "Return number of threads used by process"}, - {"proc_status", psutil_proc_status, METH_VARARGS, - "Return process status as an integer"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads as a list of tuples"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process as a list of tuples"}, - {"proc_num_fds", psutil_proc_num_fds, METH_VARARGS, - "Return the number of fds opened by process."}, - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Return the number of context switches performed by process"}, - {"proc_connections", psutil_proc_connections, METH_VARARGS, - "Get process TCP and UDP connections as a list of tuples"}, - {"proc_tty_nr", psutil_proc_tty_nr, METH_VARARGS, - "Return process tty number as an integer"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of tuples for every process's memory map"}, - - // --- system-related functions - - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Return number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return number of physical CPUs on the system"}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return system virtual memory stats"}, - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return stats about swap memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a tuple (user, system, nice, idle, irc)"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return a list of tuples including device, mount point and " - "fs type for all partitions mounted on the system."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users as a list of tuples"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_osx_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_osx_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_osx", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_osx_traverse, - psutil_osx_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_osx(void) - -#else -#define INITERROR return - -void -init_psutil_osx(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_osx", PsutilMethods); -#endif - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - // process status constants, defined in: - // http://fxr.watson.org/fxr/source/bsd/sys/proc.h?v=xnu-792.6.70#L149 - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SRUN", SRUN); - PyModule_AddIntConstant(module, "SSLEEP", SSLEEP); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - // connection status constants - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RECEIVED", TCPS_SYN_RECEIVED); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_osx.h b/python/psutil/psutil/_psutil_osx.h deleted file mode 100644 index 907a8e537..000000000 --- a/python/psutil/psutil/_psutil_osx.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -// --- per-process functions -static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args); -static PyObject* psutil_proc_connections(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); -static PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -static PyObject* psutil_proc_gids(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -static PyObject* psutil_proc_name(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_fds(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_threads(PyObject* self, PyObject* args); -static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args); -static PyObject* psutil_proc_ppid(PyObject* self, PyObject* args); -static PyObject* psutil_proc_status(PyObject* self, PyObject* args); -static PyObject* psutil_proc_threads(PyObject* self, PyObject* args); -static PyObject* psutil_proc_tty_nr(PyObject* self, PyObject* args); -static PyObject* psutil_proc_uids(PyObject* self, PyObject* args); - -// --- system-related functions -static PyObject* psutil_boot_time(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); -static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_pids(PyObject* self, PyObject* args); -static PyObject* psutil_swap_mem(PyObject* self, PyObject* args); -static PyObject* psutil_users(PyObject* self, PyObject* args); -static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); diff --git a/python/psutil/psutil/_psutil_posix.c b/python/psutil/psutil/_psutil_posix.c deleted file mode 100644 index 183dab0e1..000000000 --- a/python/psutil/psutil/_psutil_posix.c +++ /dev/null @@ -1,531 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions specific to all POSIX compliant platforms. - */ - -#include <Python.h> -#include <errno.h> -#include <stdlib.h> -#include <sys/resource.h> -#include <sys/types.h> -#include <sys/socket.h> -#include <ifaddrs.h> - -#ifdef __linux -#include <netdb.h> -#include <linux/if_packet.h> -#endif // end linux - -#if defined(__FreeBSD__) || defined(__APPLE__) -#include <netdb.h> -#include <netinet/in.h> -#include <net/if_dl.h> -#endif - -#if defined(__sun) -#include <netdb.h> -#endif - -#include "_psutil_posix.h" - - -/* - * Given a PID return process priority as a Python integer. - */ -static PyObject * -psutil_posix_getpriority(PyObject *self, PyObject *args) -{ - long pid; - int priority; - errno = 0; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - priority = getpriority(PRIO_PROCESS, pid); - if (errno != 0) - return PyErr_SetFromErrno(PyExc_OSError); - return Py_BuildValue("i", priority); -} - - -/* - * Given a PID and a value change process priority. - */ -static PyObject * -psutil_posix_setpriority(PyObject *self, PyObject *args) -{ - long pid; - int priority; - int retval; - - if (! PyArg_ParseTuple(args, "li", &pid, &priority)) - return NULL; - retval = setpriority(PRIO_PROCESS, pid, priority); - if (retval == -1) - return PyErr_SetFromErrno(PyExc_OSError); - Py_RETURN_NONE; -} - - -/* - * Translate a sockaddr struct into a Python string. - * Return None if address family is not AF_INET* or AF_PACKET. - */ -static PyObject * -psutil_convert_ipaddr(struct sockaddr *addr, int family) -{ - char buf[NI_MAXHOST]; - int err; - int addrlen; - int n; - size_t len; - const char *data; - char *ptr; - - if (addr == NULL) { - Py_INCREF(Py_None); - return Py_None; - } - else if (family == AF_INET || family == AF_INET6) { - if (family == AF_INET) - addrlen = sizeof(struct sockaddr_in); - else - addrlen = sizeof(struct sockaddr_in6); - err = getnameinfo(addr, addrlen, buf, sizeof(buf), NULL, 0, - NI_NUMERICHOST); - if (err != 0) { - // XXX we get here on FreeBSD when processing 'lo' / AF_INET6 - // broadcast. Not sure what to do other than returning None. - // ifconfig does not show anything BTW. - //PyErr_Format(PyExc_RuntimeError, gai_strerror(err)); - //return NULL; - Py_INCREF(Py_None); - return Py_None; - } - else { - return Py_BuildValue("s", buf); - } - } -#ifdef __linux - else if (family == AF_PACKET) { - struct sockaddr_ll *lladdr = (struct sockaddr_ll *)addr; - len = lladdr->sll_halen; - data = (const char *)lladdr->sll_addr; - } -#endif -#if defined(__FreeBSD__) || defined(__APPLE__) - else if (addr->sa_family == AF_LINK) { - // Note: prior to Python 3.4 socket module does not expose - // AF_LINK so we'll do. - struct sockaddr_dl *dladdr = (struct sockaddr_dl *)addr; - len = dladdr->sdl_alen; - data = LLADDR(dladdr); - } -#endif - else { - // unknown family - Py_INCREF(Py_None); - return Py_None; - } - - // AF_PACKET or AF_LINK - if (len > 0) { - ptr = buf; - for (n = 0; n < len; ++n) { - sprintf(ptr, "%02x:", data[n] & 0xff); - ptr += 3; - } - *--ptr = '\0'; - return Py_BuildValue("s", buf); - } - else { - Py_INCREF(Py_None); - return Py_None; - } -} - - -/* - * Return NICs information a-la ifconfig as a list of tuples. - * TODO: on Solaris we won't get any MAC address. - */ -static PyObject* -psutil_net_if_addrs(PyObject* self, PyObject* args) -{ - struct ifaddrs *ifaddr, *ifa; - int family; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_netmask = NULL; - PyObject *py_broadcast = NULL; - - if (py_retlist == NULL) - return NULL; - if (getifaddrs(&ifaddr) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { - if (!ifa->ifa_addr) - continue; - family = ifa->ifa_addr->sa_family; - py_address = psutil_convert_ipaddr(ifa->ifa_addr, family); - // If the primary address can't be determined just skip it. - // I've never seen this happen on Linux but I did on FreeBSD. - if (py_address == Py_None) - continue; - if (py_address == NULL) - goto error; - py_netmask = psutil_convert_ipaddr(ifa->ifa_netmask, family); - if (py_netmask == NULL) - goto error; -#ifdef __linux - py_broadcast = psutil_convert_ipaddr(ifa->ifa_ifu.ifu_broadaddr, family); -#else - py_broadcast = psutil_convert_ipaddr(ifa->ifa_broadaddr, family); -#endif - if (py_broadcast == NULL) - goto error; - py_tuple = Py_BuildValue( - "(siOOO)", - ifa->ifa_name, - family, - py_address, - py_netmask, - py_broadcast - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_DECREF(py_address); - Py_DECREF(py_netmask); - Py_DECREF(py_broadcast); - } - - freeifaddrs(ifaddr); - return py_retlist; - -error: - if (ifaddr != NULL) - freeifaddrs(ifaddr); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_XDECREF(py_netmask); - Py_XDECREF(py_broadcast); - return NULL; -} - - -/* - * net_if_stats() implementation. This is here because it is common - * to both OSX and FreeBSD and I didn't know where else to put it. - */ -#if defined(__FreeBSD__) || defined(__APPLE__) - -#include <sys/sockio.h> -#include <net/if_media.h> -#include <net/if.h> - -int psutil_get_nic_speed(int ifm_active) { - // Determine NIC speed. Taken from: - // http://www.i-scream.org/libstatgrab/ - // Assuming only ETHER devices - switch(IFM_TYPE(ifm_active)) { - case IFM_ETHER: - switch(IFM_SUBTYPE(ifm_active)) { -#if defined(IFM_HPNA_1) && ((!defined(IFM_10G_LR)) \ - || (IFM_10G_LR != IFM_HPNA_1)) - // HomePNA 1.0 (1Mb/s) - case(IFM_HPNA_1): - return 1; -#endif - // 10 Mbit - case(IFM_10_T): // 10BaseT - RJ45 - case(IFM_10_2): // 10Base2 - Thinnet - case(IFM_10_5): // 10Base5 - AUI - case(IFM_10_STP): // 10BaseT over shielded TP - case(IFM_10_FL): // 10baseFL - Fiber - return 10; - // 100 Mbit - case(IFM_100_TX): // 100BaseTX - RJ45 - case(IFM_100_FX): // 100BaseFX - Fiber - case(IFM_100_T4): // 100BaseT4 - 4 pair cat 3 - case(IFM_100_VG): // 100VG-AnyLAN - case(IFM_100_T2): // 100BaseT2 - return 100; - // 1000 Mbit - case(IFM_1000_SX): // 1000BaseSX - multi-mode fiber - case(IFM_1000_LX): // 1000baseLX - single-mode fiber - case(IFM_1000_CX): // 1000baseCX - 150ohm STP -#if defined(IFM_1000_TX) && !defined(OPENBSD) - // FreeBSD 4 and others (but NOT OpenBSD)? - case(IFM_1000_TX): -#endif -#ifdef IFM_1000_FX - case(IFM_1000_FX): -#endif -#ifdef IFM_1000_T - case(IFM_1000_T): -#endif - return 1000; -#if defined(IFM_10G_SR) || defined(IFM_10G_LR) || defined(IFM_10G_CX4) \ - || defined(IFM_10G_T) -#ifdef IFM_10G_SR - case(IFM_10G_SR): -#endif -#ifdef IFM_10G_LR - case(IFM_10G_LR): -#endif -#ifdef IFM_10G_CX4 - case(IFM_10G_CX4): -#endif -#ifdef IFM_10G_TWINAX - case(IFM_10G_TWINAX): -#endif -#ifdef IFM_10G_TWINAX_LONG - case(IFM_10G_TWINAX_LONG): -#endif -#ifdef IFM_10G_T - case(IFM_10G_T): -#endif - return 10000; -#endif -#if defined(IFM_2500_SX) -#ifdef IFM_2500_SX - case(IFM_2500_SX): -#endif - return 2500; -#endif // any 2.5GBit stuff... - // We don't know what it is - default: - return 0; - } - break; - -#ifdef IFM_TOKEN - case IFM_TOKEN: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_TOK_STP4: // Shielded twisted pair 4m - DB9 - case IFM_TOK_UTP4: // Unshielded twisted pair 4m - RJ45 - return 4; - case IFM_TOK_STP16: // Shielded twisted pair 16m - DB9 - case IFM_TOK_UTP16: // Unshielded twisted pair 16m - RJ45 - return 16; -#if defined(IFM_TOK_STP100) || defined(IFM_TOK_UTP100) -#ifdef IFM_TOK_STP100 - case IFM_TOK_STP100: // Shielded twisted pair 100m - DB9 -#endif -#ifdef IFM_TOK_UTP100 - case IFM_TOK_UTP100: // Unshielded twisted pair 100m - RJ45 -#endif - return 100; -#endif - // We don't know what it is - default: - return 0; - } - break; -#endif - -#ifdef IFM_FDDI - case IFM_FDDI: - switch(IFM_SUBTYPE(ifm_active)) { - // We don't know what it is - default: - return 0; - } - break; -#endif - case IFM_IEEE80211: - switch(IFM_SUBTYPE(ifm_active)) { - case IFM_IEEE80211_FH1: // Frequency Hopping 1Mbps - case IFM_IEEE80211_DS1: // Direct Sequence 1Mbps - return 1; - case IFM_IEEE80211_FH2: // Frequency Hopping 2Mbps - case IFM_IEEE80211_DS2: // Direct Sequence 2Mbps - return 2; - case IFM_IEEE80211_DS5: // Direct Sequence 5Mbps - return 5; - case IFM_IEEE80211_DS11: // Direct Sequence 11Mbps - return 11; - case IFM_IEEE80211_DS22: // Direct Sequence 22Mbps - return 22; - // We don't know what it is - default: - return 0; - } - break; - - default: - return 0; - } -} - - -/* - * Return stats about a particular network interface. - * References: - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject * -psutil_net_if_stats(PyObject *self, PyObject *args) -{ - char *nic_name; - int sock = 0; - int ret; - int duplex; - int speed; - int mtu; - struct ifreq ifr; - struct ifmediareq ifmed; - - PyObject *py_is_up = NULL; - - if (! PyArg_ParseTuple(args, "s", &nic_name)) - return NULL; - - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - strncpy(ifr.ifr_name, nic_name, sizeof(ifr.ifr_name)); - - // is up? - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - goto error; - if ((ifr.ifr_flags & IFF_UP) != 0) - py_is_up = Py_True; - else - py_is_up = Py_False; - Py_INCREF(py_is_up); - - // MTU - ret = ioctl(sock, SIOCGIFMTU, &ifr); - if (ret == -1) - goto error; - mtu = ifr.ifr_mtu; - - // speed / duplex - memset(&ifmed, 0, sizeof(struct ifmediareq)); - strlcpy(ifmed.ifm_name, nic_name, sizeof(ifmed.ifm_name)); - ret = ioctl(sock, SIOCGIFMEDIA, (caddr_t)&ifmed); - if (ret == -1) { - speed = 0; - duplex = 0; - } - else { - speed = psutil_get_nic_speed(ifmed.ifm_active); - if ((ifmed.ifm_active | IFM_FDX) == ifmed.ifm_active) - duplex = 2; - else if ((ifmed.ifm_active | IFM_HDX) == ifmed.ifm_active) - duplex = 1; - else - duplex = 0; - } - - close(sock); - Py_DECREF(py_is_up); - - return Py_BuildValue("[Oiii]", py_is_up, duplex, speed, mtu); - -error: - Py_XDECREF(py_is_up); - if (sock != 0) - close(sock); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} -#endif // net_if_stats() implementation - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - {"getpriority", psutil_posix_getpriority, METH_VARARGS, - "Return process priority"}, - {"setpriority", psutil_posix_setpriority, METH_VARARGS, - "Set process priority"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Retrieve NICs information"}, -#if defined(__FreeBSD__) || defined(__APPLE__) - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats."}, -#endif - {NULL, NULL, 0, NULL} -}; - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_posix_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_posix_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_posix", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_posix_traverse, - psutil_posix_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_posix(void) - -#else -#define INITERROR return - -void init_psutil_posix(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_posix", PsutilMethods); -#endif - -#if defined(__FreeBSD__) || defined(__APPLE__) || defined(__sun) - PyModule_AddIntConstant(module, "AF_LINK", AF_LINK); -#endif - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_posix.h b/python/psutil/psutil/_psutil_posix.h deleted file mode 100644 index bbe6fc5ad..000000000 --- a/python/psutil/psutil/_psutil_posix.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args); -static PyObject* psutil_posix_getpriority(PyObject* self, PyObject* args); -static PyObject* psutil_posix_setpriority(PyObject* self, PyObject* args); - -#if defined(__FreeBSD__) || defined(__APPLE__) -static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args); -#endif diff --git a/python/psutil/psutil/_psutil_sunos.c b/python/psutil/psutil/_psutil_sunos.c deleted file mode 100644 index 0cb6978f2..000000000 --- a/python/psutil/psutil/_psutil_sunos.c +++ /dev/null @@ -1,1389 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Functions specific to Sun OS Solaris platforms. - * - * Thanks to Justin Venus who originally wrote a consistent part of - * this in Cython which I later on translated in C. - */ - - -#include <Python.h> - -// fix for "Cannot use procfs in the large file compilation environment" -// error, see: -// http://sourceware.org/ml/gdb-patches/2010-11/msg00336.html -#undef _FILE_OFFSET_BITS -#define _STRUCTURED_PROC 1 - -// fix compilation issue on SunOS 5.10, see: -// https://github.com/giampaolo/psutil/issues/421 -#define NEW_MIB_COMPLIANT - -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/proc.h> -#include <sys/swap.h> -#include <sys/sysinfo.h> -#include <sys/mntent.h> // for MNTTAB -#include <sys/mnttab.h> -#include <sys/procfs.h> -#include <sys/sockio.h> -#include <sys/socket.h> -#include <fcntl.h> -#include <utmpx.h> -#include <kstat.h> -#include <sys/ioctl.h> -#include <sys/tihdr.h> -#include <stropts.h> -#include <inet/tcp.h> -#include <arpa/inet.h> -#include <net/if.h> - -#include "_psutil_sunos.h" - - -#define TV2DOUBLE(t) (((t).tv_nsec * 0.000000001) + (t).tv_sec) - -/* - * Read a file content and fills a C structure with it. - */ -int -psutil_file_to_struct(char *path, void *fstruct, size_t size) -{ - int fd; - size_t nbytes; - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, path); - return 0; - } - nbytes = read(fd, fstruct, size); - if (nbytes <= 0) { - close(fd); - PyErr_SetFromErrno(PyExc_OSError); - return 0; - } - if (nbytes != size) { - close(fd); - PyErr_SetString(PyExc_RuntimeError, "structure size mismatch"); - return 0; - } - close(fd); - return nbytes; -} - - -/* - * Return process ppid, rss, vms, ctime, nice, nthreads, status and tty - * as a Python tuple. - */ -static PyObject * -psutil_proc_basic_info(PyObject *self, PyObject *args) -{ - int pid; - char path[100]; - psinfo_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/psinfo", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("ikkdiiik", - info.pr_ppid, // parent pid - info.pr_rssize, // rss - info.pr_size, // vms - TV2DOUBLE(info.pr_start), // create time - info.pr_lwp.pr_nice, // nice - info.pr_nlwp, // no. of threads - info.pr_lwp.pr_state, // status code - info.pr_ttydev // tty nr - ); -} - - -/* - * Return process name and args as a Python tuple. - */ -static PyObject * -psutil_proc_name_and_args(PyObject *self, PyObject *args) -{ - int pid; - char path[100]; - psinfo_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/psinfo", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("ss", info.pr_fname, info.pr_psargs); -} - - -/* - * Return process user and system CPU times as a Python tuple. - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) -{ - int pid; - char path[100]; - pstatus_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/status", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - // results are more precise than os.times() - return Py_BuildValue("dd", - TV2DOUBLE(info.pr_utime), - TV2DOUBLE(info.pr_stime)); -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_cred(PyObject *self, PyObject *args) -{ - int pid; - char path[100]; - prcred_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/cred", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("iiiiii", - info.pr_ruid, info.pr_euid, info.pr_suid, - info.pr_rgid, info.pr_egid, info.pr_sgid); -} - - -/* - * Return process uids/gids as a Python tuple. - */ -static PyObject * -psutil_proc_num_ctx_switches(PyObject *self, PyObject *args) -{ - int pid; - char path[100]; - prusage_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/usage", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("kk", info.pr_vctx, info.pr_ictx); -} - - -/* - * Process IO counters. - * - * Commented out and left here as a reminder. Apparently we cannot - * retrieve process IO stats because: - * - 'pr_ioch' is a sum of chars read and written, with no distinction - * - 'pr_inblk' and 'pr_oublk', which should be the number of bytes - * read and written, hardly increase and according to: - * http://www.brendangregg.com/Perf/paper_diskubyp1.pdf - * ...they should be meaningless anyway. - * -static PyObject* -proc_io_counters(PyObject* self, PyObject* args) -{ - int pid; - char path[100]; - prusage_t info; - - if (! PyArg_ParseTuple(args, "i", &pid)) - return NULL; - sprintf(path, "/proc/%i/usage", pid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - - // On Solaris we only have 'pr_ioch' which accounts for bytes read - // *and* written. - // 'pr_inblk' and 'pr_oublk' should be expressed in blocks of - // 8KB according to: - // http://www.brendangregg.com/Perf/paper_diskubyp1.pdf (pag. 8) - return Py_BuildValue("kkkk", - info.pr_ioch, - info.pr_ioch, - info.pr_inblk, - info.pr_oublk); -} - */ - - -/* - * Return information about a given process thread. - */ -static PyObject * -psutil_proc_query_thread(PyObject *self, PyObject *args) -{ - int pid, tid; - char path[100]; - lwpstatus_t info; - - if (! PyArg_ParseTuple(args, "ii", &pid, &tid)) - return NULL; - sprintf(path, "/proc/%i/lwp/%i/lwpstatus", pid, tid); - if (! psutil_file_to_struct(path, (void *)&info, sizeof(info))) - return NULL; - return Py_BuildValue("dd", - TV2DOUBLE(info.pr_utime), - TV2DOUBLE(info.pr_stime)); -} - - -/* - * Return information about system virtual memory. - */ -static PyObject * -psutil_swap_mem(PyObject *self, PyObject *args) -{ -// XXX (arghhh!) -// total/free swap mem: commented out as for some reason I can't -// manage to get the same results shown by "swap -l", despite the -// code below is exactly the same as: -// http://cvs.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/ -// cmd/swap/swap.c -// We're going to parse "swap -l" output from Python (sigh!) - -/* - struct swaptable *st; - struct swapent *swapent; - int i; - struct stat64 statbuf; - char *path; - char fullpath[MAXPATHLEN+1]; - int num; - - if ((num = swapctl(SC_GETNSWP, NULL)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - if (num == 0) { - PyErr_SetString(PyExc_RuntimeError, "no swap devices configured"); - return NULL; - } - if ((st = malloc(num * sizeof(swapent_t) + sizeof (int))) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - if ((path = malloc(num * MAXPATHLEN)) == NULL) { - PyErr_SetString(PyExc_RuntimeError, "malloc failed"); - return NULL; - } - swapent = st->swt_ent; - for (i = 0; i < num; i++, swapent++) { - swapent->ste_path = path; - path += MAXPATHLEN; - } - st->swt_n = num; - if ((num = swapctl(SC_LIST, st)) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - return NULL; - } - - swapent = st->swt_ent; - long t = 0, f = 0; - for (i = 0; i < num; i++, swapent++) { - int diskblks_per_page =(int)(sysconf(_SC_PAGESIZE) >> DEV_BSHIFT); - t += (long)swapent->ste_pages; - f += (long)swapent->ste_free; - } - - free(st); - return Py_BuildValue("(kk)", t, f); -*/ - - kstat_ctl_t *kc; - kstat_t *k; - cpu_stat_t *cpu; - int cpu_count = 0; - int flag = 0; - uint_t sin = 0; - uint_t sout = 0; - - kc = kstat_open(); - if (kc == NULL) - return PyErr_SetFromErrno(PyExc_OSError);; - - k = kc->kc_chain; - while (k != NULL) { - if ((strncmp(k->ks_name, "cpu_stat", 8) == 0) && \ - (kstat_read(kc, k, NULL) != -1) ) - { - flag = 1; - cpu = (cpu_stat_t *) k->ks_data; - sin += cpu->cpu_vminfo.pgswapin; // num pages swapped in - sout += cpu->cpu_vminfo.pgswapout; // num pages swapped out - } - cpu_count += 1; - k = k->ks_next; - } - kstat_close(kc); - if (!flag) { - PyErr_SetString(PyExc_RuntimeError, "no swap device was found"); - return NULL; - } - return Py_BuildValue("(II)", sin, sout); -} - - -/* - * Return users currently connected on the system. - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) -{ - struct utmpx *ut; - PyObject *ret_list = PyList_New(0); - PyObject *tuple = NULL; - PyObject *user_proc = NULL; - - if (ret_list == NULL) - return NULL; - - while (NULL != (ut = getutxent())) { - if (ut->ut_type == USER_PROCESS) - user_proc = Py_True; - else - user_proc = Py_False; - tuple = Py_BuildValue( - "(sssfO)", - ut->ut_user, // username - ut->ut_line, // tty - ut->ut_host, // hostname - (float)ut->ut_tv.tv_sec, // tstamp - user_proc); // (bool) user process - if (tuple == NULL) - goto error; - if (PyList_Append(ret_list, tuple)) - goto error; - Py_DECREF(tuple); - } - endutent(); - - return ret_list; - -error: - Py_XDECREF(tuple); - Py_DECREF(ret_list); - if (ut != NULL) - endutent(); - return NULL; -} - - -/* - * Return disk mounted partitions as a list of tuples including device, - * mount point and filesystem type. - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) -{ - FILE *file; - struct mnttab mt; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) - return NULL; - - file = fopen(MNTTAB, "rb"); - if (file == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - while (getmntent(file, &mt) == 0) { - py_tuple = Py_BuildValue( - "(ssss)", - mt.mnt_special, // device - mt.mnt_mountp, // mount point - mt.mnt_fstype, // fs type - mt.mnt_mntopts); // options - if (py_tuple == NULL) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - - } - fclose(file); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - if (file != NULL) - fclose(file); - return NULL; -} - - -/* - * Return system-wide CPU times. - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) -{ - kstat_ctl_t *kc; - kstat_t *ksp; - cpu_stat_t cs; - PyObject *py_retlist = PyList_New(0); - PyObject *py_cputime = NULL; - - if (py_retlist == NULL) - return NULL; - - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - for (ksp = kc->kc_chain; ksp != NULL; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_stat") == 0) { - if (kstat_read(kc, ksp, &cs) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - py_cputime = Py_BuildValue("ffff", - (float)cs.cpu_sysinfo.cpu[CPU_USER], - (float)cs.cpu_sysinfo.cpu[CPU_KERNEL], - (float)cs.cpu_sysinfo.cpu[CPU_IDLE], - (float)cs.cpu_sysinfo.cpu[CPU_WAIT]); - if (py_cputime == NULL) - goto error; - if (PyList_Append(py_retlist, py_cputime)) - goto error; - Py_DECREF(py_cputime); - py_cputime = NULL; - } - } - - kstat_close(kc); - return py_retlist; - -error: - Py_XDECREF(py_cputime); - Py_DECREF(py_retlist); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return disk IO statistics. - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) -{ - kstat_ctl_t *kc; - kstat_t *ksp; - kstat_io_t kio; - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) { - PyErr_SetFromErrno(PyExc_OSError);; - goto error; - } - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type == KSTAT_TYPE_IO) { - if (strcmp(ksp->ks_class, "disk") == 0) { - if (kstat_read(kc, ksp, &kio) == -1) { - kstat_close(kc); - return PyErr_SetFromErrno(PyExc_OSError);; - } - py_disk_info = Py_BuildValue( - "(IIKKLL)", - kio.reads, - kio.writes, - kio.nread, - kio.nwritten, - kio.rtime / 1000 / 1000, // from nano to milli secs - kio.wtime / 1000 / 1000 // from nano to milli secs - ); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, - py_disk_info)) - goto error; - Py_DECREF(py_disk_info); - } - } - ksp = ksp->ks_next; - } - kstat_close(kc); - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -/* - * Return process memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) -{ - int pid; - int fd = -1; - char path[100]; - char perms[10]; - char *name; - struct stat st; - pstatus_t status; - - prxmap_t *xmap = NULL, *p; - off_t size; - size_t nread; - int nmap; - uintptr_t pr_addr_sz; - uintptr_t stk_base_sz, brk_base_sz; - - PyObject *pytuple = NULL; - PyObject *py_retlist = PyList_New(0); - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "i", &pid)) - goto error; - - sprintf(path, "/proc/%i/status", pid); - if (! psutil_file_to_struct(path, (void *)&status, sizeof(status))) - goto error; - - sprintf(path, "/proc/%i/xmap", pid); - if (stat(path, &st) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - size = st.st_size; - - fd = open(path, O_RDONLY); - if (fd == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - xmap = (prxmap_t *)malloc(size); - if (xmap == NULL) { - PyErr_NoMemory(); - goto error; - } - - nread = pread(fd, xmap, size, 0); - nmap = nread / sizeof(prxmap_t); - p = xmap; - - while (nmap) { - nmap -= 1; - if (p == NULL) { - p += 1; - continue; - } - - perms[0] = '\0'; - pr_addr_sz = p->pr_vaddr + p->pr_size; - - // perms - sprintf(perms, "%c%c%c%c%c%c", p->pr_mflags & MA_READ ? 'r' : '-', - p->pr_mflags & MA_WRITE ? 'w' : '-', - p->pr_mflags & MA_EXEC ? 'x' : '-', - p->pr_mflags & MA_SHARED ? 's' : '-', - p->pr_mflags & MA_NORESERVE ? 'R' : '-', - p->pr_mflags & MA_RESERVED1 ? '*' : ' '); - - // name - if (strlen(p->pr_mapname) > 0) { - name = p->pr_mapname; - } - else { - if ((p->pr_mflags & MA_ISM) || (p->pr_mflags & MA_SHM)) { - name = "[shmid]"; - } - else { - stk_base_sz = status.pr_stkbase + status.pr_stksize; - brk_base_sz = status.pr_brkbase + status.pr_brksize; - - if ((pr_addr_sz > status.pr_stkbase) && - (p->pr_vaddr < stk_base_sz)) { - name = "[stack]"; - } - else if ((p->pr_mflags & MA_ANON) && \ - (pr_addr_sz > status.pr_brkbase) && \ - (p->pr_vaddr < brk_base_sz)) { - name = "[heap]"; - } - else { - name = "[anon]"; - } - } - } - - pytuple = Py_BuildValue("iisslll", - p->pr_vaddr, - pr_addr_sz, - perms, - name, - (long)p->pr_rss * p->pr_pagesize, - (long)p->pr_anon * p->pr_pagesize, - (long)p->pr_locked * p->pr_pagesize); - if (!pytuple) - goto error; - if (PyList_Append(py_retlist, pytuple)) - goto error; - Py_DECREF(pytuple); - - // increment pointer - p += 1; - } - - close(fd); - free(xmap); - return py_retlist; - -error: - if (fd != -1) - close(fd); - Py_XDECREF(pytuple); - Py_DECREF(py_retlist); - if (xmap != NULL) - free(xmap); - return NULL; -} - - -/* - * Return a list of tuples for network I/O statistics. - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) -{ - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *rbytes, *wbytes, *rpkts, *wpkts, *ierrs, *oerrs; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - - ksp = kc->kc_chain; - while (ksp != NULL) { - if (ksp->ks_type != KSTAT_TYPE_NAMED) - goto next; - if (strcmp(ksp->ks_class, "net") != 0) - goto next; - /* - // XXX "lo" (localhost) interface makes kstat_data_lookup() fail - // (maybe because "ifconfig -a" says it's a virtual interface?). - if ((strcmp(ksp->ks_module, "link") != 0) && - (strcmp(ksp->ks_module, "lo") != 0)) { - goto skip; - */ - if ((strcmp(ksp->ks_module, "link") != 0)) - goto next; - - if (kstat_read(kc, ksp, NULL) == -1) { - errno = 0; - continue; - } - - rbytes = (kstat_named_t *)kstat_data_lookup(ksp, "rbytes"); - wbytes = (kstat_named_t *)kstat_data_lookup(ksp, "obytes"); - rpkts = (kstat_named_t *)kstat_data_lookup(ksp, "ipackets"); - wpkts = (kstat_named_t *)kstat_data_lookup(ksp, "opackets"); - ierrs = (kstat_named_t *)kstat_data_lookup(ksp, "ierrors"); - oerrs = (kstat_named_t *)kstat_data_lookup(ksp, "oerrors"); - - if ((rbytes == NULL) || (wbytes == NULL) || (rpkts == NULL) || - (wpkts == NULL) || (ierrs == NULL) || (oerrs == NULL)) - { - PyErr_SetString(PyExc_RuntimeError, "kstat_data_lookup() failed"); - goto error; - } - -#if defined(_INT64_TYPE) - py_ifc_info = Py_BuildValue("(KKKKkkii)", - wbytes->value.ui64, - rbytes->value.ui64, - wpkts->value.ui64, - rpkts->value.ui64, - ierrs->value.ui32, - oerrs->value.ui32, -#else - py_ifc_info = Py_BuildValue("(kkkkkkii)", - wbytes->value.ui32, - rbytes->value.ui32, - wpkts->value.ui32, - rpkts->value.ui32, - ierrs->value.ui32, - oerrs->value.ui32, -#endif - 0, // dropin not supported - 0 // dropout not supported - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - goto next; - -next: - ksp = ksp->ks_next; - } - - kstat_close(kc); - return py_retdict; - -error: - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (kc != NULL) - kstat_close(kc); - return NULL; -} - - -#ifndef EXPER_IP_AND_ALL_IRES -#define EXPER_IP_AND_ALL_IRES (1024+4) -#endif - -// a signaler for connections without an actual status -static int PSUTIL_CONN_NONE = 128; - -/* - * Return TCP and UDP connections opened by process. - * UNIX sockets are excluded. - * - * Thanks to: - * https://github.com/DavidGriffith/finx/blob/master/ - * nxsensor-3.5.0-1/src/sysdeps/solaris.c - * ...and: - * https://hg.java.net/hg/solaris~on-src/file/tip/usr/src/cmd/ - * cmd-inet/usr.bin/netstat/netstat.c - */ -static PyObject * -psutil_net_connections(PyObject *self, PyObject *args) -{ - long pid; - int sd = 0; - mib2_tcpConnEntry_t *tp = NULL; - mib2_udpEntry_t *ude; -#if defined(AF_INET6) - mib2_tcp6ConnEntry_t *tp6; - mib2_udp6Entry_t *ude6; -#endif - char buf[512]; - int i, flags, getcode, num_ent, state; - char lip[200], rip[200]; - int lport, rport; - int processed_pid; - int databuf_init = 0; - struct strbuf ctlbuf, databuf; - struct T_optmgmt_req *tor = (struct T_optmgmt_req *)buf; - struct T_optmgmt_ack *toa = (struct T_optmgmt_ack *)buf; - struct T_error_ack *tea = (struct T_error_ack *)buf; - struct opthdr *mibhdr; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_laddr = NULL; - PyObject *py_raddr = NULL; - PyObject *af_filter = NULL; - PyObject *type_filter = NULL; - - if (py_retlist == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) - goto error; - if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - goto error; - } - - sd = open("/dev/arp", O_RDWR); - if (sd == -1) { - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/dev/arp"); - goto error; - } - - /* - XXX - These 2 are used in ifconfig.c but they seem unnecessary - ret = ioctl(sd, I_PUSH, "tcp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - ret = ioctl(sd, I_PUSH, "udp"); - if (ret == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - */ - - // OK, this mess is basically copied and pasted from nxsensor project - // which copied and pasted it from netstat source code, mibget() - // function. Also see: - // http://stackoverflow.com/questions/8723598/ - tor->PRIM_type = T_SVR4_OPTMGMT_REQ; - tor->OPT_offset = sizeof (struct T_optmgmt_req); - tor->OPT_length = sizeof (struct opthdr); - tor->MGMT_flags = T_CURRENT; - mibhdr = (struct opthdr *)&tor[1]; - mibhdr->level = EXPER_IP_AND_ALL_IRES; - mibhdr->name = 0; - mibhdr->len = 0; - - ctlbuf.buf = buf; - ctlbuf.len = tor->OPT_offset + tor->OPT_length; - flags = 0; // request to be sent in non-priority - - if (putmsg(sd, &ctlbuf, (struct strbuf *)0, flags) == -1) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - mibhdr = (struct opthdr *)&toa[1]; - ctlbuf.maxlen = sizeof (buf); - - for (;;) { - flags = 0; - getcode = getmsg(sd, &ctlbuf, (struct strbuf *)0, &flags); - - if (getcode != MOREDATA || - ctlbuf.len < sizeof (struct T_optmgmt_ack) || - toa->PRIM_type != T_OPTMGMT_ACK || - toa->MGMT_flags != T_SUCCESS) - { - break; - } - if (ctlbuf.len >= sizeof (struct T_error_ack) && - tea->PRIM_type == T_ERROR_ACK) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_ACK"); - goto error; - } - if (getcode == 0 && - ctlbuf.len >= sizeof (struct T_optmgmt_ack) && - toa->PRIM_type == T_OPTMGMT_ACK && - toa->MGMT_flags == T_SUCCESS) - { - PyErr_SetString(PyExc_RuntimeError, "ERROR_T_OPTMGMT_ACK"); - goto error; - } - - databuf.maxlen = mibhdr->len; - databuf.len = 0; - databuf.buf = (char *)malloc((int)mibhdr->len); - if (!databuf.buf) { - PyErr_NoMemory(); - goto error; - } - databuf_init = 1; - - flags = 0; - getcode = getmsg(sd, (struct strbuf *)0, &databuf, &flags); - if (getcode < 0) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // TCPv4 - if (mibhdr->level == MIB2_TCP && mibhdr->name == MIB2_TCP_13) { - tp = (mib2_tcpConnEntry_t *)databuf.buf; - num_ent = mibhdr->len / sizeof(mib2_tcpConnEntry_t); - for (i = 0; i < num_ent; i++, tp++) { - processed_pid = tp->tcpConnCreationProcess; - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET, &tp->tcpConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET, &tp->tcpConnRemAddress, rip, sizeof(rip)); - lport = tp->tcpConnLocalPort; - rport = tp->tcpConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else { - py_raddr = Py_BuildValue("()"); - } - if (!py_raddr) - goto error; - state = tp->tcpConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_STREAM, - py_laddr, py_raddr, state, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } -#if defined(AF_INET6) - // TCPv6 - else if (mibhdr->level == MIB2_TCP6 && mibhdr->name == MIB2_TCP6_CONN) - { - tp6 = (mib2_tcp6ConnEntry_t *)databuf.buf; - num_ent = mibhdr->len / sizeof(mib2_tcp6ConnEntry_t); - - for (i = 0; i < num_ent; i++, tp6++) { - processed_pid = tp6->tcp6ConnCreationProcess; - if (pid != -1 && processed_pid != pid) - continue; - // construct local/remote addresses - inet_ntop(AF_INET6, &tp6->tcp6ConnLocalAddress, lip, sizeof(lip)); - inet_ntop(AF_INET6, &tp6->tcp6ConnRemAddress, rip, sizeof(rip)); - lport = tp6->tcp6ConnLocalPort; - rport = tp6->tcp6ConnRemPort; - - // contruct python tuple/list - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - if (rport != 0) - py_raddr = Py_BuildValue("(si)", rip, rport); - else - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - state = tp6->tcp6ConnEntryInfo.ce_state; - - // add item - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_STREAM, - py_laddr, py_raddr, state, processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } -#endif - // UDPv4 - else if (mibhdr->level == MIB2_UDP || mibhdr->level == MIB2_UDP_ENTRY) { - ude = (mib2_udpEntry_t *)databuf.buf; - num_ent = mibhdr->len / sizeof(mib2_udpEntry_t); - for (i = 0; i < num_ent; i++, ude++) { - processed_pid = ude->udpCreationProcess; - if (pid != -1 && processed_pid != pid) - continue; - // XXX Very ugly hack! It seems we get here only the first - // time we bump into a UDPv4 socket. PID is a very high - // number (clearly impossible) and the address does not - // belong to any valid interface. Not sure what else - // to do other than skipping. - if (processed_pid > 131072) - continue; - inet_ntop(AF_INET, &ude->udpLocalAddress, lip, sizeof(lip)); - lport = ude->udpLocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } -#if defined(AF_INET6) - // UDPv6 - else if (mibhdr->level == MIB2_UDP6 || - mibhdr->level == MIB2_UDP6_ENTRY) - { - ude6 = (mib2_udp6Entry_t *)databuf.buf; - num_ent = mibhdr->len / sizeof(mib2_udp6Entry_t); - for (i = 0; i < num_ent; i++, ude6++) { - processed_pid = ude6->udp6CreationProcess; - if (pid != -1 && processed_pid != pid) - continue; - inet_ntop(AF_INET6, &ude6->udp6LocalAddress, lip, sizeof(lip)); - lport = ude6->udp6LocalPort; - py_laddr = Py_BuildValue("(si)", lip, lport); - if (!py_laddr) - goto error; - py_raddr = Py_BuildValue("()"); - if (!py_raddr) - goto error; - py_tuple = Py_BuildValue("(iiiNNiI)", -1, AF_INET6, SOCK_DGRAM, - py_laddr, py_raddr, PSUTIL_CONN_NONE, - processed_pid); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - } -#endif - free(databuf.buf); - } - - close(sd); - return py_retlist; - -error: - Py_XDECREF(py_tuple); - Py_XDECREF(py_laddr); - Py_XDECREF(py_raddr); - Py_DECREF(py_retlist); - if (databuf_init == 1) - free(databuf.buf); - if (sd != 0) - close(sd); - return NULL; -} - - -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) -{ - float boot_time = 0.0; - struct utmpx *ut; - - while (NULL != (ut = getutxent())) { - if (ut->ut_type == BOOT_TIME) { - boot_time = (float)ut->ut_tv.tv_sec; - break; - } - } - endutent(); - if (boot_time != 0.0) { - return Py_BuildValue("f", boot_time); - } - else { - PyErr_SetString(PyExc_RuntimeError, "can't determine boot time"); - return NULL; - } -} - - -/* - * Return the number of physical CPU cores on the system. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) -{ - kstat_ctl_t *kc; - kstat_t *ksp; - int ncpus = 0; - - kc = kstat_open(); - if (kc == NULL) - goto error; - ksp = kstat_lookup(kc, "cpu_info", -1, NULL); - if (ksp == NULL) - goto error; - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_module, "cpu_info") != 0) - continue; - if (kstat_read(kc, ksp, NULL) == -1) - goto error; - ncpus += 1; - } - - kstat_close(kc); - if (ncpus > 0) - return Py_BuildValue("i", ncpus); - else - goto error; - -error: - // mimic os.cpu_count() - if (kc != NULL) - kstat_close(kc); - Py_RETURN_NONE; -} - - -/* - * Return stats about a particular network - * interface. References: - * https://github.com/dpaleino/wicd/blob/master/wicd/backends/be-ioctl.py - * http://www.i-scream.org/libstatgrab/ - */ -static PyObject* -psutil_net_if_stats(PyObject* self, PyObject* args) -{ - kstat_ctl_t *kc = NULL; - kstat_t *ksp; - kstat_named_t *knp; - int ret; - int sock = 0; - int duplex; - int speed; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - kc = kstat_open(); - if (kc == NULL) - goto error; - sock = socket(AF_INET, SOCK_DGRAM, 0); - if (sock == -1) - goto error; - - for (ksp = kc->kc_chain; ksp; ksp = ksp->ks_next) { - if (strcmp(ksp->ks_class, "net") == 0) { - struct ifreq ifr; - - kstat_read(kc, ksp, NULL); - if (ksp->ks_type != KSTAT_TYPE_NAMED) - continue; - if (strcmp(ksp->ks_class, "net") != 0) - continue; - - strncpy(ifr.ifr_name, ksp->ks_name, sizeof(ifr.ifr_name)); - ret = ioctl(sock, SIOCGIFFLAGS, &ifr); - if (ret == -1) - continue; // not a network interface - - // is up? - if ((ifr.ifr_flags & IFF_UP) != 0) { - if ((knp = kstat_data_lookup(ksp, "link_up")) != NULL) { - if (knp->value.ui32 != 0u) - py_is_up = Py_True; - else - py_is_up = Py_False; - } - else { - py_is_up = Py_True; - } - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - // duplex - duplex = 0; // unknown - if ((knp = kstat_data_lookup(ksp, "link_duplex")) != NULL) { - if (knp->value.ui32 == 1) - duplex = 1; // half - else if (knp->value.ui32 == 2) - duplex = 2; // full - } - - // speed - if ((knp = kstat_data_lookup(ksp, "ifspeed")) != NULL) - // expressed in bits per sec, we want mega bits per sec - speed = (int)knp->value.ui64 / 1000000; - else - speed = 0; - - // mtu - ret = ioctl(sock, SIOCGIFMTU, &ifr); - if (ret == -1) - goto error; - - py_ifc_info = Py_BuildValue("(Oiii)", py_is_up, duplex, speed, - ifr.ifr_mtu); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, ksp->ks_name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - } - - close(sock); - kstat_close(kc); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (sock != 0) - close(sock); - if (kc != NULL) - kstat_close(kc); - PyErr_SetFromErrno(PyExc_OSError); - return NULL; -} - - -/* - * define the psutil C module methods and initialize the module. - */ -static PyMethodDef -PsutilMethods[] = -{ - // --- process-related functions - {"proc_basic_info", psutil_proc_basic_info, METH_VARARGS, - "Return process ppid, rss, vms, ctime, nice, nthreads, status and tty"}, - {"proc_name_and_args", psutil_proc_name_and_args, METH_VARARGS, - "Return process name and args."}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return process user and system CPU times."}, - {"proc_cred", psutil_proc_cred, METH_VARARGS, - "Return process uids/gids."}, - {"query_process_thread", psutil_proc_query_thread, METH_VARARGS, - "Return info about a process thread"}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return process memory mappings"}, - {"proc_num_ctx_switches", psutil_proc_num_ctx_switches, METH_VARARGS, - "Return the number of context switches performed by process"}, - - // --- system-related functions - {"swap_mem", psutil_swap_mem, METH_VARARGS, - "Return information about system swap memory."}, - {"users", psutil_users, METH_VARARGS, - "Return currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-CPU times."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return a Python dict of tuples for disk I/O statistics."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return a Python dict of tuples for network I/O statistics."}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return system boot time in seconds since the EPOCH."}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Return the number of physical CPUs on the system."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return TCP and UDP syste-wide open connections."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NIC stats (isup, duplex, speed, mtu)"}, - -{NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int -psutil_sunos_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int -psutil_sunos_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_sunos", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_sunos_traverse, - psutil_sunos_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_sunos(void) - -#else -#define INITERROR return - -void init_psutil_sunos(void) -#endif -{ -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_sunos", PsutilMethods); -#endif - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - PyModule_AddIntConstant(module, "SSLEEP", SSLEEP); - PyModule_AddIntConstant(module, "SRUN", SRUN); - PyModule_AddIntConstant(module, "SZOMB", SZOMB); - PyModule_AddIntConstant(module, "SSTOP", SSTOP); - PyModule_AddIntConstant(module, "SIDL", SIDL); - PyModule_AddIntConstant(module, "SONPROC", SONPROC); - PyModule_AddIntConstant(module, "SWAIT", SWAIT); - - PyModule_AddIntConstant(module, "PRNODEV", PRNODEV); // for process tty - - PyModule_AddIntConstant(module, "TCPS_CLOSED", TCPS_CLOSED); - PyModule_AddIntConstant(module, "TCPS_CLOSING", TCPS_CLOSING); - PyModule_AddIntConstant(module, "TCPS_CLOSE_WAIT", TCPS_CLOSE_WAIT); - PyModule_AddIntConstant(module, "TCPS_LISTEN", TCPS_LISTEN); - PyModule_AddIntConstant(module, "TCPS_ESTABLISHED", TCPS_ESTABLISHED); - PyModule_AddIntConstant(module, "TCPS_SYN_SENT", TCPS_SYN_SENT); - PyModule_AddIntConstant(module, "TCPS_SYN_RCVD", TCPS_SYN_RCVD); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_1", TCPS_FIN_WAIT_1); - PyModule_AddIntConstant(module, "TCPS_FIN_WAIT_2", TCPS_FIN_WAIT_2); - PyModule_AddIntConstant(module, "TCPS_LAST_ACK", TCPS_LAST_ACK); - PyModule_AddIntConstant(module, "TCPS_TIME_WAIT", TCPS_TIME_WAIT); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_IDLE", TCPS_IDLE); - // sunos specific - PyModule_AddIntConstant(module, "TCPS_BOUND", TCPS_BOUND); - PyModule_AddIntConstant(module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - - if (module == NULL) - INITERROR; -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_sunos.h b/python/psutil/psutil/_psutil_sunos.h deleted file mode 100644 index f93dbfe0f..000000000 --- a/python/psutil/psutil/_psutil_sunos.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -// processes -static PyObject* psutil_proc_basic_info(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cred(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -static PyObject* psutil_proc_name_and_args(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_ctx_switches(PyObject* self, PyObject* args); -static PyObject* psutil_proc_query_thread(PyObject* self, PyObject* args); - -// system -static PyObject* psutil_boot_time(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); -static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_swap_mem(PyObject* self, PyObject* args); -static PyObject* psutil_users(PyObject* self, PyObject* args); -static PyObject* psutil_net_connections(PyObject* self, PyObject* args); -static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args); diff --git a/python/psutil/psutil/_psutil_windows.c b/python/psutil/psutil/_psutil_windows.c deleted file mode 100644 index 3e0f7a7cd..000000000 --- a/python/psutil/psutil/_psutil_windows.c +++ /dev/null @@ -1,3405 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Windows platform-specific module methods for _psutil_windows - */ - -// Fixes clash between winsock2.h and windows.h -#define WIN32_LEAN_AND_MEAN - -#include <Python.h> -#include <windows.h> -#include <Psapi.h> -#include <time.h> -#include <lm.h> -#include <WinIoCtl.h> -#include <tchar.h> -#include <tlhelp32.h> -#include <winsock2.h> -#include <iphlpapi.h> -#include <wtsapi32.h> -#include <ws2tcpip.h> - -// Link with Iphlpapi.lib -#pragma comment(lib, "IPHLPAPI.lib") - -#include "_psutil_windows.h" -#include "_psutil_common.h" -#include "arch/windows/security.h" -#include "arch/windows/process_info.h" -#include "arch/windows/process_handles.h" -#include "arch/windows/ntextapi.h" -#include "arch/windows/inet_ntop.h" - -#ifdef __MINGW32__ -#include "arch/windows/glpi.h" -#endif - - -/* - * ============================================================================ - * Utilities - * ============================================================================ - */ - - // a flag for connections without an actual status -static int PSUTIL_CONN_NONE = 128; - -#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x)) -#define FREE(x) HeapFree(GetProcessHeap(), 0, (x)) -#define LO_T ((float)1e-7) -#define HI_T (LO_T*4294967296.0) -#define BYTESWAP_USHORT(x) ((((USHORT)(x) << 8) | ((USHORT)(x) >> 8)) & 0xffff) -#ifndef AF_INET6 -#define AF_INET6 23 -#endif -#define _psutil_conn_decref_objs() \ - Py_DECREF(_AF_INET); \ - Py_DECREF(_AF_INET6);\ - Py_DECREF(_SOCK_STREAM);\ - Py_DECREF(_SOCK_DGRAM); - -typedef BOOL (WINAPI *LPFN_GLPI) - (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION, PDWORD); - -// fix for mingw32, see -// https://github.com/giampaolo/psutil/issues/351#c2 -typedef struct _DISK_PERFORMANCE_WIN_2008 { - LARGE_INTEGER BytesRead; - LARGE_INTEGER BytesWritten; - LARGE_INTEGER ReadTime; - LARGE_INTEGER WriteTime; - LARGE_INTEGER IdleTime; - DWORD ReadCount; - DWORD WriteCount; - DWORD QueueDepth; - DWORD SplitCount; - LARGE_INTEGER QueryTime; - DWORD StorageDeviceNumber; - WCHAR StorageManagerName[8]; -} DISK_PERFORMANCE_WIN_2008; - -// --- network connections mingw32 support -#ifndef _IPRTRMIB_H -typedef struct _MIB_TCP6ROW_OWNER_PID { - UCHAR ucLocalAddr[16]; - DWORD dwLocalScopeId; - DWORD dwLocalPort; - UCHAR ucRemoteAddr[16]; - DWORD dwRemoteScopeId; - DWORD dwRemotePort; - DWORD dwState; - DWORD dwOwningPid; -} MIB_TCP6ROW_OWNER_PID, *PMIB_TCP6ROW_OWNER_PID; - -typedef struct _MIB_TCP6TABLE_OWNER_PID { - DWORD dwNumEntries; - MIB_TCP6ROW_OWNER_PID table[ANY_SIZE]; -} MIB_TCP6TABLE_OWNER_PID, *PMIB_TCP6TABLE_OWNER_PID; -#endif - -#ifndef __IPHLPAPI_H__ -typedef struct in6_addr { - union { - UCHAR Byte[16]; - USHORT Word[8]; - } u; -} IN6_ADDR, *PIN6_ADDR, FAR *LPIN6_ADDR; - -typedef enum _UDP_TABLE_CLASS { - UDP_TABLE_BASIC, - UDP_TABLE_OWNER_PID, - UDP_TABLE_OWNER_MODULE -} UDP_TABLE_CLASS, *PUDP_TABLE_CLASS; - -typedef struct _MIB_UDPROW_OWNER_PID { - DWORD dwLocalAddr; - DWORD dwLocalPort; - DWORD dwOwningPid; -} MIB_UDPROW_OWNER_PID, *PMIB_UDPROW_OWNER_PID; - -typedef struct _MIB_UDPTABLE_OWNER_PID { - DWORD dwNumEntries; - MIB_UDPROW_OWNER_PID table[ANY_SIZE]; -} MIB_UDPTABLE_OWNER_PID, *PMIB_UDPTABLE_OWNER_PID; -#endif - -typedef struct _MIB_UDP6ROW_OWNER_PID { - UCHAR ucLocalAddr[16]; - DWORD dwLocalScopeId; - DWORD dwLocalPort; - DWORD dwOwningPid; -} MIB_UDP6ROW_OWNER_PID, *PMIB_UDP6ROW_OWNER_PID; - -typedef struct _MIB_UDP6TABLE_OWNER_PID { - DWORD dwNumEntries; - MIB_UDP6ROW_OWNER_PID table[ANY_SIZE]; -} MIB_UDP6TABLE_OWNER_PID, *PMIB_UDP6TABLE_OWNER_PID; - - -PIP_ADAPTER_ADDRESSES -psutil_get_nic_addresses() { - // allocate a 15 KB buffer to start with - int outBufLen = 15000; - DWORD dwRetVal = 0; - ULONG attempts = 0; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - - do { - pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen); - if (pAddresses == NULL) { - PyErr_NoMemory(); - return NULL; - } - - dwRetVal = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, pAddresses, - &outBufLen); - if (dwRetVal == ERROR_BUFFER_OVERFLOW) { - free(pAddresses); - pAddresses = NULL; - } - else { - break; - } - - attempts++; - } while ((dwRetVal == ERROR_BUFFER_OVERFLOW) && (attempts < 3)); - - if (dwRetVal != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, "GetAdaptersAddresses() failed."); - return NULL; - } - - return pAddresses; -} - - -/* - * ============================================================================ - * Public Python API - * ============================================================================ - */ - - -/* - * Return a Python float representing the system uptime expressed in seconds - * since the epoch. - */ -static PyObject * -psutil_boot_time(PyObject *self, PyObject *args) -{ - double uptime; - time_t pt; - FILETIME fileTime; - long long ll; - - GetSystemTimeAsFileTime(&fileTime); - - /* - HUGE thanks to: - http://johnstewien.spaces.live.com/blog/cns!E6885DB5CEBABBC8!831.entry - - This function converts the FILETIME structure to the 32 bit - Unix time structure. - The time_t is a 32-bit value for the number of seconds since - January 1, 1970. A FILETIME is a 64-bit for the number of - 100-nanosecond periods since January 1, 1601. Convert by - subtracting the number of 100-nanosecond period betwee 01-01-1970 - and 01-01-1601, from time_t the divide by 1e+7 to get to the same - base granularity. - */ - ll = (((LONGLONG)(fileTime.dwHighDateTime)) << 32) \ - + fileTime.dwLowDateTime; - pt = (time_t)((ll - 116444736000000000ull) / 10000000ull); - - // XXX - By using GetTickCount() time will wrap around to zero if the - // system is run continuously for 49.7 days. - uptime = GetTickCount() / 1000.00f; - return Py_BuildValue("d", (double)pt - uptime); -} - - -/* - * Return 1 if PID exists in the current process list, else 0. - */ -static PyObject * -psutil_pid_exists(PyObject *self, PyObject *args) -{ - long pid; - int status; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - status = psutil_pid_is_running(pid); - if (-1 == status) - return NULL; // exception raised in psutil_pid_is_running() - return PyBool_FromLong(status); -} - - -/* - * Return a Python list of all the PIDs running on the system. - */ -static PyObject * -psutil_pids(PyObject *self, PyObject *args) -{ - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - PyObject *pid = NULL; - PyObject *retlist = PyList_New(0); - - if (retlist == NULL) - return NULL; - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - goto error; - - for (i = 0; i < numberOfReturnedPIDs; i++) { - pid = Py_BuildValue("I", proclist[i]); - if (!pid) - goto error; - if (PyList_Append(retlist, pid)) - goto error; - Py_DECREF(pid); - } - - // free C array allocated for PIDs - free(proclist); - return retlist; - -error: - Py_XDECREF(pid); - Py_DECREF(retlist); - if (proclist != NULL) - free(proclist); - return NULL; -} - - -/* - * Kill a process given its PID. - */ -static PyObject * -psutil_proc_kill(PyObject *self, PyObject *args) -{ - HANDLE hProcess; - long pid; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (pid == 0) - return AccessDenied(); - - hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // see https://github.com/giampaolo/psutil/issues/24 - NoSuchProcess(); - } - else { - PyErr_SetFromWindowsErr(0); - } - return NULL; - } - - // kill the process - if (! TerminateProcess(hProcess, 0)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return NULL; - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Wait for process to terminate and return its exit code. - */ -static PyObject * -psutil_proc_wait(PyObject *self, PyObject *args) -{ - HANDLE hProcess; - DWORD ExitCode; - DWORD retVal; - long pid; - long timeout; - - if (! PyArg_ParseTuple(args, "ll", &pid, &timeout)) - return NULL; - if (pid == 0) - return AccessDenied(); - - hProcess = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, - FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) { - // no such process; we do not want to raise NSP but - // return None instead. - Py_RETURN_NONE; - } - else { - PyErr_SetFromWindowsErr(0); - return NULL; - } - } - - // wait until the process has terminated - Py_BEGIN_ALLOW_THREADS - retVal = WaitForSingleObject(hProcess, timeout); - Py_END_ALLOW_THREADS - - if (retVal == WAIT_FAILED) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(GetLastError()); - } - if (retVal == WAIT_TIMEOUT) { - CloseHandle(hProcess); - return Py_BuildValue("l", WAIT_TIMEOUT); - } - - // get the exit code; note: subprocess module (erroneously?) uses - // what returned by WaitForSingleObject - if (GetExitCodeProcess(hProcess, &ExitCode) == 0) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(GetLastError()); - } - CloseHandle(hProcess); -#if PY_MAJOR_VERSION >= 3 - return PyLong_FromLong((long) ExitCode); -#else - return PyInt_FromLong((long) ExitCode); -#endif -} - - -/* - * Return a Python tuple (user_time, kernel_time) - */ -static PyObject * -psutil_proc_cpu_times(PyObject *self, PyObject *args) -{ - long pid; - HANDLE hProcess; - FILETIME ftCreate, ftExit, ftKernel, ftUser; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) - return NULL; - if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { - CloseHandle(hProcess); - if (GetLastError() == ERROR_ACCESS_DENIED) { - // usually means the process has died so we throw a NoSuchProcess - // here - return NoSuchProcess(); - } - else { - PyErr_SetFromWindowsErr(0); - return NULL; - } - } - - CloseHandle(hProcess); - - /* - * User and kernel times are represented as a FILETIME structure - * wich contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - return Py_BuildValue( - "(dd)", - (double)(ftUser.dwHighDateTime * 429.4967296 + \ - ftUser.dwLowDateTime * 1e-7), - (double)(ftKernel.dwHighDateTime * 429.4967296 + \ - ftKernel.dwLowDateTime * 1e-7) - ); -} - - -/* - * Return a Python float indicating the process create time expressed in - * seconds since the epoch. - */ -static PyObject * -psutil_proc_create_time(PyObject *self, PyObject *args) -{ - long pid; - long long unix_time; - DWORD exitCode; - HANDLE hProcess; - BOOL ret; - FILETIME ftCreate, ftExit, ftKernel, ftUser; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - // special case for PIDs 0 and 4, return system boot time - if (0 == pid || 4 == pid) - return psutil_boot_time(NULL, NULL); - - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) - return NULL; - if (! GetProcessTimes(hProcess, &ftCreate, &ftExit, &ftKernel, &ftUser)) { - CloseHandle(hProcess); - if (GetLastError() == ERROR_ACCESS_DENIED) { - // usually means the process has died so we throw a - // NoSuchProcess here - return NoSuchProcess(); - } - else { - PyErr_SetFromWindowsErr(0); - return NULL; - } - } - - // Make sure the process is not gone as OpenProcess alone seems to be - // unreliable in doing so (it seems a previous call to p.wait() makes - // it unreliable). - // This check is important as creation time is used to make sure the - // process is still running. - ret = GetExitCodeProcess(hProcess, &exitCode); - CloseHandle(hProcess); - if (ret != 0) { - if (exitCode != STILL_ACTIVE) - return NoSuchProcess(); - } - else { - // Ignore access denied as it means the process is still alive. - // For all other errors, we want an exception. - if (GetLastError() != ERROR_ACCESS_DENIED) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - } - - /* - Convert the FILETIME structure to a Unix time. - It's the best I could find by googling and borrowing code here and there. - The time returned has a precision of 1 second. - */ - unix_time = ((LONGLONG)ftCreate.dwHighDateTime) << 32; - unix_time += ftCreate.dwLowDateTime - 116444736000000000LL; - unix_time /= 10000000; - return Py_BuildValue("d", (double)unix_time); -} - - - -/* - * Return the number of logical CPUs. - */ -static PyObject * -psutil_cpu_count_logical(PyObject *self, PyObject *args) -{ - SYSTEM_INFO system_info; - system_info.dwNumberOfProcessors = 0; - - GetSystemInfo(&system_info); - if (system_info.dwNumberOfProcessors == 0) - Py_RETURN_NONE; // mimic os.cpu_count() - else - return Py_BuildValue("I", system_info.dwNumberOfProcessors); -} - - -/* - * Return the number of physical CPU cores. - */ -static PyObject * -psutil_cpu_count_phys(PyObject *self, PyObject *args) -{ - LPFN_GLPI glpi; - DWORD rc; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION buffer = NULL; - PSYSTEM_LOGICAL_PROCESSOR_INFORMATION ptr = NULL; - DWORD length = 0; - DWORD offset = 0; - int ncpus = 0; - - glpi = (LPFN_GLPI)GetProcAddress(GetModuleHandle(TEXT("kernel32")), - "GetLogicalProcessorInformation"); - if (glpi == NULL) - goto return_none; - - while (1) { - rc = glpi(buffer, &length); - if (rc == FALSE) { - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - if (buffer) - free(buffer); - buffer = (PSYSTEM_LOGICAL_PROCESSOR_INFORMATION)malloc( - length); - if (NULL == buffer) { - PyErr_NoMemory(); - return NULL; - } - } - else { - goto return_none; - } - } - else { - break; - } - } - - ptr = buffer; - while (offset + sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION) <= length) { - if (ptr->Relationship == RelationProcessorCore) - ncpus += 1; - offset += sizeof(SYSTEM_LOGICAL_PROCESSOR_INFORMATION); - ptr++; - } - - free(buffer); - if (ncpus == 0) - goto return_none; - else - return Py_BuildValue("i", ncpus); - -return_none: - // mimic os.cpu_count() - if (buffer != NULL) - free(buffer); - Py_RETURN_NONE; -} - - -/* - * Return process cmdline as a Python list of cmdline arguments. - */ -static PyObject * -psutil_proc_cmdline(PyObject *self, PyObject *args) { - long pid; - int pid_return; - PyObject *arglist; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if ((pid == 0) || (pid == 4)) - return Py_BuildValue("[]"); - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) - return NoSuchProcess(); - if (pid_return == -1) - return NULL; - - // XXX the assumptio below probably needs to go away - - // May fail any of several ReadProcessMemory calls etc. and - // not indicate a real problem so we ignore any errors and - // just live without commandline. - arglist = psutil_get_arg_list(pid); - if ( NULL == arglist ) { - // carry on anyway, clear any exceptions too - PyErr_Clear(); - return Py_BuildValue("[]"); - } - - return arglist; -} - - -/* - * Return process executable path. - */ -static PyObject * -psutil_proc_exe(PyObject *self, PyObject *args) { - long pid; - HANDLE hProcess; - wchar_t exe[MAX_PATH]; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION); - if (NULL == hProcess) - return NULL; - if (GetProcessImageFileNameW(hProcess, exe, MAX_PATH) == 0) { - CloseHandle(hProcess); - PyErr_SetFromWindowsErr(0); - return NULL; - } - CloseHandle(hProcess); - return Py_BuildValue("u", exe); -} - - -/* - * Return process base name. - * Note: psutil_proc_exe() is attempted first because it's faster - * but it raise AccessDenied for processes owned by other users - * in which case we fall back on using this. - */ -static PyObject * -psutil_proc_name(PyObject *self, PyObject *args) { - long pid; - int ok; - PROCESSENTRY32 pentry; - HANDLE hSnapShot; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, pid); - if (hSnapShot == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - pentry.dwSize = sizeof(PROCESSENTRY32); - ok = Process32First(hSnapShot, &pentry); - if (! ok) { - CloseHandle(hSnapShot); - PyErr_SetFromWindowsErr(0); - return NULL; - } - while (ok) { - if (pentry.th32ProcessID == pid) { - CloseHandle(hSnapShot); - return Py_BuildValue("s", pentry.szExeFile); - } - ok = Process32Next(hSnapShot, &pentry); - } - - CloseHandle(hSnapShot); - NoSuchProcess(); - return NULL; -} - - -/* - * Return process memory information as a Python tuple. - */ -static PyObject * -psutil_proc_memory_info(PyObject *self, PyObject *args) -{ - HANDLE hProcess; - DWORD pid; -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - PROCESS_MEMORY_COUNTERS_EX cnt; -#else - PROCESS_MEMORY_COUNTERS cnt; -#endif - SIZE_T private = 0; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid); - if (NULL == hProcess) - return NULL; - - if (! GetProcessMemoryInfo(hProcess, (PPROCESS_MEMORY_COUNTERS)&cnt, - sizeof(cnt))) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(0); - } - -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - private = cnt.PrivateUsage; -#endif - - CloseHandle(hProcess); - - // PROCESS_MEMORY_COUNTERS values are defined as SIZE_T which on 64bits - // is an (unsigned long long) and on 32bits is an (unsigned int). - // "_WIN64" is defined if we're running a 64bit Python interpreter not - // exclusively if the *system* is 64bit. -#if defined(_WIN64) - return Py_BuildValue( - "(kKKKKKKKKK)", - cnt.PageFaultCount, // unsigned long - (unsigned long long)cnt.PeakWorkingSetSize, - (unsigned long long)cnt.WorkingSetSize, - (unsigned long long)cnt.QuotaPeakPagedPoolUsage, - (unsigned long long)cnt.QuotaPagedPoolUsage, - (unsigned long long)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned long long)cnt.QuotaNonPagedPoolUsage, - (unsigned long long)cnt.PagefileUsage, - (unsigned long long)cnt.PeakPagefileUsage, - (unsigned long long)private); -#else - return Py_BuildValue( - "(kIIIIIIIII)", - cnt.PageFaultCount, // unsigned long - (unsigned int)cnt.PeakWorkingSetSize, - (unsigned int)cnt.WorkingSetSize, - (unsigned int)cnt.QuotaPeakPagedPoolUsage, - (unsigned int)cnt.QuotaPagedPoolUsage, - (unsigned int)cnt.QuotaPeakNonPagedPoolUsage, - (unsigned int)cnt.QuotaNonPagedPoolUsage, - (unsigned int)cnt.PagefileUsage, - (unsigned int)cnt.PeakPagefileUsage, - (unsigned int)private); -#endif -} - - -/* - * Alternative implementation of the one above but bypasses ACCESS DENIED. - */ -static PyObject * -psutil_proc_memory_info_2(PyObject *self, PyObject *args) -{ - DWORD pid; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - SIZE_T private; - unsigned long pfault_count; - -#if defined(_WIN64) - unsigned long long m1, m2, m3, m4, m5, m6, m7, m8; -#else - unsigned int m1, m2, m3, m4, m5, m6, m7, m8; -#endif - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - -#if (_WIN32_WINNT >= 0x0501) // Windows XP with SP2 - private = process->PrivatePageCount; -#else - private = 0; -#endif - pfault_count = process->PageFaultCount; - - m1 = process->PeakWorkingSetSize; - m2 = process->WorkingSetSize; - m3 = process->QuotaPeakPagedPoolUsage; - m4 = process->QuotaPagedPoolUsage; - m5 = process->QuotaPeakNonPagedPoolUsage; - m6 = process->QuotaNonPagedPoolUsage; - m7 = process->PagefileUsage; - m8 = process->PeakPagefileUsage; - - free(buffer); - - // SYSTEM_PROCESS_INFORMATION values are defined as SIZE_T which on 64 - // bits is an (unsigned long long) and on 32bits is an (unsigned int). - // "_WIN64" is defined if we're running a 64bit Python interpreter not - // exclusively if the *system* is 64bit. -#if defined(_WIN64) - return Py_BuildValue("(kKKKKKKKKK)", -#else - return Py_BuildValue("(kIIIIIIIII)", -#endif - pfault_count, m1, m2, m3, m4, m5, m6, m7, m8, private); -} - - -/* - * Return a Python integer indicating the total amount of physical memory - * in bytes. - */ -static PyObject * -psutil_virtual_mem(PyObject *self, PyObject *args) -{ - MEMORYSTATUSEX memInfo; - memInfo.dwLength = sizeof(MEMORYSTATUSEX); - - if (! GlobalMemoryStatusEx(&memInfo)) - return PyErr_SetFromWindowsErr(0); - return Py_BuildValue("(LLLLLL)", - memInfo.ullTotalPhys, // total - memInfo.ullAvailPhys, // avail - memInfo.ullTotalPageFile, // total page file - memInfo.ullAvailPageFile, // avail page file - memInfo.ullTotalVirtual, // total virtual - memInfo.ullAvailVirtual); // avail virtual -} - - -/* - * Retrieves system CPU timing information as a (user, system, idle) - * tuple. On a multiprocessor system, the values returned are the - * sum of the designated times across all processors. - */ -static PyObject * -psutil_cpu_times(PyObject *self, PyObject *args) -{ - float idle, kernel, user, system; - FILETIME idle_time, kernel_time, user_time; - - if (!GetSystemTimes(&idle_time, &kernel_time, &user_time)) - return PyErr_SetFromWindowsErr(0); - - idle = (float)((HI_T * idle_time.dwHighDateTime) + \ - (LO_T * idle_time.dwLowDateTime)); - user = (float)((HI_T * user_time.dwHighDateTime) + \ - (LO_T * user_time.dwLowDateTime)); - kernel = (float)((HI_T * kernel_time.dwHighDateTime) + \ - (LO_T * kernel_time.dwLowDateTime)); - - // Kernel time includes idle time. - // We return only busy kernel time subtracting idle time from - // kernel time. - system = (kernel - idle); - return Py_BuildValue("(fff)", user, system, idle); -} - - -/* - * Same as above but for all system CPUs. - */ -static PyObject * -psutil_per_cpu_times(PyObject *self, PyObject *args) -{ - float idle, kernel, user; - typedef DWORD (_stdcall * NTQSI_PROC) (int, PVOID, ULONG, PULONG); - NTQSI_PROC NtQuerySystemInformation; - HINSTANCE hNtDll; - SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *sppi = NULL; - SYSTEM_INFO si; - UINT i; - PyObject *arg = NULL; - PyObject *retlist = PyList_New(0); - - if (retlist == NULL) - return NULL; - - // dynamic linking is mandatory to use NtQuerySystemInformation - hNtDll = LoadLibrary(TEXT("ntdll.dll")); - if (hNtDll != NULL) { - // gets NtQuerySystemInformation address - NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress( - hNtDll, "NtQuerySystemInformation"); - - if (NtQuerySystemInformation != NULL) - { - // retrives number of processors - GetSystemInfo(&si); - - // allocates an array of SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION - // structures, one per processor - sppi = (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION *) \ - malloc(si.dwNumberOfProcessors * \ - sizeof(SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION)); - if (sppi != NULL) - { - // gets cpu time informations - if (0 == NtQuerySystemInformation( - SystemProcessorPerformanceInformation, - sppi, - si.dwNumberOfProcessors * sizeof - (SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION), - NULL) - ) - { - // computes system global times summing each - // processor value - idle = user = kernel = 0; - for (i = 0; i < si.dwNumberOfProcessors; i++) { - arg = NULL; - user = (float)((HI_T * sppi[i].UserTime.HighPart) + - (LO_T * sppi[i].UserTime.LowPart)); - idle = (float)((HI_T * sppi[i].IdleTime.HighPart) + - (LO_T * sppi[i].IdleTime.LowPart)); - kernel = (float)((HI_T * sppi[i].KernelTime.HighPart) + - (LO_T * sppi[i].KernelTime.LowPart)); - // kernel time includes idle time on windows - // we return only busy kernel time subtracting - // idle time from kernel time - arg = Py_BuildValue("(ddd)", - user, - kernel - idle, - idle); - if (!arg) - goto error; - if (PyList_Append(retlist, arg)) - goto error; - Py_DECREF(arg); - } - free(sppi); - FreeLibrary(hNtDll); - return retlist; - - } // END NtQuerySystemInformation - } // END malloc SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION - } // END GetProcAddress - } // END LoadLibrary - goto error; - -error: - Py_XDECREF(arg); - Py_DECREF(retlist); - if (sppi) - free(sppi); - if (hNtDll) - FreeLibrary(hNtDll); - PyErr_SetFromWindowsErr(0); - return NULL; -} - - -/* - * Return process current working directory as a Python string. - */ - -static PyObject * -psutil_proc_cwd(PyObject *self, PyObject *args) -{ - long pid; - HANDLE processHandle = NULL; - PVOID pebAddress; - PVOID rtlUserProcParamsAddress; - UNICODE_STRING currentDirectory; - WCHAR *currentDirectoryContent = NULL; - PyObject *returnPyObj = NULL; - PyObject *cwd_from_wchar = NULL; - PyObject *cwd = NULL; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - processHandle = psutil_handle_from_pid(pid); - if (processHandle == NULL) - return NULL; - - pebAddress = psutil_get_peb_address(processHandle); - - // get the address of ProcessParameters -#ifdef _WIN64 - if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 32, - &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) -#else - if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 0x10, - &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) -#endif - { - CloseHandle(processHandle); - if (GetLastError() == ERROR_PARTIAL_COPY) { - // this occurs quite often with system processes - return AccessDenied(); - } - else { - return PyErr_SetFromWindowsErr(0); - } - } - - // Read the currentDirectory UNICODE_STRING structure. - // 0x24 refers to "CurrentDirectoryPath" of RTL_USER_PROCESS_PARAMETERS - // structure, see: - // http://wj32.wordpress.com/2009/01/24/ - // howto-get-the-command-line-of-processes/ -#ifdef _WIN64 - if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 56, - ¤tDirectory, sizeof(currentDirectory), NULL)) -#else - if (!ReadProcessMemory(processHandle, - (PCHAR)rtlUserProcParamsAddress + 0x24, - ¤tDirectory, sizeof(currentDirectory), NULL)) -#endif - { - CloseHandle(processHandle); - if (GetLastError() == ERROR_PARTIAL_COPY) { - // this occurs quite often with system processes - return AccessDenied(); - } - else { - return PyErr_SetFromWindowsErr(0); - } - } - - // allocate memory to hold cwd - currentDirectoryContent = (WCHAR *)malloc(currentDirectory.Length + 1); - if (currentDirectoryContent == NULL) { - PyErr_NoMemory(); - goto error; - } - - // read cwd - if (!ReadProcessMemory(processHandle, currentDirectory.Buffer, - currentDirectoryContent, currentDirectory.Length, - NULL)) - { - if (GetLastError() == ERROR_PARTIAL_COPY) { - // this occurs quite often with system processes - AccessDenied(); - } - else { - PyErr_SetFromWindowsErr(0); - } - goto error; - } - - // null-terminate the string to prevent wcslen from returning - // incorrect length the length specifier is in characters, but - // currentDirectory.Length is in bytes - currentDirectoryContent[(currentDirectory.Length / sizeof(WCHAR))] = '\0'; - - // convert wchar array to a Python unicode string, and then to UTF8 - cwd_from_wchar = PyUnicode_FromWideChar(currentDirectoryContent, - wcslen(currentDirectoryContent)); - if (cwd_from_wchar == NULL) - goto error; - -#if PY_MAJOR_VERSION >= 3 - cwd = PyUnicode_FromObject(cwd_from_wchar); -#else - cwd = PyUnicode_AsUTF8String(cwd_from_wchar); -#endif - if (cwd == NULL) - goto error; - - // decrement the reference count on our temp unicode str to avoid - // mem leak - returnPyObj = Py_BuildValue("N", cwd); - if (!returnPyObj) - goto error; - - Py_DECREF(cwd_from_wchar); - - CloseHandle(processHandle); - free(currentDirectoryContent); - return returnPyObj; - -error: - Py_XDECREF(cwd_from_wchar); - Py_XDECREF(cwd); - Py_XDECREF(returnPyObj); - if (currentDirectoryContent != NULL) - free(currentDirectoryContent); - if (processHandle != NULL) - CloseHandle(processHandle); - return NULL; -} - - -/* - * Resume or suspends a process - */ -int -psutil_proc_suspend_or_resume(DWORD pid, int suspend) -{ - // a huge thanks to http://www.codeproject.com/KB/threads/pausep.aspx - HANDLE hThreadSnap = NULL; - THREADENTRY32 te32 = {0}; - - if (pid == 0) { - AccessDenied(); - return FALSE; - } - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - return FALSE; - } - - // Fill in the size of the structure before using it - te32.dwSize = sizeof(THREADENTRY32); - - if (! Thread32First(hThreadSnap, &te32)) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hThreadSnap); - return FALSE; - } - - // Walk the thread snapshot to find all threads of the process. - // If the thread belongs to the process, add its information - // to the display list. - do - { - if (te32.th32OwnerProcessID == pid) - { - HANDLE hThread = OpenThread(THREAD_SUSPEND_RESUME, FALSE, - te32.th32ThreadID); - if (hThread == NULL) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hThread); - CloseHandle(hThreadSnap); - return FALSE; - } - if (suspend == 1) - { - if (SuspendThread(hThread) == (DWORD) - 1) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hThread); - CloseHandle(hThreadSnap); - return FALSE; - } - } - else - { - if (ResumeThread(hThread) == (DWORD) - 1) { - PyErr_SetFromWindowsErr(0); - CloseHandle(hThread); - CloseHandle(hThreadSnap); - return FALSE; - } - } - CloseHandle(hThread); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle(hThreadSnap); - return TRUE; -} - - -static PyObject * -psutil_proc_suspend(PyObject *self, PyObject *args) -{ - long pid; - int suspend = 1; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_suspend_or_resume(pid, suspend)) - return NULL; - Py_RETURN_NONE; -} - - -static PyObject * -psutil_proc_resume(PyObject *self, PyObject *args) -{ - long pid; - int suspend = 0; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_proc_suspend_or_resume(pid, suspend)) - return NULL; - Py_RETURN_NONE; -} - - -static PyObject * -psutil_proc_threads(PyObject *self, PyObject *args) -{ - HANDLE hThread; - THREADENTRY32 te32 = {0}; - long pid; - int pid_return; - int rc; - FILETIME ftDummy, ftKernel, ftUser; - PyObject *retList = PyList_New(0); - PyObject *pyTuple = NULL; - HANDLE hThreadSnap = NULL; - - if (retList == NULL) - return NULL; - if (! PyArg_ParseTuple(args, "l", &pid)) - goto error; - if (pid == 0) { - // raise AD instead of returning 0 as procexp is able to - // retrieve useful information somehow - AccessDenied(); - goto error; - } - - pid_return = psutil_pid_is_running(pid); - if (pid_return == 0) { - NoSuchProcess(); - goto error; - } - if (pid_return == -1) - goto error; - - hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); - if (hThreadSnap == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - // Fill in the size of the structure before using it - te32.dwSize = sizeof(THREADENTRY32); - - if (! Thread32First(hThreadSnap, &te32)) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - // Walk the thread snapshot to find all threads of the process. - // If the thread belongs to the process, increase the counter. - do { - if (te32.th32OwnerProcessID == pid) { - pyTuple = NULL; - hThread = NULL; - hThread = OpenThread(THREAD_QUERY_INFORMATION, - FALSE, te32.th32ThreadID); - if (hThread == NULL) { - // thread has disappeared on us - continue; - } - - rc = GetThreadTimes(hThread, &ftDummy, &ftDummy, &ftKernel, - &ftUser); - if (rc == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - /* - * User and kernel times are represented as a FILETIME structure - * wich contains a 64-bit value representing the number of - * 100-nanosecond intervals since January 1, 1601 (UTC): - * http://msdn.microsoft.com/en-us/library/ms724284(VS.85).aspx - * To convert it into a float representing the seconds that the - * process has executed in user/kernel mode I borrowed the code - * below from Python's Modules/posixmodule.c - */ - pyTuple = Py_BuildValue( - "kdd", - te32.th32ThreadID, - (double)(ftUser.dwHighDateTime * 429.4967296 + \ - ftUser.dwLowDateTime * 1e-7), - (double)(ftKernel.dwHighDateTime * 429.4967296 + \ - ftKernel.dwLowDateTime * 1e-7)); - if (!pyTuple) - goto error; - if (PyList_Append(retList, pyTuple)) - goto error; - Py_DECREF(pyTuple); - - CloseHandle(hThread); - } - } while (Thread32Next(hThreadSnap, &te32)); - - CloseHandle(hThreadSnap); - return retList; - -error: - Py_XDECREF(pyTuple); - Py_DECREF(retList); - if (hThread != NULL) - CloseHandle(hThread); - if (hThreadSnap != NULL) - CloseHandle(hThreadSnap); - return NULL; -} - - -static PyObject * -psutil_proc_open_files(PyObject *self, PyObject *args) -{ - long pid; - HANDLE processHandle; - DWORD access = PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION; - PyObject *filesList; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - processHandle = psutil_handle_from_pid_waccess(pid, access); - if (processHandle == NULL) - return NULL; - filesList = psutil_get_open_files(pid, processHandle); - CloseHandle(processHandle); - if (filesList == NULL) - return PyErr_SetFromWindowsErr(0); - return filesList; -} - - -/* - Accept a filename's drive in native format like "\Device\HarddiskVolume1\" - and return the corresponding drive letter (e.g. "C:\\"). - If no match is found return an empty string. -*/ -static PyObject * -psutil_win32_QueryDosDevice(PyObject *self, PyObject *args) -{ - LPCTSTR lpDevicePath; - TCHAR d = TEXT('A'); - TCHAR szBuff[5]; - - if (!PyArg_ParseTuple(args, "s", &lpDevicePath)) - return NULL; - - while (d <= TEXT('Z')) { - TCHAR szDeviceName[3] = {d, TEXT(':'), TEXT('\0')}; - TCHAR szTarget[512] = {0}; - if (QueryDosDevice(szDeviceName, szTarget, 511) != 0) { - if (_tcscmp(lpDevicePath, szTarget) == 0) { - _stprintf_s(szBuff, _countof(szBuff), TEXT("%c:"), d); - return Py_BuildValue("s", szBuff); - } - } - d++; - } - return Py_BuildValue("s", ""); -} - - -/* - * Return process username as a "DOMAIN//USERNAME" string. - */ -static PyObject * -psutil_proc_username(PyObject *self, PyObject *args) -{ - long pid; - HANDLE processHandle; - HANDLE tokenHandle; - PTOKEN_USER user; - ULONG bufferSize; - PTSTR name; - ULONG nameSize; - PTSTR domainName; - ULONG domainNameSize; - SID_NAME_USE nameUse; - PTSTR fullName; - PyObject *returnObject; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - processHandle = psutil_handle_from_pid_waccess( - pid, PROCESS_QUERY_INFORMATION); - if (processHandle == NULL) - return NULL; - - if (!OpenProcessToken(processHandle, TOKEN_QUERY, &tokenHandle)) { - CloseHandle(processHandle); - return PyErr_SetFromWindowsErr(0); - } - - CloseHandle(processHandle); - - // Get the user SID. - - bufferSize = 0x100; - user = malloc(bufferSize); - if (user == NULL) - return PyErr_NoMemory(); - - if (!GetTokenInformation(tokenHandle, TokenUser, user, bufferSize, - &bufferSize)) - { - free(user); - user = malloc(bufferSize); - if (user == NULL) { - CloseHandle(tokenHandle); - return PyErr_NoMemory(); - } - if (!GetTokenInformation(tokenHandle, TokenUser, user, bufferSize, - &bufferSize)) - { - free(user); - CloseHandle(tokenHandle); - return PyErr_SetFromWindowsErr(0); - } - } - - CloseHandle(tokenHandle); - - // resolve the SID to a name - nameSize = 0x100; - domainNameSize = 0x100; - - name = malloc(nameSize * sizeof(TCHAR)); - if (name == NULL) - return PyErr_NoMemory(); - domainName = malloc(domainNameSize * sizeof(TCHAR)); - if (domainName == NULL) - return PyErr_NoMemory(); - - if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, domainName, - &domainNameSize, &nameUse)) - { - free(name); - free(domainName); - name = malloc(nameSize * sizeof(TCHAR)); - if (name == NULL) - return PyErr_NoMemory(); - domainName = malloc(domainNameSize * sizeof(TCHAR)); - if (domainName == NULL) - return PyErr_NoMemory(); - if (!LookupAccountSid(NULL, user->User.Sid, name, &nameSize, - domainName, &domainNameSize, &nameUse)) - { - free(name); - free(domainName); - free(user); - - return PyErr_SetFromWindowsErr(0); - } - } - - nameSize = _tcslen(name); - domainNameSize = _tcslen(domainName); - - // build the full username string - fullName = malloc((domainNameSize + 1 + nameSize + 1) * sizeof(TCHAR)); - if (fullName == NULL) { - free(name); - free(domainName); - free(user); - return PyErr_NoMemory(); - } - memcpy(fullName, domainName, domainNameSize); - fullName[domainNameSize] = '\\'; - memcpy(&fullName[domainNameSize + 1], name, nameSize); - fullName[domainNameSize + 1 + nameSize] = '\0'; - - returnObject = PyUnicode_Decode( - fullName, _tcslen(fullName), Py_FileSystemDefaultEncoding, "replace"); - - free(fullName); - free(name); - free(domainName); - free(user); - - return returnObject; -} - - -/* - * Return a list of network connections opened by a process - */ -static PyObject * -psutil_net_connections(PyObject *self, PyObject *args) -{ - static long null_address[4] = { 0, 0, 0, 0 }; - - unsigned long pid; - PyObject *connectionsList; - PyObject *connectionTuple = NULL; - PyObject *af_filter = NULL; - PyObject *type_filter = NULL; - - PyObject *_AF_INET = PyLong_FromLong((long)AF_INET); - PyObject *_AF_INET6 = PyLong_FromLong((long)AF_INET6); - PyObject *_SOCK_STREAM = PyLong_FromLong((long)SOCK_STREAM); - PyObject *_SOCK_DGRAM = PyLong_FromLong((long)SOCK_DGRAM); - - typedef PSTR (NTAPI * _RtlIpv4AddressToStringA)(struct in_addr *, PSTR); - _RtlIpv4AddressToStringA rtlIpv4AddressToStringA; - typedef PSTR (NTAPI * _RtlIpv6AddressToStringA)(struct in6_addr *, PSTR); - _RtlIpv6AddressToStringA rtlIpv6AddressToStringA; - typedef DWORD (WINAPI * _GetExtendedTcpTable)(PVOID, PDWORD, BOOL, ULONG, - TCP_TABLE_CLASS, ULONG); - _GetExtendedTcpTable getExtendedTcpTable; - typedef DWORD (WINAPI * _GetExtendedUdpTable)(PVOID, PDWORD, BOOL, ULONG, - UDP_TABLE_CLASS, ULONG); - _GetExtendedUdpTable getExtendedUdpTable; - PVOID table = NULL; - DWORD tableSize; - PMIB_TCPTABLE_OWNER_PID tcp4Table; - PMIB_UDPTABLE_OWNER_PID udp4Table; - PMIB_TCP6TABLE_OWNER_PID tcp6Table; - PMIB_UDP6TABLE_OWNER_PID udp6Table; - ULONG i; - CHAR addressBufferLocal[65]; - PyObject *addressTupleLocal = NULL; - CHAR addressBufferRemote[65]; - PyObject *addressTupleRemote = NULL; - - if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) { - _psutil_conn_decref_objs(); - return NULL; - } - - if (!PySequence_Check(af_filter) || !PySequence_Check(type_filter)) { - _psutil_conn_decref_objs(); - PyErr_SetString(PyExc_TypeError, "arg 2 or 3 is not a sequence"); - return NULL; - } - - if (pid != -1) { - if (psutil_pid_is_running(pid) == 0) { - _psutil_conn_decref_objs(); - return NoSuchProcess(); - } - } - - // Import some functions. - { - HMODULE ntdll; - HMODULE iphlpapi; - - ntdll = LoadLibrary(TEXT("ntdll.dll")); - rtlIpv4AddressToStringA = (_RtlIpv4AddressToStringA)GetProcAddress( - ntdll, "RtlIpv4AddressToStringA"); - rtlIpv6AddressToStringA = (_RtlIpv6AddressToStringA)GetProcAddress( - ntdll, "RtlIpv6AddressToStringA"); - /* TODO: Check these two function pointers */ - - iphlpapi = LoadLibrary(TEXT("iphlpapi.dll")); - getExtendedTcpTable = (_GetExtendedTcpTable)GetProcAddress(iphlpapi, - "GetExtendedTcpTable"); - getExtendedUdpTable = (_GetExtendedUdpTable)GetProcAddress(iphlpapi, - "GetExtendedUdpTable"); - FreeLibrary(ntdll); - FreeLibrary(iphlpapi); - } - - if ((getExtendedTcpTable == NULL) || (getExtendedUdpTable == NULL)) { - PyErr_SetString(PyExc_NotImplementedError, - "feature not supported on this Windows version"); - _psutil_conn_decref_objs(); - return NULL; - } - - connectionsList = PyList_New(0); - if (connectionsList == NULL) { - _psutil_conn_decref_objs(); - return NULL; - } - - // TCP IPv4 - - if ((PySequence_Contains(af_filter, _AF_INET) == 1) && - (PySequence_Contains(type_filter, _SOCK_STREAM) == 1)) - { - table = NULL; - connectionTuple = NULL; - addressTupleLocal = NULL; - addressTupleRemote = NULL; - tableSize = 0; - getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET, - TCP_TABLE_OWNER_PID_ALL, 0); - - table = malloc(tableSize); - if (table == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET, - TCP_TABLE_OWNER_PID_ALL, 0) == 0) - { - tcp4Table = table; - - for (i = 0; i < tcp4Table->dwNumEntries; i++) - { - if (pid != -1) { - if (tcp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (tcp4Table->table[i].dwLocalAddr != 0 || - tcp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwLocalAddr; - rtlIpv4AddressToStringA(&addr, addressBufferLocal); - addressTupleLocal = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp4Table->table[i].dwLocalPort)); - } - else { - addressTupleLocal = PyTuple_New(0); - } - - if (addressTupleLocal == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((tcp4Table->table[i].dwRemoteAddr != 0 || - tcp4Table->table[i].dwRemotePort != 0) && - (tcp4Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in_addr addr; - - addr.S_un.S_addr = tcp4Table->table[i].dwRemoteAddr; - rtlIpv4AddressToStringA(&addr, addressBufferRemote); - addressTupleRemote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp4Table->table[i].dwRemotePort)); - } - else - { - addressTupleRemote = PyTuple_New(0); - } - - if (addressTupleRemote == NULL) - goto error; - - connectionTuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_STREAM, - addressTupleLocal, - addressTupleRemote, - tcp4Table->table[i].dwState, - tcp4Table->table[i].dwOwningPid); - if (!connectionTuple) - goto error; - if (PyList_Append(connectionsList, connectionTuple)) - goto error; - Py_DECREF(connectionTuple); - } - } - - free(table); - } - - // TCP IPv6 - - if ((PySequence_Contains(af_filter, _AF_INET6) == 1) && - (PySequence_Contains(type_filter, _SOCK_STREAM) == 1)) - { - table = NULL; - connectionTuple = NULL; - addressTupleLocal = NULL; - addressTupleRemote = NULL; - tableSize = 0; - getExtendedTcpTable(NULL, &tableSize, FALSE, AF_INET6, - TCP_TABLE_OWNER_PID_ALL, 0); - - table = malloc(tableSize); - if (table == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (getExtendedTcpTable(table, &tableSize, FALSE, AF_INET6, - TCP_TABLE_OWNER_PID_ALL, 0) == 0) - { - tcp6Table = table; - - for (i = 0; i < tcp6Table->dwNumEntries; i++) - { - if (pid != -1) { - if (tcp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(tcp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || tcp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucLocalAddr, 16); - rtlIpv6AddressToStringA(&addr, addressBufferLocal); - addressTupleLocal = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(tcp6Table->table[i].dwLocalPort)); - } - else - { - addressTupleLocal = PyTuple_New(0); - } - - if (addressTupleLocal == NULL) - goto error; - - // On Windows <= XP, remote addr is filled even if socket - // is in LISTEN mode in which case we just ignore it. - if ((memcmp(tcp6Table->table[i].ucRemoteAddr, null_address, 16) - != 0 || - tcp6Table->table[i].dwRemotePort != 0) && - (tcp6Table->table[i].dwState != MIB_TCP_STATE_LISTEN)) - { - struct in6_addr addr; - - memcpy(&addr, tcp6Table->table[i].ucRemoteAddr, 16); - rtlIpv6AddressToStringA(&addr, addressBufferRemote); - addressTupleRemote = Py_BuildValue( - "(si)", - addressBufferRemote, - BYTESWAP_USHORT(tcp6Table->table[i].dwRemotePort)); - } - else - { - addressTupleRemote = PyTuple_New(0); - } - - if (addressTupleRemote == NULL) - goto error; - - connectionTuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_STREAM, - addressTupleLocal, - addressTupleRemote, - tcp6Table->table[i].dwState, - tcp6Table->table[i].dwOwningPid); - if (!connectionTuple) - goto error; - if (PyList_Append(connectionsList, connectionTuple)) - goto error; - Py_DECREF(connectionTuple); - } - } - - free(table); - } - - // UDP IPv4 - - if ((PySequence_Contains(af_filter, _AF_INET) == 1) && - (PySequence_Contains(type_filter, _SOCK_DGRAM) == 1)) - { - table = NULL; - connectionTuple = NULL; - addressTupleLocal = NULL; - addressTupleRemote = NULL; - tableSize = 0; - getExtendedUdpTable(NULL, &tableSize, FALSE, AF_INET, - UDP_TABLE_OWNER_PID, 0); - - table = malloc(tableSize); - if (table == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET, - UDP_TABLE_OWNER_PID, 0) == 0) - { - udp4Table = table; - - for (i = 0; i < udp4Table->dwNumEntries; i++) - { - if (pid != -1) { - if (udp4Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (udp4Table->table[i].dwLocalAddr != 0 || - udp4Table->table[i].dwLocalPort != 0) - { - struct in_addr addr; - - addr.S_un.S_addr = udp4Table->table[i].dwLocalAddr; - rtlIpv4AddressToStringA(&addr, addressBufferLocal); - addressTupleLocal = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp4Table->table[i].dwLocalPort)); - } - else { - addressTupleLocal = PyTuple_New(0); - } - - if (addressTupleLocal == NULL) - goto error; - - connectionTuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET, - SOCK_DGRAM, - addressTupleLocal, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp4Table->table[i].dwOwningPid); - if (!connectionTuple) - goto error; - if (PyList_Append(connectionsList, connectionTuple)) - goto error; - Py_DECREF(connectionTuple); - } - } - - free(table); - } - - // UDP IPv6 - - if ((PySequence_Contains(af_filter, _AF_INET6) == 1) && - (PySequence_Contains(type_filter, _SOCK_DGRAM) == 1)) - { - table = NULL; - connectionTuple = NULL; - addressTupleLocal = NULL; - addressTupleRemote = NULL; - tableSize = 0; - getExtendedUdpTable(NULL, &tableSize, FALSE, - AF_INET6, UDP_TABLE_OWNER_PID, 0); - - table = malloc(tableSize); - if (table == NULL) { - PyErr_NoMemory(); - goto error; - } - - if (getExtendedUdpTable(table, &tableSize, FALSE, AF_INET6, - UDP_TABLE_OWNER_PID, 0) == 0) - { - udp6Table = table; - - for (i = 0; i < udp6Table->dwNumEntries; i++) - { - if (pid != -1) { - if (udp6Table->table[i].dwOwningPid != pid) { - continue; - } - } - - if (memcmp(udp6Table->table[i].ucLocalAddr, null_address, 16) - != 0 || udp6Table->table[i].dwLocalPort != 0) - { - struct in6_addr addr; - - memcpy(&addr, udp6Table->table[i].ucLocalAddr, 16); - rtlIpv6AddressToStringA(&addr, addressBufferLocal); - addressTupleLocal = Py_BuildValue( - "(si)", - addressBufferLocal, - BYTESWAP_USHORT(udp6Table->table[i].dwLocalPort)); - } - else { - addressTupleLocal = PyTuple_New(0); - } - - if (addressTupleLocal == NULL) - goto error; - - connectionTuple = Py_BuildValue( - "(iiiNNiI)", - -1, - AF_INET6, - SOCK_DGRAM, - addressTupleLocal, - PyTuple_New(0), - PSUTIL_CONN_NONE, - udp6Table->table[i].dwOwningPid); - if (!connectionTuple) - goto error; - if (PyList_Append(connectionsList, connectionTuple)) - goto error; - Py_DECREF(connectionTuple); - } - } - - free(table); - } - - _psutil_conn_decref_objs(); - return connectionsList; - -error: - _psutil_conn_decref_objs(); - Py_XDECREF(connectionTuple); - Py_XDECREF(addressTupleLocal); - Py_XDECREF(addressTupleRemote); - Py_DECREF(connectionsList); - if (table != NULL) - free(table); - return NULL; -} - - -/* - * Get process priority as a Python integer. - */ -static PyObject * -psutil_proc_priority_get(PyObject *self, PyObject *args) -{ - long pid; - DWORD priority; - HANDLE hProcess; - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) { - return NULL; - } - - priority = GetPriorityClass(hProcess); - CloseHandle(hProcess); - if (priority == 0) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - return Py_BuildValue("i", priority); -} - - -/* - * Set process priority. - */ -static PyObject * -psutil_proc_priority_set(PyObject *self, PyObject *args) -{ - long pid; - int priority; - int retval; - HANDLE hProcess; - DWORD dwDesiredAccess = \ - PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - if (! PyArg_ParseTuple(args, "li", &pid, &priority)) { - return NULL; - } - - hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess); - if (hProcess == NULL) { - return NULL; - } - - retval = SetPriorityClass(hProcess, priority); - CloseHandle(hProcess); - if (retval == 0) { - PyErr_SetFromWindowsErr(0); - return NULL; - } - Py_RETURN_NONE; -} - - -#if (_WIN32_WINNT >= 0x0600) // Windows Vista -/* - * Get process IO priority as a Python integer. - */ -static PyObject * -psutil_proc_io_priority_get(PyObject *self, PyObject *args) -{ - long pid; - HANDLE hProcess; - PULONG IoPriority; - - _NtQueryInformationProcess NtQueryInformationProcess = - (_NtQueryInformationProcess)GetProcAddress( - GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) { - return NULL; - } - - NtQueryInformationProcess( - hProcess, - ProcessIoPriority, - &IoPriority, - sizeof(ULONG), - NULL - ); - CloseHandle(hProcess); - return Py_BuildValue("i", IoPriority); -} - - -/* - * Set process IO priority. - */ -static PyObject * -psutil_proc_io_priority_set(PyObject *self, PyObject *args) -{ - long pid; - int prio; - HANDLE hProcess; - - _NtSetInformationProcess NtSetInformationProcess = - (_NtSetInformationProcess)GetProcAddress( - GetModuleHandleA("ntdll.dll"), "NtSetInformationProcess"); - - if (NtSetInformationProcess == NULL) { - PyErr_SetString(PyExc_RuntimeError, - "couldn't get NtSetInformationProcess"); - return NULL; - } - - if (! PyArg_ParseTuple(args, "li", &pid, &prio)) { - return NULL; - } - hProcess = psutil_handle_from_pid_waccess(pid, PROCESS_ALL_ACCESS); - if (hProcess == NULL) { - return NULL; - } - - NtSetInformationProcess( - hProcess, - ProcessIoPriority, - (PVOID)&prio, - sizeof((PVOID)prio) - ); - - CloseHandle(hProcess); - Py_RETURN_NONE; -} -#endif - - -/* - * Return a Python tuple referencing process I/O counters. - */ -static PyObject * -psutil_proc_io_counters(PyObject *self, PyObject *args) -{ - DWORD pid; - HANDLE hProcess; - IO_COUNTERS IoCounters; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid); - if (NULL == hProcess) { - return NULL; - } - if (! GetProcessIoCounters(hProcess, &IoCounters)) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(0); - } - CloseHandle(hProcess); - return Py_BuildValue("(KKKK)", - IoCounters.ReadOperationCount, - IoCounters.WriteOperationCount, - IoCounters.ReadTransferCount, - IoCounters.WriteTransferCount); -} - - -/* - * Return process CPU affinity as a bitmask - */ -static PyObject * -psutil_proc_cpu_affinity_get(PyObject *self, PyObject *args) -{ - DWORD pid; - HANDLE hProcess; - DWORD_PTR proc_mask; - DWORD_PTR system_mask; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) { - return NULL; - } - if (GetProcessAffinityMask(hProcess, &proc_mask, &system_mask) == 0) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(0); - } - - CloseHandle(hProcess); -#ifdef _WIN64 - return Py_BuildValue("K", (unsigned long long)proc_mask); -#else - return Py_BuildValue("k", (unsigned long)proc_mask); -#endif -} - - -/* - * Set process CPU affinity - */ -static PyObject * -psutil_proc_cpu_affinity_set(PyObject *self, PyObject *args) -{ - DWORD pid; - HANDLE hProcess; - DWORD dwDesiredAccess = \ - PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION; - DWORD_PTR mask; - -#ifdef _WIN64 - if (! PyArg_ParseTuple(args, "lK", &pid, &mask)) -#else - if (! PyArg_ParseTuple(args, "lk", &pid, &mask)) -#endif - { - return NULL; - } - hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess); - if (hProcess == NULL) { - return NULL; - } - - if (SetProcessAffinityMask(hProcess, mask) == 0) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(0); - } - - CloseHandle(hProcess); - Py_RETURN_NONE; -} - - -/* - * Return True if one of the process threads is in a waiting or - * suspended status. - */ -static PyObject * -psutil_proc_is_suspended(PyObject *self, PyObject *args) -{ - DWORD pid; - ULONG i; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) { - return NULL; - } - for (i = 0; i < process->NumberOfThreads; i++) { - if (process->Threads[i].ThreadState != Waiting || - process->Threads[i].WaitReason != Suspended) - { - free(buffer); - Py_RETURN_FALSE; - } - } - free(buffer); - Py_RETURN_TRUE; -} - - -/* - * Return path's disk total and free as a Python tuple. - */ -static PyObject * -psutil_disk_usage(PyObject *self, PyObject *args) -{ - BOOL retval; - ULARGE_INTEGER _, total, free; - char *path; - - if (PyArg_ParseTuple(args, "u", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceExW((LPCWSTR)path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } - - // on Python 2 we also want to accept plain strings other - // than Unicode -#if PY_MAJOR_VERSION <= 2 - PyErr_Clear(); // drop the argument parsing error - if (PyArg_ParseTuple(args, "s", &path)) { - Py_BEGIN_ALLOW_THREADS - retval = GetDiskFreeSpaceEx(path, &_, &total, &free); - Py_END_ALLOW_THREADS - goto return_; - } -#endif - - return NULL; - -return_: - if (retval == 0) - return PyErr_SetFromWindowsErr(0); - else - return Py_BuildValue("(LL)", total.QuadPart, free.QuadPart); -} - - -/* - * Return a Python list of named tuples with overall network I/O information - */ -static PyObject * -psutil_net_io_counters(PyObject *self, PyObject *args) -{ - char ifname[MAX_PATH]; - DWORD dwRetVal = 0; - MIB_IFROW *pIfRow = NULL; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_nic_info = NULL; - PyObject *py_nic_name = NULL; - - if (py_retdict == NULL) - return NULL; - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - py_nic_name = NULL; - py_nic_info = NULL; - pIfRow = (MIB_IFROW *) malloc(sizeof(MIB_IFROW)); - - if (pIfRow == NULL) { - PyErr_NoMemory(); - goto error; - } - - pIfRow->dwIndex = pCurrAddresses->IfIndex; - dwRetVal = GetIfEntry(pIfRow); - if (dwRetVal != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, "GetIfEntry() failed."); - goto error; - } - - py_nic_info = Py_BuildValue("(kkkkkkkk)", - pIfRow->dwOutOctets, - pIfRow->dwInOctets, - pIfRow->dwOutUcastPkts, - pIfRow->dwInUcastPkts, - pIfRow->dwInErrors, - pIfRow->dwOutErrors, - pIfRow->dwInDiscards, - pIfRow->dwOutDiscards); - if (!py_nic_info) - goto error; - - sprintf_s(ifname, MAX_PATH, "%wS", pCurrAddresses->FriendlyName); - py_nic_name = PyUnicode_Decode( - ifname, _tcslen(ifname), Py_FileSystemDefaultEncoding, "replace"); - - if (py_nic_name == NULL) - goto error; - if (PyDict_SetItem(py_retdict, py_nic_name, py_nic_info)) - goto error; - Py_XDECREF(py_nic_name); - Py_XDECREF(py_nic_info); - - free(pIfRow); - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_nic_name); - Py_XDECREF(py_nic_info); - Py_DECREF(py_retdict); - if (pAddresses != NULL) - free(pAddresses); - if (pIfRow != NULL) - free(pIfRow); - return NULL; -} - - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_disk_io_counters(PyObject *self, PyObject *args) -{ - DISK_PERFORMANCE_WIN_2008 diskPerformance; - DWORD dwSize; - HANDLE hDevice = NULL; - char szDevice[MAX_PATH]; - char szDeviceDisplay[MAX_PATH]; - int devNum; - PyObject *py_retdict = PyDict_New(); - PyObject *py_disk_info = NULL; - if (py_retdict == NULL) { - return NULL; - } - - // Apparently there's no way to figure out how many times we have - // to iterate in order to find valid drives. - // Let's assume 32, which is higher than 26, the number of letters - // in the alphabet (from A:\ to Z:\). - for (devNum = 0; devNum <= 32; ++devNum) { - py_disk_info = NULL; - sprintf_s(szDevice, MAX_PATH, "\\\\.\\PhysicalDrive%d", devNum); - hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - - if (hDevice == INVALID_HANDLE_VALUE) { - continue; - } - if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0, - &diskPerformance, sizeof(diskPerformance), - &dwSize, NULL)) - { - sprintf_s(szDeviceDisplay, MAX_PATH, "PhysicalDrive%d", devNum); - py_disk_info = Py_BuildValue( - "(IILLKK)", - diskPerformance.ReadCount, - diskPerformance.WriteCount, - diskPerformance.BytesRead, - diskPerformance.BytesWritten, - (unsigned long long)(diskPerformance.ReadTime.QuadPart * 10) / 1000, - (unsigned long long)(diskPerformance.WriteTime.QuadPart * 10) / 1000); - if (!py_disk_info) - goto error; - if (PyDict_SetItemString(py_retdict, szDeviceDisplay, - py_disk_info)) - { - goto error; - } - Py_XDECREF(py_disk_info); - } - else { - // XXX we might get here with ERROR_INSUFFICIENT_BUFFER when - // compiling with mingw32; not sure what to do. - // return PyErr_SetFromWindowsErr(0); - ;; - } - - CloseHandle(hDevice); - } - - return py_retdict; - -error: - Py_XDECREF(py_disk_info); - Py_DECREF(py_retdict); - if (hDevice != NULL) - CloseHandle(hDevice); - return NULL; -} - - -static char *psutil_get_drive_type(int type) -{ - switch (type) { - case DRIVE_FIXED: - return "fixed"; - case DRIVE_CDROM: - return "cdrom"; - case DRIVE_REMOVABLE: - return "removable"; - case DRIVE_UNKNOWN: - return "unknown"; - case DRIVE_NO_ROOT_DIR: - return "unmounted"; - case DRIVE_REMOTE: - return "remote"; - case DRIVE_RAMDISK: - return "ramdisk"; - default: - return "?"; - } -} - - -#ifndef _ARRAYSIZE -#define _ARRAYSIZE(a) (sizeof(a)/sizeof(a[0])) -#endif - -/* - * Return disk partitions as a list of tuples such as - * (drive_letter, drive_letter, type, "") - */ -static PyObject * -psutil_disk_partitions(PyObject *self, PyObject *args) -{ - DWORD num_bytes; - char drive_strings[255]; - char *drive_letter = drive_strings; - int all; - int type; - int ret; - char opts[20]; - LPTSTR fs_type[MAX_PATH + 1] = { 0 }; - DWORD pflags = 0; - PyObject *py_all; - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_retlist == NULL) { - return NULL; - } - - // avoid to visualize a message box in case something goes wrong - // see https://github.com/giampaolo/psutil/issues/264 - SetErrorMode(SEM_FAILCRITICALERRORS); - - if (! PyArg_ParseTuple(args, "O", &py_all)) { - goto error; - } - all = PyObject_IsTrue(py_all); - - Py_BEGIN_ALLOW_THREADS - num_bytes = GetLogicalDriveStrings(254, drive_letter); - Py_END_ALLOW_THREADS - - if (num_bytes == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - while (*drive_letter != 0) { - py_tuple = NULL; - opts[0] = 0; - fs_type[0] = 0; - - Py_BEGIN_ALLOW_THREADS - type = GetDriveType(drive_letter); - Py_END_ALLOW_THREADS - - // by default we only show hard drives and cd-roms - if (all == 0) { - if ((type == DRIVE_UNKNOWN) || - (type == DRIVE_NO_ROOT_DIR) || - (type == DRIVE_REMOTE) || - (type == DRIVE_RAMDISK)) { - goto next; - } - // floppy disk: skip it by default as it introduces a - // considerable slowdown. - if ((type == DRIVE_REMOVABLE) && - (strcmp(drive_letter, "A:\\") == 0)) { - goto next; - } - } - - ret = GetVolumeInformation( - (LPCTSTR)drive_letter, NULL, _ARRAYSIZE(drive_letter), - NULL, NULL, &pflags, (LPTSTR)fs_type, _ARRAYSIZE(fs_type)); - if (ret == 0) { - // We might get here in case of a floppy hard drive, in - // which case the error is (21, "device not ready"). - // Let's pretend it didn't happen as we already have - // the drive name and type ('removable'). - strcat_s(opts, _countof(opts), ""); - SetLastError(0); - } - else { - if (pflags & FILE_READ_ONLY_VOLUME) { - strcat_s(opts, _countof(opts), "ro"); - } - else { - strcat_s(opts, _countof(opts), "rw"); - } - if (pflags & FILE_VOLUME_IS_COMPRESSED) { - strcat_s(opts, _countof(opts), ",compressed"); - } - } - - if (strlen(opts) > 0) { - strcat_s(opts, _countof(opts), ","); - } - strcat_s(opts, _countof(opts), psutil_get_drive_type(type)); - - py_tuple = Py_BuildValue( - "(ssss)", - drive_letter, - drive_letter, - fs_type, // either FAT, FAT32, NTFS, HPFS, CDFS, UDF or NWFS - opts); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - goto next; - -next: - drive_letter = strchr(drive_letter, 0) + 1; - } - - SetErrorMode(0); - return py_retlist; - -error: - SetErrorMode(0); - Py_XDECREF(py_tuple); - Py_DECREF(py_retlist); - return NULL; -} - -/* - * Return a Python dict of tuples for disk I/O information - */ -static PyObject * -psutil_users(PyObject *self, PyObject *args) -{ - HANDLE hServer = NULL; - LPTSTR buffer_user = NULL; - LPTSTR buffer_addr = NULL; - PWTS_SESSION_INFO sessions = NULL; - DWORD count; - DWORD i; - DWORD sessionId; - DWORD bytes; - PWTS_CLIENT_ADDRESS address; - char address_str[50]; - long long unix_time; - - PWINSTATIONQUERYINFORMATIONW WinStationQueryInformationW; - WINSTATION_INFO station_info; - HINSTANCE hInstWinSta = NULL; - ULONG returnLen; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_buffer_user_encoded = NULL; - - if (py_retlist == NULL) { - return NULL; - } - - hInstWinSta = LoadLibraryA("winsta.dll"); - WinStationQueryInformationW = (PWINSTATIONQUERYINFORMATIONW) \ - GetProcAddress(hInstWinSta, "WinStationQueryInformationW"); - - hServer = WTSOpenServer('\0'); - if (hServer == NULL) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - if (WTSEnumerateSessions(hServer, 0, 1, &sessions, &count) == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - for (i = 0; i < count; i++) { - py_address = NULL; - py_tuple = NULL; - sessionId = sessions[i].SessionId; - if (buffer_user != NULL) { - WTSFreeMemory(buffer_user); - } - if (buffer_addr != NULL) { - WTSFreeMemory(buffer_addr); - } - - buffer_user = NULL; - buffer_addr = NULL; - - // username - bytes = 0; - if (WTSQuerySessionInformation(hServer, sessionId, WTSUserName, - &buffer_user, &bytes) == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - if (bytes == 1) { - continue; - } - - // address - bytes = 0; - if (WTSQuerySessionInformation(hServer, sessionId, WTSClientAddress, - &buffer_addr, &bytes) == 0) { - PyErr_SetFromWindowsErr(0); - goto error; - } - - address = (PWTS_CLIENT_ADDRESS)buffer_addr; - if (address->AddressFamily == 0) { // AF_INET - sprintf_s(address_str, - _countof(address_str), - "%u.%u.%u.%u", - address->Address[0], - address->Address[1], - address->Address[2], - address->Address[3]); - py_address = Py_BuildValue("s", address_str); - if (!py_address) - goto error; - } - else { - py_address = Py_None; - } - - // login time - if (!WinStationQueryInformationW(hServer, - sessionId, - WinStationInformation, - &station_info, - sizeof(station_info), - &returnLen)) - { - goto error; - } - - unix_time = ((LONGLONG)station_info.ConnectTime.dwHighDateTime) << 32; - unix_time += \ - station_info.ConnectTime.dwLowDateTime - 116444736000000000LL; - unix_time /= 10000000; - - py_buffer_user_encoded = PyUnicode_Decode( - buffer_user, _tcslen(buffer_user), Py_FileSystemDefaultEncoding, - "replace"); - py_tuple = Py_BuildValue("OOd", py_buffer_user_encoded, py_address, - (double)unix_time); - if (!py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_XDECREF(py_buffer_user_encoded); - Py_XDECREF(py_address); - Py_XDECREF(py_tuple); - } - - WTSCloseServer(hServer); - WTSFreeMemory(sessions); - WTSFreeMemory(buffer_user); - WTSFreeMemory(buffer_addr); - FreeLibrary(hInstWinSta); - return py_retlist; - -error: - Py_XDECREF(py_buffer_user_encoded); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - Py_DECREF(py_retlist); - - if (hInstWinSta != NULL) { - FreeLibrary(hInstWinSta); - } - if (hServer != NULL) { - WTSCloseServer(hServer); - } - if (sessions != NULL) { - WTSFreeMemory(sessions); - } - if (buffer_user != NULL) { - WTSFreeMemory(buffer_user); - } - if (buffer_addr != NULL) { - WTSFreeMemory(buffer_addr); - } - return NULL; -} - - -/* - * Return the number of handles opened by process. - */ -static PyObject * -psutil_proc_num_handles(PyObject *self, PyObject *args) -{ - DWORD pid; - HANDLE hProcess; - DWORD handleCount; - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - hProcess = psutil_handle_from_pid(pid); - if (NULL == hProcess) { - return NULL; - } - if (! GetProcessHandleCount(hProcess, &handleCount)) { - CloseHandle(hProcess); - return PyErr_SetFromWindowsErr(0); - } - CloseHandle(hProcess); - return Py_BuildValue("k", handleCount); -} - - -/* - * Get various process information by using NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes. - * Returned tuple includes the following process info: - * - * - num_threads - * - ctx_switches - * - num_handles (fallback) - * - user/kernel times (fallback) - * - create time (fallback) - * - io counters (fallback) - */ -static PyObject * -psutil_proc_info(PyObject *self, PyObject *args) -{ - DWORD pid; - PSYSTEM_PROCESS_INFORMATION process; - PVOID buffer; - ULONG num_handles; - ULONG i; - ULONG ctx_switches = 0; - double user_time; - double kernel_time; - long long create_time; - int num_threads; - LONGLONG io_rcount, io_wcount, io_rbytes, io_wbytes; - - - if (! PyArg_ParseTuple(args, "l", &pid)) - return NULL; - if (! psutil_get_proc_info(pid, &process, &buffer)) - return NULL; - - num_handles = process->HandleCount; - for (i = 0; i < process->NumberOfThreads; i++) - ctx_switches += process->Threads[i].ContextSwitches; - user_time = (double)process->UserTime.HighPart * 429.4967296 + \ - (double)process->UserTime.LowPart * 1e-7; - kernel_time = (double)process->KernelTime.HighPart * 429.4967296 + \ - (double)process->KernelTime.LowPart * 1e-7; - // Convert the LARGE_INTEGER union to a Unix time. - // It's the best I could find by googling and borrowing code here - // and there. The time returned has a precision of 1 second. - if (0 == pid || 4 == pid) { - // the python module will translate this into BOOT_TIME later - create_time = 0; - } - else { - create_time = ((LONGLONG)process->CreateTime.HighPart) << 32; - create_time += process->CreateTime.LowPart - 116444736000000000LL; - create_time /= 10000000; - } - num_threads = (int)process->NumberOfThreads; - io_rcount = process->ReadOperationCount.QuadPart; - io_wcount = process->WriteOperationCount.QuadPart; - io_rbytes = process->ReadTransferCount.QuadPart; - io_wbytes = process->WriteTransferCount.QuadPart; - free(buffer); - - return Py_BuildValue( - "kkdddiKKKK", - num_handles, - ctx_switches, - user_time, - kernel_time, - (double)create_time, - num_threads, - io_rcount, - io_wcount, - io_rbytes, - io_wbytes - ); -} - - -static char *get_region_protection_string(ULONG protection) -{ - switch (protection & 0xff) { - case PAGE_NOACCESS: - return ""; - case PAGE_READONLY: - return "r"; - case PAGE_READWRITE: - return "rw"; - case PAGE_WRITECOPY: - return "wc"; - case PAGE_EXECUTE: - return "x"; - case PAGE_EXECUTE_READ: - return "xr"; - case PAGE_EXECUTE_READWRITE: - return "xrw"; - case PAGE_EXECUTE_WRITECOPY: - return "xwc"; - default: - return "?"; - } -} - - -/* - * Return a list of process's memory mappings. - */ -static PyObject * -psutil_proc_memory_maps(PyObject *self, PyObject *args) -{ - DWORD pid; - HANDLE hProcess = NULL; - MEMORY_BASIC_INFORMATION basicInfo; - PVOID baseAddress; - PVOID previousAllocationBase; - CHAR mappedFileName[MAX_PATH]; - SYSTEM_INFO system_info; - LPVOID maxAddr; - PyObject *py_list = PyList_New(0); - PyObject *py_tuple = NULL; - - if (py_list == NULL) { - return NULL; - } - if (! PyArg_ParseTuple(args, "l", &pid)) { - goto error; - } - hProcess = psutil_handle_from_pid(pid); - if (NULL == hProcess) { - goto error; - } - - GetSystemInfo(&system_info); - maxAddr = system_info.lpMaximumApplicationAddress; - baseAddress = NULL; - previousAllocationBase = NULL; - - while (VirtualQueryEx(hProcess, baseAddress, &basicInfo, - sizeof(MEMORY_BASIC_INFORMATION))) - { - py_tuple = NULL; - if (baseAddress > maxAddr) { - break; - } - if (GetMappedFileNameA(hProcess, baseAddress, mappedFileName, - sizeof(mappedFileName))) - { - py_tuple = Py_BuildValue( - "(kssI)", - (unsigned long)baseAddress, - get_region_protection_string(basicInfo.Protect), - mappedFileName, - basicInfo.RegionSize); - if (!py_tuple) - goto error; - if (PyList_Append(py_list, py_tuple)) - goto error; - Py_DECREF(py_tuple); - } - previousAllocationBase = basicInfo.AllocationBase; - baseAddress = (PCHAR)baseAddress + basicInfo.RegionSize; - } - - CloseHandle(hProcess); - return py_list; - -error: - Py_XDECREF(py_tuple); - Py_DECREF(py_list); - if (hProcess != NULL) - CloseHandle(hProcess); - return NULL; -} - - -/* - * Return a {pid:ppid, ...} dict for all running processes. - */ -static PyObject * -psutil_ppid_map(PyObject *self, PyObject *args) -{ - PyObject *pid = NULL; - PyObject *ppid = NULL; - PyObject *py_retdict = PyDict_New(); - HANDLE handle = NULL; - PROCESSENTRY32 pe = {0}; - pe.dwSize = sizeof(PROCESSENTRY32); - - if (py_retdict == NULL) - return NULL; - handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); - if (handle == INVALID_HANDLE_VALUE) { - PyErr_SetFromWindowsErr(0); - Py_DECREF(py_retdict); - return NULL; - } - - if (Process32First(handle, &pe)) { - do { - pid = Py_BuildValue("I", pe.th32ProcessID); - if (pid == NULL) - goto error; - ppid = Py_BuildValue("I", pe.th32ParentProcessID); - if (ppid == NULL) - goto error; - if (PyDict_SetItem(py_retdict, pid, ppid)) - goto error; - Py_DECREF(pid); - Py_DECREF(ppid); - } while (Process32Next(handle, &pe)); - } - - CloseHandle(handle); - return py_retdict; - -error: - Py_XDECREF(pid); - Py_XDECREF(ppid); - Py_DECREF(py_retdict); - CloseHandle(handle); - return NULL; -} - - -/* - * Return NICs addresses. - */ - -static PyObject * -psutil_net_if_addrs(PyObject *self, PyObject *args) -{ - unsigned int i = 0; - ULONG family; - PCTSTR intRet; - char *ptr; - char buff[100]; - char ifname[MAX_PATH]; - DWORD bufflen = 100; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - PIP_ADAPTER_UNICAST_ADDRESS pUnicast = NULL; - - PyObject *py_retlist = PyList_New(0); - PyObject *py_tuple = NULL; - PyObject *py_address = NULL; - PyObject *py_mac_address = NULL; - - if (py_retlist == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - pCurrAddresses = pAddresses; - - while (pCurrAddresses) { - pUnicast = pCurrAddresses->FirstUnicastAddress; - sprintf_s(ifname, MAX_PATH, "%wS", pCurrAddresses->FriendlyName); - - // MAC address - if (pCurrAddresses->PhysicalAddressLength != 0) { - ptr = buff; - *ptr = '\0'; - for (i = 0; i < (int) pCurrAddresses->PhysicalAddressLength; i++) { - if (i == (pCurrAddresses->PhysicalAddressLength - 1)) { - sprintf_s(ptr, _countof(buff), "%.2X\n", - (int)pCurrAddresses->PhysicalAddress[i]); - } - else { - sprintf_s(ptr, _countof(buff), "%.2X-", - (int)pCurrAddresses->PhysicalAddress[i]); - } - ptr += 3; - } - *--ptr = '\0'; - -#if PY_MAJOR_VERSION >= 3 - py_mac_address = PyUnicode_FromString(buff); -#else - py_mac_address = PyString_FromString(buff); -#endif - if (py_mac_address == NULL) - goto error; - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(siOOO)", - ifname, - -1, // this will be converted later to AF_LINK - py_mac_address, - Py_None, - Py_None - ); - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_DECREF(py_mac_address); - } - - // find out the IP address associated with the NIC - if (pUnicast != NULL) { - for (i = 0; pUnicast != NULL; i++) { - family = pUnicast->Address.lpSockaddr->sa_family; - if (family == AF_INET) { - struct sockaddr_in *sa_in = (struct sockaddr_in *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET, &(sa_in->sin_addr), buff, - bufflen); - } - else if (family == AF_INET6) { - struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *) - pUnicast->Address.lpSockaddr; - intRet = inet_ntop(AF_INET6, &(sa_in6->sin6_addr), - buff, bufflen); - } - else { - // we should never get here - pUnicast = pUnicast->Next; - continue; - } - - if (intRet == NULL) { - PyErr_SetFromWindowsErr(GetLastError()); - goto error; - } -#if PY_MAJOR_VERSION >= 3 - py_address = PyUnicode_FromString(buff); -#else - py_address = PyString_FromString(buff); -#endif - if (py_address == NULL) - goto error; - - Py_INCREF(Py_None); - Py_INCREF(Py_None); - py_tuple = Py_BuildValue( - "(siOOO)", - ifname, - family, - py_address, - Py_None, - Py_None - ); - - if (! py_tuple) - goto error; - if (PyList_Append(py_retlist, py_tuple)) - goto error; - Py_DECREF(py_tuple); - Py_DECREF(py_address); - - pUnicast = pUnicast->Next; - } - } - - pCurrAddresses = pCurrAddresses->Next; - } - - free(pAddresses); - return py_retlist; - -error: - if (pAddresses) - free(pAddresses); - Py_DECREF(py_retlist); - Py_XDECREF(py_tuple); - Py_XDECREF(py_address); - return NULL; -} - - -/* - * Provides stats about NIC interfaces installed on the system. - * TODO: get 'duplex' (currently it's hard coded to '2', aka - 'full duplex') - */ -static PyObject * -psutil_net_if_stats(PyObject *self, PyObject *args) -{ - int i; - DWORD dwSize = 0; - DWORD dwRetVal = 0; - MIB_IFTABLE *pIfTable; - MIB_IFROW *pIfRow; - PIP_ADAPTER_ADDRESSES pAddresses = NULL; - PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL; - char friendly_name[MAX_PATH]; - char descr[MAX_PATH]; - int ifname_found; - - PyObject *py_retdict = PyDict_New(); - PyObject *py_ifc_info = NULL; - PyObject *py_is_up = NULL; - - if (py_retdict == NULL) - return NULL; - - pAddresses = psutil_get_nic_addresses(); - if (pAddresses == NULL) - goto error; - - pIfTable = (MIB_IFTABLE *) malloc(sizeof (MIB_IFTABLE)); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - dwSize = sizeof(MIB_IFTABLE); - if (GetIfTable(pIfTable, &dwSize, FALSE) == ERROR_INSUFFICIENT_BUFFER) { - free(pIfTable); - pIfTable = (MIB_IFTABLE *) malloc(dwSize); - if (pIfTable == NULL) { - PyErr_NoMemory(); - goto error; - } - } - // Make a second call to GetIfTable to get the actual - // data we want. - if ((dwRetVal = GetIfTable(pIfTable, &dwSize, FALSE)) != NO_ERROR) { - PyErr_SetString(PyExc_RuntimeError, "GetIfTable() failed"); - goto error; - } - - for (i = 0; i < (int) pIfTable->dwNumEntries; i++) { - pIfRow = (MIB_IFROW *) & pIfTable->table[i]; - - // GetIfTable is not able to give us NIC with "friendly names" - // so we determine them via GetAdapterAddresses() which - // provides friendly names *and* descriptions and find the - // ones that match. - ifname_found = 0; - pCurrAddresses = pAddresses; - while (pCurrAddresses) { - sprintf_s(descr, MAX_PATH, "%wS", pCurrAddresses->Description); - if (lstrcmp(descr, pIfRow->bDescr) == 0) { - sprintf_s(friendly_name, MAX_PATH, "%wS", pCurrAddresses->FriendlyName); - ifname_found = 1; - break; - } - pCurrAddresses = pCurrAddresses->Next; - } - if (ifname_found == 0) { - // Name not found means GetAdapterAddresses() doesn't list - // this NIC, only GetIfTable, meaning it's not really a NIC - // interface so we skip it. - continue; - } - - // is up? - if((pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_CONNECTED || - pIfRow->dwOperStatus == MIB_IF_OPER_STATUS_OPERATIONAL) && - pIfRow->dwAdminStatus == 1 ) { - py_is_up = Py_True; - } - else { - py_is_up = Py_False; - } - Py_INCREF(py_is_up); - - py_ifc_info = Py_BuildValue( - "(Oikk)", - py_is_up, - 2, // there's no way to know duplex so let's assume 'full' - pIfRow->dwSpeed / 1000000, // expressed in bytes, we want Mb - pIfRow->dwMtu - ); - if (!py_ifc_info) - goto error; - if (PyDict_SetItemString(py_retdict, friendly_name, py_ifc_info)) - goto error; - Py_DECREF(py_ifc_info); - } - - free(pIfTable); - free(pAddresses); - return py_retdict; - -error: - Py_XDECREF(py_is_up); - Py_XDECREF(py_ifc_info); - Py_DECREF(py_retdict); - if (pIfTable != NULL) - free(pIfTable); - if (pAddresses != NULL) - free(pAddresses); - return NULL; -} - - -// ------------------------ Python init --------------------------- - -static PyMethodDef -PsutilMethods[] = -{ - // --- per-process functions - - {"proc_cmdline", psutil_proc_cmdline, METH_VARARGS, - "Return process cmdline as a list of cmdline arguments"}, - {"proc_exe", psutil_proc_exe, METH_VARARGS, - "Return path of the process executable"}, - {"proc_name", psutil_proc_name, METH_VARARGS, - "Return process name"}, - {"proc_kill", psutil_proc_kill, METH_VARARGS, - "Kill the process identified by the given PID"}, - {"proc_cpu_times", psutil_proc_cpu_times, METH_VARARGS, - "Return tuple of user/kern time for the given PID"}, - {"proc_create_time", psutil_proc_create_time, METH_VARARGS, - "Return a float indicating the process create time expressed in " - "seconds since the epoch"}, - {"proc_memory_info", psutil_proc_memory_info, METH_VARARGS, - "Return a tuple of process memory information"}, - {"proc_memory_info_2", psutil_proc_memory_info_2, METH_VARARGS, - "Alternate implementation"}, - {"proc_cwd", psutil_proc_cwd, METH_VARARGS, - "Return process current working directory"}, - {"proc_suspend", psutil_proc_suspend, METH_VARARGS, - "Suspend a process"}, - {"proc_resume", psutil_proc_resume, METH_VARARGS, - "Resume a process"}, - {"proc_open_files", psutil_proc_open_files, METH_VARARGS, - "Return files opened by process"}, - {"proc_username", psutil_proc_username, METH_VARARGS, - "Return the username of a process"}, - {"proc_threads", psutil_proc_threads, METH_VARARGS, - "Return process threads information as a list of tuple"}, - {"proc_wait", psutil_proc_wait, METH_VARARGS, - "Wait for process to terminate and return its exit code."}, - {"proc_priority_get", psutil_proc_priority_get, METH_VARARGS, - "Return process priority."}, - {"proc_priority_set", psutil_proc_priority_set, METH_VARARGS, - "Set process priority."}, -#if (_WIN32_WINNT >= 0x0600) // Windows Vista - {"proc_io_priority_get", psutil_proc_io_priority_get, METH_VARARGS, - "Return process IO priority."}, - {"proc_io_priority_set", psutil_proc_io_priority_set, METH_VARARGS, - "Set process IO priority."}, -#endif - {"proc_cpu_affinity_get", psutil_proc_cpu_affinity_get, METH_VARARGS, - "Return process CPU affinity as a bitmask."}, - {"proc_cpu_affinity_set", psutil_proc_cpu_affinity_set, METH_VARARGS, - "Set process CPU affinity."}, - {"proc_io_counters", psutil_proc_io_counters, METH_VARARGS, - "Get process I/O counters."}, - {"proc_is_suspended", psutil_proc_is_suspended, METH_VARARGS, - "Return True if one of the process threads is in a suspended state"}, - {"proc_num_handles", psutil_proc_num_handles, METH_VARARGS, - "Return the number of handles opened by process."}, - {"proc_memory_maps", psutil_proc_memory_maps, METH_VARARGS, - "Return a list of process's memory mappings"}, - - // --- alternative pinfo interface - {"proc_info", psutil_proc_info, METH_VARARGS, - "Various process information"}, - - // --- system-related functions - {"pids", psutil_pids, METH_VARARGS, - "Returns a list of PIDs currently running on the system"}, - {"ppid_map", psutil_ppid_map, METH_VARARGS, - "Return a {pid:ppid, ...} dict for all running processes"}, - {"pid_exists", psutil_pid_exists, METH_VARARGS, - "Determine if the process exists in the current process list."}, - {"cpu_count_logical", psutil_cpu_count_logical, METH_VARARGS, - "Returns the number of logical CPUs on the system"}, - {"cpu_count_phys", psutil_cpu_count_phys, METH_VARARGS, - "Returns the number of physical CPUs on the system"}, - {"boot_time", psutil_boot_time, METH_VARARGS, - "Return the system boot time expressed in seconds since the epoch."}, - {"virtual_mem", psutil_virtual_mem, METH_VARARGS, - "Return the total amount of physical memory, in bytes"}, - {"cpu_times", psutil_cpu_times, METH_VARARGS, - "Return system cpu times as a list"}, - {"per_cpu_times", psutil_per_cpu_times, METH_VARARGS, - "Return system per-cpu times as a list of tuples"}, - {"disk_usage", psutil_disk_usage, METH_VARARGS, - "Return path's disk total and free as a Python tuple."}, - {"net_io_counters", psutil_net_io_counters, METH_VARARGS, - "Return dict of tuples of networks I/O information."}, - {"disk_io_counters", psutil_disk_io_counters, METH_VARARGS, - "Return dict of tuples of disks I/O information."}, - {"users", psutil_users, METH_VARARGS, - "Return a list of currently connected users."}, - {"disk_partitions", psutil_disk_partitions, METH_VARARGS, - "Return disk partitions."}, - {"net_connections", psutil_net_connections, METH_VARARGS, - "Return system-wide connections"}, - {"net_if_addrs", psutil_net_if_addrs, METH_VARARGS, - "Return NICs addresses."}, - {"net_if_stats", psutil_net_if_stats, METH_VARARGS, - "Return NICs stats."}, - - // --- windows API bindings - {"win32_QueryDosDevice", psutil_win32_QueryDosDevice, METH_VARARGS, - "QueryDosDevice binding"}, - - {NULL, NULL, 0, NULL} -}; - - -struct module_state { - PyObject *error; -}; - -#if PY_MAJOR_VERSION >= 3 -#define GETSTATE(m) ((struct module_state*)PyModule_GetState(m)) -#else -#define GETSTATE(m) (&_state) -static struct module_state _state; -#endif - -#if PY_MAJOR_VERSION >= 3 - -static int psutil_windows_traverse(PyObject *m, visitproc visit, void *arg) { - Py_VISIT(GETSTATE(m)->error); - return 0; -} - -static int psutil_windows_clear(PyObject *m) { - Py_CLEAR(GETSTATE(m)->error); - return 0; -} - -static struct PyModuleDef moduledef = { - PyModuleDef_HEAD_INIT, - "psutil_windows", - NULL, - sizeof(struct module_state), - PsutilMethods, - NULL, - psutil_windows_traverse, - psutil_windows_clear, - NULL -}; - -#define INITERROR return NULL - -PyMODINIT_FUNC PyInit__psutil_windows(void) - -#else -#define INITERROR return -void init_psutil_windows(void) -#endif -{ - struct module_state *st = NULL; -#if PY_MAJOR_VERSION >= 3 - PyObject *module = PyModule_Create(&moduledef); -#else - PyObject *module = Py_InitModule("_psutil_windows", PsutilMethods); -#endif - - if (module == NULL) { - INITERROR; - } - - st = GETSTATE(module); - st->error = PyErr_NewException("_psutil_windows.Error", NULL, NULL); - if (st->error == NULL) { - Py_DECREF(module); - INITERROR; - } - - PyModule_AddIntConstant(module, "version", PSUTIL_VERSION); - - // process status constants - // http://msdn.microsoft.com/en-us/library/ms683211(v=vs.85).aspx - PyModule_AddIntConstant( - module, "ABOVE_NORMAL_PRIORITY_CLASS", ABOVE_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "BELOW_NORMAL_PRIORITY_CLASS", BELOW_NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "HIGH_PRIORITY_CLASS", HIGH_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "IDLE_PRIORITY_CLASS", IDLE_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "NORMAL_PRIORITY_CLASS", NORMAL_PRIORITY_CLASS); - PyModule_AddIntConstant( - module, "REALTIME_PRIORITY_CLASS", REALTIME_PRIORITY_CLASS); - // connection status constants - // http://msdn.microsoft.com/en-us/library/cc669305.aspx - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSED", MIB_TCP_STATE_CLOSED); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSING", MIB_TCP_STATE_CLOSING); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_CLOSE_WAIT", MIB_TCP_STATE_CLOSE_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LISTEN", MIB_TCP_STATE_LISTEN); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_ESTAB", MIB_TCP_STATE_ESTAB); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_SENT", MIB_TCP_STATE_SYN_SENT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_SYN_RCVD", MIB_TCP_STATE_SYN_RCVD); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT1", MIB_TCP_STATE_FIN_WAIT1); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_FIN_WAIT2", MIB_TCP_STATE_FIN_WAIT2); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_LAST_ACK", MIB_TCP_STATE_LAST_ACK); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_TIME_WAIT", MIB_TCP_STATE_TIME_WAIT); - PyModule_AddIntConstant( - module, "MIB_TCP_STATE_DELETE_TCB", MIB_TCP_STATE_DELETE_TCB); - PyModule_AddIntConstant( - module, "PSUTIL_CONN_NONE", PSUTIL_CONN_NONE); - // ...for internal use in _psutil_windows.py - PyModule_AddIntConstant( - module, "INFINITE", INFINITE); - PyModule_AddIntConstant( - module, "ERROR_ACCESS_DENIED", ERROR_ACCESS_DENIED); - - // set SeDebug for the current process - psutil_set_se_debug(); - -#if PY_MAJOR_VERSION >= 3 - return module; -#endif -} diff --git a/python/psutil/psutil/_psutil_windows.h b/python/psutil/psutil/_psutil_windows.h deleted file mode 100644 index c77f64e9c..000000000 --- a/python/psutil/psutil/_psutil_windows.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> -#include <windows.h> - -// --- per-process functions - -static PyObject* psutil_proc_cmdline(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_affinity_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_affinity_set(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_proc_create_time(PyObject* self, PyObject* args); -static PyObject* psutil_proc_cwd(PyObject* self, PyObject* args); -static PyObject* psutil_proc_exe(PyObject* self, PyObject* args); -static PyObject* psutil_proc_info(PyObject* self, PyObject* args); -static PyObject* psutil_proc_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_proc_is_suspended(PyObject* self, PyObject* args); -static PyObject* psutil_proc_kill(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_info(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_info_2(PyObject* self, PyObject* args); -static PyObject* psutil_proc_memory_maps(PyObject* self, PyObject* args); -static PyObject* psutil_proc_name(PyObject* self, PyObject* args); -static PyObject* psutil_proc_num_handles(PyObject* self, PyObject* args); -static PyObject* psutil_proc_open_files(PyObject* self, PyObject* args); -static PyObject* psutil_proc_priority_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_priority_set(PyObject* self, PyObject* args); -static PyObject* psutil_proc_resume(PyObject* self, PyObject* args); -static PyObject* psutil_proc_suspend(PyObject* self, PyObject* args); -static PyObject* psutil_proc_threads(PyObject* self, PyObject* args); -static PyObject* psutil_proc_username(PyObject* self, PyObject* args); -static PyObject* psutil_proc_wait(PyObject* self, PyObject* args); - -#if (PSUTIL_WINVER >= 0x0600) // Windows Vista -static PyObject* psutil_proc_io_priority_get(PyObject* self, PyObject* args); -static PyObject* psutil_proc_io_priority_set(PyObject* self, PyObject* args); -#endif - -// --- system-related functions - -static PyObject* psutil_boot_time(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_logical(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_count_phys(PyObject* self, PyObject* args); -static PyObject* psutil_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_disk_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_disk_partitions(PyObject* self, PyObject* args); -static PyObject* psutil_disk_usage(PyObject* self, PyObject* args); -static PyObject* psutil_net_connections(PyObject* self, PyObject* args); -static PyObject* psutil_net_io_counters(PyObject* self, PyObject* args); -static PyObject* psutil_per_cpu_times(PyObject* self, PyObject* args); -static PyObject* psutil_pid_exists(PyObject* self, PyObject* args); -static PyObject* psutil_pids(PyObject* self, PyObject* args); -static PyObject* psutil_ppid_map(PyObject* self, PyObject* args); -static PyObject* psutil_users(PyObject* self, PyObject* args); -static PyObject* psutil_virtual_mem(PyObject* self, PyObject* args); -static PyObject* psutil_net_if_addrs(PyObject* self, PyObject* args); -static PyObject* psutil_net_if_stats(PyObject* self, PyObject* args); - -// --- windows API bindings - -static PyObject* psutil_win32_QueryDosDevice(PyObject* self, PyObject* args); - -// --- internal - -int psutil_proc_suspend_or_resume(DWORD pid, int suspend); diff --git a/python/psutil/psutil/_pswindows.py b/python/psutil/psutil/_pswindows.py deleted file mode 100644 index 2d8babb19..000000000 --- a/python/psutil/psutil/_pswindows.py +++ /dev/null @@ -1,548 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Windows platform implementation.""" - -import errno -import functools -import os -import sys -from collections import namedtuple - -from . import _common -from . import _psutil_windows as cext -from ._common import conn_tmap, usage_percent, isfile_strict -from ._common import sockfam_to_enum, socktype_to_enum -from ._compat import PY3, xrange, lru_cache, long -from ._psutil_windows import (ABOVE_NORMAL_PRIORITY_CLASS, - BELOW_NORMAL_PRIORITY_CLASS, - HIGH_PRIORITY_CLASS, - IDLE_PRIORITY_CLASS, - NORMAL_PRIORITY_CLASS, - REALTIME_PRIORITY_CLASS) - -if sys.version_info >= (3, 4): - import enum -else: - enum = None - -# process priority constants, import from __init__.py: -# http://msdn.microsoft.com/en-us/library/ms686219(v=vs.85).aspx -__extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS", - "HIGH_PRIORITY_CLASS", "IDLE_PRIORITY_CLASS", - "NORMAL_PRIORITY_CLASS", "REALTIME_PRIORITY_CLASS", - "CONN_DELETE_TCB", - "AF_LINK", - ] - -# --- module level constants (gets pushed up to psutil module) - -CONN_DELETE_TCB = "DELETE_TCB" -WAIT_TIMEOUT = 0x00000102 # 258 in decimal -ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES, - cext.ERROR_ACCESS_DENIED]) -if enum is None: - AF_LINK = -1 -else: - AddressFamily = enum.IntEnum('AddressFamily', {'AF_LINK': -1}) - AF_LINK = AddressFamily.AF_LINK - -TCP_STATUSES = { - cext.MIB_TCP_STATE_ESTAB: _common.CONN_ESTABLISHED, - cext.MIB_TCP_STATE_SYN_SENT: _common.CONN_SYN_SENT, - cext.MIB_TCP_STATE_SYN_RCVD: _common.CONN_SYN_RECV, - cext.MIB_TCP_STATE_FIN_WAIT1: _common.CONN_FIN_WAIT1, - cext.MIB_TCP_STATE_FIN_WAIT2: _common.CONN_FIN_WAIT2, - cext.MIB_TCP_STATE_TIME_WAIT: _common.CONN_TIME_WAIT, - cext.MIB_TCP_STATE_CLOSED: _common.CONN_CLOSE, - cext.MIB_TCP_STATE_CLOSE_WAIT: _common.CONN_CLOSE_WAIT, - cext.MIB_TCP_STATE_LAST_ACK: _common.CONN_LAST_ACK, - cext.MIB_TCP_STATE_LISTEN: _common.CONN_LISTEN, - cext.MIB_TCP_STATE_CLOSING: _common.CONN_CLOSING, - cext.MIB_TCP_STATE_DELETE_TCB: CONN_DELETE_TCB, - cext.PSUTIL_CONN_NONE: _common.CONN_NONE, -} - -if enum is not None: - class Priority(enum.IntEnum): - ABOVE_NORMAL_PRIORITY_CLASS = ABOVE_NORMAL_PRIORITY_CLASS - BELOW_NORMAL_PRIORITY_CLASS = BELOW_NORMAL_PRIORITY_CLASS - HIGH_PRIORITY_CLASS = HIGH_PRIORITY_CLASS - IDLE_PRIORITY_CLASS = IDLE_PRIORITY_CLASS - NORMAL_PRIORITY_CLASS = NORMAL_PRIORITY_CLASS - REALTIME_PRIORITY_CLASS = REALTIME_PRIORITY_CLASS - - globals().update(Priority.__members__) - -scputimes = namedtuple('scputimes', ['user', 'system', 'idle']) -svmem = namedtuple('svmem', ['total', 'available', 'percent', 'used', 'free']) -pextmem = namedtuple( - 'pextmem', ['num_page_faults', 'peak_wset', 'wset', 'peak_paged_pool', - 'paged_pool', 'peak_nonpaged_pool', 'nonpaged_pool', - 'pagefile', 'peak_pagefile', 'private']) -pmmap_grouped = namedtuple('pmmap_grouped', ['path', 'rss']) -pmmap_ext = namedtuple( - 'pmmap_ext', 'addr perms ' + ' '.join(pmmap_grouped._fields)) -ntpinfo = namedtuple( - 'ntpinfo', ['num_handles', 'ctx_switches', 'user_time', 'kernel_time', - 'create_time', 'num_threads', 'io_rcount', 'io_wcount', - 'io_rbytes', 'io_wbytes']) - -# set later from __init__.py -NoSuchProcess = None -AccessDenied = None -TimeoutExpired = None - - -@lru_cache(maxsize=512) -def _win32_QueryDosDevice(s): - return cext.win32_QueryDosDevice(s) - - -def _convert_raw_path(s): - # convert paths using native DOS format like: - # "\Device\HarddiskVolume1\Windows\systemew\file.txt" - # into: "C:\Windows\systemew\file.txt" - if PY3 and not isinstance(s, str): - s = s.decode('utf8') - rawdrive = '\\'.join(s.split('\\')[:3]) - driveletter = _win32_QueryDosDevice(rawdrive) - return os.path.join(driveletter, s[len(rawdrive):]) - - -# --- public functions - - -def virtual_memory(): - """System virtual memory as a namedtuple.""" - mem = cext.virtual_mem() - totphys, availphys, totpagef, availpagef, totvirt, freevirt = mem - # - total = totphys - avail = availphys - free = availphys - used = total - avail - percent = usage_percent((total - avail), total, _round=1) - return svmem(total, avail, percent, used, free) - - -def swap_memory(): - """Swap system memory as a (total, used, free, sin, sout) tuple.""" - mem = cext.virtual_mem() - total = mem[2] - free = mem[3] - used = total - free - percent = usage_percent(used, total, _round=1) - return _common.sswap(total, used, free, percent, 0, 0) - - -def disk_usage(path): - """Return disk usage associated with path.""" - try: - total, free = cext.disk_usage(path) - except WindowsError: - if not os.path.exists(path): - msg = "No such file or directory: '%s'" % path - raise OSError(errno.ENOENT, msg) - raise - used = total - free - percent = usage_percent(used, total, _round=1) - return _common.sdiskusage(total, used, free, percent) - - -def disk_partitions(all): - """Return disk partitions.""" - rawlist = cext.disk_partitions(all) - return [_common.sdiskpart(*x) for x in rawlist] - - -def cpu_times(): - """Return system CPU times as a named tuple.""" - user, system, idle = cext.cpu_times() - return scputimes(user, system, idle) - - -def per_cpu_times(): - """Return system per-CPU times as a list of named tuples.""" - ret = [] - for cpu_t in cext.per_cpu_times(): - user, system, idle = cpu_t - item = scputimes(user, system, idle) - ret.append(item) - return ret - - -def cpu_count_logical(): - """Return the number of logical CPUs in the system.""" - return cext.cpu_count_logical() - - -def cpu_count_physical(): - """Return the number of physical CPUs in the system.""" - return cext.cpu_count_phys() - - -def boot_time(): - """The system boot time expressed in seconds since the epoch.""" - return cext.boot_time() - - -def net_connections(kind, _pid=-1): - """Return socket connections. If pid == -1 return system-wide - connections (as opposed to connections opened by one process only). - """ - if kind not in conn_tmap: - raise ValueError("invalid %r kind argument; choose between %s" - % (kind, ', '.join([repr(x) for x in conn_tmap]))) - families, types = conn_tmap[kind] - rawlist = cext.net_connections(_pid, families, types) - ret = set() - for item in rawlist: - fd, fam, type, laddr, raddr, status, pid = item - status = TCP_STATUSES[status] - fam = sockfam_to_enum(fam) - type = socktype_to_enum(type) - if _pid == -1: - nt = _common.sconn(fd, fam, type, laddr, raddr, status, pid) - else: - nt = _common.pconn(fd, fam, type, laddr, raddr, status) - ret.add(nt) - return list(ret) - - -def net_if_stats(): - ret = cext.net_if_stats() - for name, items in ret.items(): - isup, duplex, speed, mtu = items - if hasattr(_common, 'NicDuplex'): - duplex = _common.NicDuplex(duplex) - ret[name] = _common.snicstats(isup, duplex, speed, mtu) - return ret - - -def users(): - """Return currently connected users as a list of namedtuples.""" - retlist = [] - rawlist = cext.users() - for item in rawlist: - user, hostname, tstamp = item - nt = _common.suser(user, None, hostname, tstamp) - retlist.append(nt) - return retlist - - -pids = cext.pids -pid_exists = cext.pid_exists -net_io_counters = cext.net_io_counters -disk_io_counters = cext.disk_io_counters -ppid_map = cext.ppid_map # not meant to be public -net_if_addrs = cext.net_if_addrs - - -def wrap_exceptions(fun): - """Decorator which translates bare OSError and WindowsError - exceptions into NoSuchProcess and AccessDenied. - """ - @functools.wraps(fun) - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - # support for private module import - if NoSuchProcess is None or AccessDenied is None: - raise - if err.errno in ACCESS_DENIED_SET: - raise AccessDenied(self.pid, self._name) - if err.errno == errno.ESRCH: - raise NoSuchProcess(self.pid, self._name) - raise - return wrapper - - -class Process(object): - """Wrapper class around underlying C implementation.""" - - __slots__ = ["pid", "_name", "_ppid"] - - def __init__(self, pid): - self.pid = pid - self._name = None - self._ppid = None - - @wrap_exceptions - def name(self): - """Return process name, which on Windows is always the final - part of the executable. - """ - # This is how PIDs 0 and 4 are always represented in taskmgr - # and process-hacker. - if self.pid == 0: - return "System Idle Process" - elif self.pid == 4: - return "System" - else: - try: - # Note: this will fail with AD for most PIDs owned - # by another user but it's faster. - return os.path.basename(self.exe()) - except AccessDenied: - return cext.proc_name(self.pid) - - @wrap_exceptions - def exe(self): - # Note: os.path.exists(path) may return False even if the file - # is there, see: - # http://stackoverflow.com/questions/3112546/os-path-exists-lies - - # see https://github.com/giampaolo/psutil/issues/414 - # see https://github.com/giampaolo/psutil/issues/528 - if self.pid in (0, 4): - raise AccessDenied(self.pid, self._name) - return _convert_raw_path(cext.proc_exe(self.pid)) - - @wrap_exceptions - def cmdline(self): - return cext.proc_cmdline(self.pid) - - def ppid(self): - try: - return ppid_map()[self.pid] - except KeyError: - raise NoSuchProcess(self.pid, self._name) - - def _get_raw_meminfo(self): - try: - return cext.proc_memory_info(self.pid) - except OSError as err: - if err.errno in ACCESS_DENIED_SET: - # TODO: the C ext can probably be refactored in order - # to get this from cext.proc_info() - return cext.proc_memory_info_2(self.pid) - raise - - @wrap_exceptions - def memory_info(self): - # on Windows RSS == WorkingSetSize and VSM == PagefileUsage - # fields of PROCESS_MEMORY_COUNTERS struct: - # http://msdn.microsoft.com/en-us/library/windows/desktop/ - # ms684877(v=vs.85).aspx - t = self._get_raw_meminfo() - return _common.pmem(t[2], t[7]) - - @wrap_exceptions - def memory_info_ex(self): - return pextmem(*self._get_raw_meminfo()) - - def memory_maps(self): - try: - raw = cext.proc_memory_maps(self.pid) - except OSError as err: - # XXX - can't use wrap_exceptions decorator as we're - # returning a generator; probably needs refactoring. - if err.errno in ACCESS_DENIED_SET: - raise AccessDenied(self.pid, self._name) - if err.errno == errno.ESRCH: - raise NoSuchProcess(self.pid, self._name) - raise - else: - for addr, perm, path, rss in raw: - path = _convert_raw_path(path) - addr = hex(addr) - yield (addr, perm, path, rss) - - @wrap_exceptions - def kill(self): - return cext.proc_kill(self.pid) - - @wrap_exceptions - def wait(self, timeout=None): - if timeout is None: - timeout = cext.INFINITE - else: - # WaitForSingleObject() expects time in milliseconds - timeout = int(timeout * 1000) - ret = cext.proc_wait(self.pid, timeout) - if ret == WAIT_TIMEOUT: - # support for private module import - if TimeoutExpired is None: - raise RuntimeError("timeout expired") - raise TimeoutExpired(timeout, self.pid, self._name) - return ret - - @wrap_exceptions - def username(self): - if self.pid in (0, 4): - return 'NT AUTHORITY\\SYSTEM' - return cext.proc_username(self.pid) - - @wrap_exceptions - def create_time(self): - # special case for kernel process PIDs; return system boot time - if self.pid in (0, 4): - return boot_time() - try: - return cext.proc_create_time(self.pid) - except OSError as err: - if err.errno in ACCESS_DENIED_SET: - return ntpinfo(*cext.proc_info(self.pid)).create_time - raise - - @wrap_exceptions - def num_threads(self): - return ntpinfo(*cext.proc_info(self.pid)).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) - return retlist - - @wrap_exceptions - def cpu_times(self): - try: - ret = cext.proc_cpu_times(self.pid) - except OSError as err: - if err.errno in ACCESS_DENIED_SET: - nt = ntpinfo(*cext.proc_info(self.pid)) - ret = (nt.user_time, nt.kernel_time) - else: - raise - return _common.pcputimes(*ret) - - @wrap_exceptions - def suspend(self): - return cext.proc_suspend(self.pid) - - @wrap_exceptions - def resume(self): - return cext.proc_resume(self.pid) - - @wrap_exceptions - def cwd(self): - if self.pid in (0, 4): - raise AccessDenied(self.pid, self._name) - # return a normalized pathname since the native C function appends - # "\\" at the and of the path - path = cext.proc_cwd(self.pid) - return os.path.normpath(path) - - @wrap_exceptions - def open_files(self): - if self.pid in (0, 4): - return [] - retlist = [] - # Filenames come in in native format like: - # "\Device\HarddiskVolume1\Windows\systemew\file.txt" - # Convert the first part in the corresponding drive letter - # (e.g. "C:\") by using Windows's QueryDosDevice() - raw_file_names = cext.proc_open_files(self.pid) - for _file in raw_file_names: - _file = _convert_raw_path(_file) - if isfile_strict(_file) and _file not in retlist: - ntuple = _common.popenfile(_file, -1) - retlist.append(ntuple) - return retlist - - @wrap_exceptions - def connections(self, kind='inet'): - return net_connections(kind, _pid=self.pid) - - @wrap_exceptions - def nice_get(self): - value = cext.proc_priority_get(self.pid) - if enum is not None: - value = Priority(value) - return value - - @wrap_exceptions - def nice_set(self, value): - return cext.proc_priority_set(self.pid, value) - - # available on Windows >= Vista - if hasattr(cext, "proc_io_priority_get"): - @wrap_exceptions - def ionice_get(self): - return cext.proc_io_priority_get(self.pid) - - @wrap_exceptions - def ionice_set(self, value, _): - if _: - raise TypeError("set_proc_ionice() on Windows takes only " - "1 argument (2 given)") - if value not in (2, 1, 0): - raise ValueError("value must be 2 (normal), 1 (low) or 0 " - "(very low); got %r" % value) - return cext.proc_io_priority_set(self.pid, value) - - @wrap_exceptions - def io_counters(self): - try: - ret = cext.proc_io_counters(self.pid) - except OSError as err: - if err.errno in ACCESS_DENIED_SET: - nt = ntpinfo(*cext.proc_info(self.pid)) - ret = (nt.io_rcount, nt.io_wcount, nt.io_rbytes, nt.io_wbytes) - else: - raise - return _common.pio(*ret) - - @wrap_exceptions - def status(self): - suspended = cext.proc_is_suspended(self.pid) - if suspended: - return _common.STATUS_STOPPED - else: - return _common.STATUS_RUNNING - - @wrap_exceptions - def cpu_affinity_get(self): - def from_bitmask(x): - return [i for i in xrange(64) if (1 << i) & x] - bitmask = cext.proc_cpu_affinity_get(self.pid) - return from_bitmask(bitmask) - - @wrap_exceptions - def cpu_affinity_set(self, value): - def to_bitmask(l): - if not l: - raise ValueError("invalid argument %r" % l) - out = 0 - for b in l: - out |= 2 ** b - return out - - # SetProcessAffinityMask() states that ERROR_INVALID_PARAMETER - # is returned for an invalid CPU but this seems not to be true, - # therefore we check CPUs validy beforehand. - allcpus = list(range(len(per_cpu_times()))) - for cpu in value: - if cpu not in allcpus: - if not isinstance(cpu, (int, long)): - raise TypeError( - "invalid CPU %r; an integer is required" % cpu) - else: - raise ValueError("invalid CPU %r" % cpu) - - bitmask = to_bitmask(value) - cext.proc_cpu_affinity_set(self.pid, bitmask) - - @wrap_exceptions - def num_handles(self): - try: - return cext.proc_num_handles(self.pid) - except OSError as err: - if err.errno in ACCESS_DENIED_SET: - return ntpinfo(*cext.proc_info(self.pid)).num_handles - raise - - @wrap_exceptions - def num_ctx_switches(self): - ctx_switches = ntpinfo(*cext.proc_info(self.pid)).ctx_switches - # only voluntary ctx switches are supported - return _common.pctxsw(ctx_switches, 0) diff --git a/python/psutil/psutil/arch/bsd/process_info.c b/python/psutil/psutil/arch/bsd/process_info.c deleted file mode 100644 index 4d7392406..000000000 --- a/python/psutil/psutil/arch/bsd/process_info.c +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Helper functions related to fetching process information. - * Used by _psutil_bsd module methods. - */ - - -#include <Python.h> -#include <assert.h> -#include <errno.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/types.h> -#include <sys/sysctl.h> -#include <sys/param.h> -#include <sys/user.h> -#include <sys/proc.h> -#include <signal.h> - -#include "process_info.h" - - -/* - * Returns a list of all BSD processes on the system. This routine - * allocates the list and puts it in *procList and a count of the - * number of entries in *procCount. You are responsible for freeing - * this list (use "free" from System framework). - * On success, the function returns 0. - * On error, the function returns a BSD errno value. - */ -int -psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount) -{ - int err; - struct kinfo_proc *result; - int done; - static const int name[] = { CTL_KERN, KERN_PROC, KERN_PROC_PROC, 0 }; - // Declaring name as const requires us to cast it when passing it to - // sysctl because the prototype doesn't include the const modifier. - size_t length; - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - *procCount = 0; - - /* - * We start by calling sysctl with result == NULL and length == 0. - * That will succeed, and set length to the appropriate length. - * We then allocate a buffer of that size and call sysctl again - * with that buffer. If that succeeds, we're done. If that fails - * with ENOMEM, we have to throw away our buffer and loop. Note - * that the loop causes use to call sysctl with NULL again; this - * is necessary because the ENOMEM failure case sets length to - * the amount of data returned, not the amount of data that - * could have been returned. - */ - result = NULL; - done = 0; - do { - assert(result == NULL); - // Call sysctl with a NULL buffer. - length = 0; - err = sysctl((int *)name, (sizeof(name) / sizeof(*name)) - 1, - NULL, &length, NULL, 0); - if (err == -1) - err = errno; - - // Allocate an appropriately sized buffer based on the results - // from the previous call. - if (err == 0) { - result = malloc(length); - if (result == NULL) - err = ENOMEM; - } - - // Call sysctl again with the new buffer. If we get an ENOMEM - // error, toss away our buffer and start again. - if (err == 0) { - err = sysctl((int *) name, (sizeof(name) / sizeof(*name)) - 1, - result, &length, NULL, 0); - if (err == -1) - err = errno; - if (err == 0) { - done = 1; - } - else if (err == ENOMEM) { - assert(result != NULL); - free(result); - result = NULL; - err = 0; - } - } - } while (err == 0 && ! done); - - // Clean up and establish post conditions. - if (err != 0 && result != NULL) { - free(result); - result = NULL; - } - - *procList = result; - *procCount = length / sizeof(struct kinfo_proc); - - assert((err == 0) == (*procList != NULL)); - return err; -} - - -char -*psutil_get_cmd_path(long pid, size_t *pathsize) -{ - int mib[4]; - char *path; - size_t size = 0; - - /* - * Make a sysctl() call to get the raw argument space of the process. - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PATHNAME; - mib[3] = pid; - - // call with a null buffer first to determine if we need a buffer - if (sysctl(mib, 4, NULL, &size, NULL, 0) == -1) - return NULL; - - path = malloc(size); - if (path == NULL) { - PyErr_NoMemory(); - return NULL; - } - - *pathsize = size; - if (sysctl(mib, 4, path, &size, NULL, 0) == -1) { - free(path); - return NULL; // Insufficient privileges - } - - return path; -} - - -/* - * XXX no longer used; it probably makese sense to remove it. - * Borrowed from psi Python System Information project - * - * Get command arguments and environment variables. - * - * Based on code from ps. - * - * Returns: - * 0 for success; - * -1 for failure (Exception raised); - * 1 for insufficient privileges. - */ -char -*psutil_get_cmd_args(long pid, size_t *argsize) -{ - int mib[4], argmax; - size_t size = sizeof(argmax); - char *procargs = NULL; - - // Get the maximum process arguments size. - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - size = sizeof(argmax); - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == -1) - return NULL; - - // Allocate space for the arguments. - procargs = (char *)malloc(argmax); - if (procargs == NULL) { - PyErr_NoMemory(); - return NULL; - } - - /* - * Make a sysctl() call to get the raw argument space of the process. - */ - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_ARGS; - mib[3] = pid; - - size = argmax; - if (sysctl(mib, 4, procargs, &size, NULL, 0) == -1) { - free(procargs); - return NULL; // Insufficient privileges - } - - // return string and set the length of arguments - *argsize = size; - return procargs; -} - - -// returns the command line as a python list object -PyObject * -psutil_get_arg_list(long pid) -{ - char *argstr = NULL; - int pos = 0; - size_t argsize = 0; - PyObject *retlist = Py_BuildValue("[]"); - PyObject *item = NULL; - - if (pid < 0) - return retlist; - argstr = psutil_get_cmd_args(pid, &argsize); - if (argstr == NULL) - goto error; - - // args are returned as a flattened string with \0 separators between - // arguments add each string to the list then step forward to the next - // separator - if (argsize > 0) { - while (pos < argsize) { - item = Py_BuildValue("s", &argstr[pos]); - if (!item) - goto error; - if (PyList_Append(retlist, item)) - goto error; - Py_DECREF(item); - pos = pos + strlen(&argstr[pos]) + 1; - } - } - - free(argstr); - return retlist; - -error: - Py_XDECREF(item); - Py_DECREF(retlist); - if (argstr != NULL) - free(argstr); - return NULL; -} - - -/* - * Return 1 if PID exists in the current process list, else 0. - */ -int -psutil_pid_exists(long pid) -{ - int kill_ret; - - if (pid < 0) - return 0; - // if kill returns success of permission denied we know it's a valid PID - kill_ret = kill(pid , 0); - if ((0 == kill_ret) || (EPERM == errno)) - return 1; - // otherwise return 0 for PID not found - return 0; -} - diff --git a/python/psutil/psutil/arch/bsd/process_info.h b/python/psutil/psutil/arch/bsd/process_info.h deleted file mode 100644 index 858bd88a5..000000000 --- a/python/psutil/psutil/arch/bsd/process_info.h +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -typedef struct kinfo_proc kinfo_proc; - -char *psutil_get_cmd_args(long pid, size_t *argsize); -char *psutil_get_cmd_path(long pid, size_t *pathsize); -int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount); -int psutil_pid_exists(long pid); -PyObject* psutil_get_arg_list(long pid); diff --git a/python/psutil/psutil/arch/osx/process_info.c b/python/psutil/psutil/arch/osx/process_info.c deleted file mode 100644 index b6dd5bb93..000000000 --- a/python/psutil/psutil/arch/osx/process_info.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Helper functions related to fetching process information. - * Used by _psutil_osx module methods. - */ - - -#include <Python.h> -#include <assert.h> -#include <errno.h> -#include <limits.h> // for INT_MAX -#include <stdbool.h> -#include <stdlib.h> -#include <stdio.h> -#include <signal.h> -#include <sys/sysctl.h> -#include <libproc.h> - -#include "process_info.h" -#include "../../_psutil_common.h" - - -/* - * Return 1 if PID exists in the current process list, else 0. - */ -int -psutil_pid_exists(long pid) -{ - int kill_ret; - - // save some time if it's an invalid PID - if (pid < 0) - return 0; - // if kill returns success of permission denied we know it's a valid PID - kill_ret = kill(pid , 0); - if ( (0 == kill_ret) || (EPERM == errno)) - return 1; - - // otherwise return 0 for PID not found - return 0; -} - - -/* - * Returns a list of all BSD processes on the system. This routine - * allocates the list and puts it in *procList and a count of the - * number of entries in *procCount. You are responsible for freeing - * this list (use "free" from System framework). - * On success, the function returns 0. - * On error, the function returns a BSD errno value. - */ -int -psutil_get_proc_list(kinfo_proc **procList, size_t *procCount) -{ - // Declaring mib as const requires use of a cast since the - // sysctl prototype doesn't include the const modifier. - static const int mib3[3] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL }; - size_t size, size2; - void *ptr; - int err, lim = 8; // some limit - - assert( procList != NULL); - assert(*procList == NULL); - assert(procCount != NULL); - - *procCount = 0; - - /* - * We start by calling sysctl with ptr == NULL and size == 0. - * That will succeed, and set size to the appropriate length. - * We then allocate a buffer of at least that size and call - * sysctl with that buffer. If that succeeds, we're done. - * If that call fails with ENOMEM, we throw the buffer away - * and try again. - * Note that the loop calls sysctl with NULL again. This is - * is necessary because the ENOMEM failure case sets size to - * the amount of data returned, not the amount of data that - * could have been returned. - */ - while (lim-- > 0) { - size = 0; - if (sysctl((int *)mib3, 3, NULL, &size, NULL, 0) == -1) - return errno; - size2 = size + (size >> 3); // add some - if (size2 > size) { - ptr = malloc(size2); - if (ptr == NULL) - ptr = malloc(size); - else - size = size2; - } - else { - ptr = malloc(size); - } - if (ptr == NULL) - return ENOMEM; - - if (sysctl((int *)mib3, 3, ptr, &size, NULL, 0) == -1) { - err = errno; - free(ptr); - if (err != ENOMEM) - return err; - } - else { - *procList = (kinfo_proc *)ptr; - *procCount = size / sizeof(kinfo_proc); - return 0; - } - } - return ENOMEM; -} - - -// Read the maximum argument size for processes -int -psutil_get_argmax() -{ - int argmax; - int mib[] = { CTL_KERN, KERN_ARGMAX }; - size_t size = sizeof(argmax); - - if (sysctl(mib, 2, &argmax, &size, NULL, 0) == 0) - return argmax; - return 0; -} - - -// return process args as a python list -PyObject * -psutil_get_arg_list(long pid) -{ - int mib[3]; - int nargs; - int len; - char *procargs = NULL; - char *arg_ptr; - char *arg_end; - char *curr_arg; - size_t argmax; - PyObject *arg = NULL; - PyObject *arglist = NULL; - - // special case for PID 0 (kernel_task) where cmdline cannot be fetched - if (pid == 0) - return Py_BuildValue("[]"); - - // read argmax and allocate memory for argument space. - argmax = psutil_get_argmax(); - if (! argmax) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - procargs = (char *)malloc(argmax); - if (NULL == procargs) { - PyErr_SetFromErrno(PyExc_OSError); - goto error; - } - - // read argument space - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = pid; - if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) { - if (EINVAL == errno) { - // EINVAL == access denied OR nonexistent PID - if (psutil_pid_exists(pid)) - AccessDenied(); - else - NoSuchProcess(); - } - goto error; - } - - arg_end = &procargs[argmax]; - // copy the number of arguments to nargs - memcpy(&nargs, procargs, sizeof(nargs)); - - arg_ptr = procargs + sizeof(nargs); - len = strlen(arg_ptr); - arg_ptr += len + 1; - - if (arg_ptr == arg_end) { - free(procargs); - return Py_BuildValue("[]"); - } - - // skip ahead to the first argument - for (; arg_ptr < arg_end; arg_ptr++) { - if (*arg_ptr != '\0') - break; - } - - // iterate through arguments - curr_arg = arg_ptr; - arglist = Py_BuildValue("[]"); - if (!arglist) - goto error; - while (arg_ptr < arg_end && nargs > 0) { - if (*arg_ptr++ == '\0') { - arg = Py_BuildValue("s", curr_arg); - if (!arg) - goto error; - if (PyList_Append(arglist, arg)) - goto error; - Py_DECREF(arg); - // iterate to next arg and decrement # of args - curr_arg = arg_ptr; - nargs--; - } - } - - free(procargs); - return arglist; - -error: - Py_XDECREF(arg); - Py_XDECREF(arglist); - if (procargs != NULL) - free(procargs); - return NULL; -} - - -int -psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp) -{ - int mib[4]; - size_t len; - mib[0] = CTL_KERN; - mib[1] = KERN_PROC; - mib[2] = KERN_PROC_PID; - mib[3] = pid; - - // fetch the info with sysctl() - len = sizeof(struct kinfo_proc); - - // now read the data from sysctl - if (sysctl(mib, 4, kp, &len, NULL, 0) == -1) { - // raise an exception and throw errno as the error - PyErr_SetFromErrno(PyExc_OSError); - return -1; - } - - // sysctl succeeds but len is zero, happens when process has gone away - if (len == 0) { - NoSuchProcess(); - return -1; - } - return 0; -} - - -/* - * A thin wrapper around proc_pidinfo() - */ -int -psutil_proc_pidinfo(long pid, int flavor, void *pti, int size) -{ - int ret = proc_pidinfo((int)pid, flavor, 0, pti, size); - if (ret == 0) { - if (! psutil_pid_exists(pid)) { - NoSuchProcess(); - return 0; - } - else { - AccessDenied(); - return 0; - } - } - else if (ret != size) { - AccessDenied(); - return 0; - } - else { - return 1; - } -} diff --git a/python/psutil/psutil/arch/osx/process_info.h b/python/psutil/psutil/arch/osx/process_info.h deleted file mode 100644 index c89c8570e..000000000 --- a/python/psutil/psutil/arch/osx/process_info.h +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include <Python.h> - -typedef struct kinfo_proc kinfo_proc; - -int psutil_get_argmax(void); -int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp); -int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount); -int psutil_pid_exists(long pid); -int psutil_proc_pidinfo(long pid, int flavor, void *pti, int size); -PyObject* psutil_get_arg_list(long pid); diff --git a/python/psutil/psutil/arch/windows/glpi.h b/python/psutil/psutil/arch/windows/glpi.h deleted file mode 100644 index 6f9848373..000000000 --- a/python/psutil/psutil/arch/windows/glpi.h +++ /dev/null @@ -1,41 +0,0 @@ -// mingw headers are missing this - -typedef enum _LOGICAL_PROCESSOR_RELATIONSHIP { - RelationProcessorCore, - RelationNumaNode, - RelationCache, - RelationProcessorPackage, - RelationGroup, - RelationAll=0xffff -} LOGICAL_PROCESSOR_RELATIONSHIP; - -typedef enum _PROCESSOR_CACHE_TYPE { - CacheUnified,CacheInstruction,CacheData,CacheTrace -} PROCESSOR_CACHE_TYPE; - -typedef struct _CACHE_DESCRIPTOR { - BYTE Level; - BYTE Associativity; - WORD LineSize; - DWORD Size; - PROCESSOR_CACHE_TYPE Type; -} CACHE_DESCRIPTOR,*PCACHE_DESCRIPTOR; - -typedef struct _SYSTEM_LOGICAL_PROCESSOR_INFORMATION { - ULONG_PTR ProcessorMask; - LOGICAL_PROCESSOR_RELATIONSHIP Relationship; - union { - struct { - BYTE Flags; - } ProcessorCore; - struct { - DWORD NodeNumber; - } NumaNode; - CACHE_DESCRIPTOR Cache; - ULONGLONG Reserved[2]; - }; -} SYSTEM_LOGICAL_PROCESSOR_INFORMATION,*PSYSTEM_LOGICAL_PROCESSOR_INFORMATION; - -WINBASEAPI WINBOOL WINAPI -GetLogicalProcessorInformation(PSYSTEM_LOGICAL_PROCESSOR_INFORMATION Buffer, - PDWORD ReturnedLength);
\ No newline at end of file diff --git a/python/psutil/psutil/arch/windows/inet_ntop.c b/python/psutil/psutil/arch/windows/inet_ntop.c deleted file mode 100644 index b9fffd1c1..000000000 --- a/python/psutil/psutil/arch/windows/inet_ntop.c +++ /dev/null @@ -1,41 +0,0 @@ -#include "inet_ntop.h" - -// From: https://memset.wordpress.com/2010/10/09/inet_ntop-for-win32/ -PCSTR -WSAAPI -inet_ntop( - __in INT Family, - __in PVOID pAddr, - __out_ecount(StringBufSize) PSTR pStringBuf, - __in size_t StringBufSize - ) -{ - DWORD dwAddressLength = 0; - struct sockaddr_storage srcaddr; - struct sockaddr_in *srcaddr4 = (struct sockaddr_in*) &srcaddr; - struct sockaddr_in6 *srcaddr6 = (struct sockaddr_in6*) &srcaddr; - - memset(&srcaddr, 0, sizeof(struct sockaddr_storage)); - srcaddr.ss_family = Family; - - if (Family == AF_INET) - { - dwAddressLength = sizeof(struct sockaddr_in); - memcpy(&(srcaddr4->sin_addr), pAddr, sizeof(struct in_addr)); - } else if (Family == AF_INET6) - { - dwAddressLength = sizeof(struct sockaddr_in6); - memcpy(&(srcaddr6->sin6_addr), pAddr, sizeof(struct in6_addr)); - } else { - return NULL; - } - - if (WSAAddressToString((LPSOCKADDR) &srcaddr, - dwAddressLength, - 0, - pStringBuf, - (LPDWORD) &StringBufSize) != 0) { - return NULL; - } - return pStringBuf; -}
\ No newline at end of file diff --git a/python/psutil/psutil/arch/windows/inet_ntop.h b/python/psutil/psutil/arch/windows/inet_ntop.h deleted file mode 100644 index 0d97e28c8..000000000 --- a/python/psutil/psutil/arch/windows/inet_ntop.h +++ /dev/null @@ -1,10 +0,0 @@ -#include <ws2tcpip.h> - -PCSTR -WSAAPI -inet_ntop( - __in INT Family, - __in PVOID pAddr, - __out_ecount(StringBufSize) PSTR pStringBuf, - __in size_t StringBufSize -);
\ No newline at end of file diff --git a/python/psutil/psutil/arch/windows/ntextapi.h b/python/psutil/psutil/arch/windows/ntextapi.h deleted file mode 100644 index d10432a3e..000000000 --- a/python/psutil/psutil/arch/windows/ntextapi.h +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ -#if !defined(__NTEXTAPI_H__) -#define __NTEXTAPI_H__ -#include <winternl.h> - -typedef enum _KTHREAD_STATE { - Initialized, - Ready, - Running, - Standby, - Terminated, - Waiting, - Transition, - DeferredReady, - GateWait, - MaximumThreadState -} KTHREAD_STATE, *PKTHREAD_STATE; - -typedef enum _KWAIT_REASON { - Executive = 0, - FreePage = 1, - PageIn = 2, - PoolAllocation = 3, - DelayExecution = 4, - Suspended = 5, - UserRequest = 6, - WrExecutive = 7, - WrFreePage = 8, - WrPageIn = 9, - WrPoolAllocation = 10, - WrDelayExecution = 11, - WrSuspended = 12, - WrUserRequest = 13, - WrEventPair = 14, - WrQueue = 15, - WrLpcReceive = 16, - WrLpcReply = 17, - WrVirtualMemory = 18, - WrPageOut = 19, - WrRendezvous = 20, - Spare2 = 21, - Spare3 = 22, - Spare4 = 23, - Spare5 = 24, - WrCalloutStack = 25, - WrKernel = 26, - WrResource = 27, - WrPushLock = 28, - WrMutex = 29, - WrQuantumEnd = 30, - WrDispatchInt = 31, - WrPreempted = 32, - WrYieldExecution = 33, - WrFastMutex = 34, - WrGuardedMutex = 35, - WrRundown = 36, - MaximumWaitReason = 37 -} KWAIT_REASON, *PKWAIT_REASON; - -typedef struct _CLIENT_ID { - HANDLE UniqueProcess; - HANDLE UniqueThread; -} CLIENT_ID, *PCLIENT_ID; - -typedef struct _SYSTEM_THREAD_INFORMATION { - LARGE_INTEGER KernelTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER CreateTime; - ULONG WaitTime; - PVOID StartAddress; - CLIENT_ID ClientId; - LONG Priority; - LONG BasePriority; - ULONG ContextSwitches; - ULONG ThreadState; - KWAIT_REASON WaitReason; -} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION; - -typedef struct _TEB *PTEB; - -// private -typedef struct _SYSTEM_EXTENDED_THREAD_INFORMATION { - SYSTEM_THREAD_INFORMATION ThreadInfo; - PVOID StackBase; - PVOID StackLimit; - PVOID Win32StartAddress; - PTEB TebBase; - ULONG_PTR Reserved2; - ULONG_PTR Reserved3; - ULONG_PTR Reserved4; -} SYSTEM_EXTENDED_THREAD_INFORMATION, *PSYSTEM_EXTENDED_THREAD_INFORMATION; - -typedef struct _SYSTEM_PROCESS_INFORMATION2 { - ULONG NextEntryOffset; - ULONG NumberOfThreads; - LARGE_INTEGER SpareLi1; - LARGE_INTEGER SpareLi2; - LARGE_INTEGER SpareLi3; - LARGE_INTEGER CreateTime; - LARGE_INTEGER UserTime; - LARGE_INTEGER KernelTime; - UNICODE_STRING ImageName; - LONG BasePriority; - HANDLE UniqueProcessId; - HANDLE InheritedFromUniqueProcessId; - ULONG HandleCount; - ULONG SessionId; - ULONG_PTR PageDirectoryBase; - SIZE_T PeakVirtualSize; - SIZE_T VirtualSize; - DWORD PageFaultCount; - SIZE_T PeakWorkingSetSize; - SIZE_T WorkingSetSize; - SIZE_T QuotaPeakPagedPoolUsage; - SIZE_T QuotaPagedPoolUsage; - SIZE_T QuotaPeakNonPagedPoolUsage; - SIZE_T QuotaNonPagedPoolUsage; - SIZE_T PagefileUsage; - SIZE_T PeakPagefileUsage; - SIZE_T PrivatePageCount; - LARGE_INTEGER ReadOperationCount; - LARGE_INTEGER WriteOperationCount; - LARGE_INTEGER OtherOperationCount; - LARGE_INTEGER ReadTransferCount; - LARGE_INTEGER WriteTransferCount; - LARGE_INTEGER OtherTransferCount; - SYSTEM_THREAD_INFORMATION Threads[1]; -} SYSTEM_PROCESS_INFORMATION2, *PSYSTEM_PROCESS_INFORMATION2; - -#define SYSTEM_PROCESS_INFORMATION SYSTEM_PROCESS_INFORMATION2 -#define PSYSTEM_PROCESS_INFORMATION PSYSTEM_PROCESS_INFORMATION2 - - -// ================================================ -// psutil.users() support -// ================================================ - -typedef struct _WINSTATION_INFO { - BYTE Reserved1[72]; - ULONG SessionId; - BYTE Reserved2[4]; - FILETIME ConnectTime; - FILETIME DisconnectTime; - FILETIME LastInputTime; - FILETIME LoginTime; - BYTE Reserved3[1096]; - FILETIME CurrentTime; -} WINSTATION_INFO, *PWINSTATION_INFO; - -typedef BOOLEAN (WINAPI * PWINSTATIONQUERYINFORMATIONW) - (HANDLE,ULONG,WINSTATIONINFOCLASS,PVOID,ULONG,PULONG); - - -/* - * NtQueryInformationProcess code taken from - * http://wj32.wordpress.com/2009/01/24/howto-get-the-command-line-of-processes/ - * typedefs needed to compile against ntdll functions not exposted in the API - */ -typedef LONG NTSTATUS; - -typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength, - PDWORD ReturnLength -); - -typedef NTSTATUS (NTAPI *_NtSetInformationProcess)( - HANDLE ProcessHandle, - DWORD ProcessInformationClass, - PVOID ProcessInformation, - DWORD ProcessInformationLength -); - - -typedef enum _PROCESSINFOCLASS2 { - _ProcessBasicInformation, - ProcessQuotaLimits, - ProcessIoCounters, - ProcessVmCounters, - ProcessTimes, - ProcessBasePriority, - ProcessRaisePriority, - ProcessDebugPort, - ProcessExceptionPort, - ProcessAccessToken, - ProcessLdtInformation, - ProcessLdtSize, - ProcessDefaultHardErrorMode, - ProcessIoPortHandlers, - ProcessPooledUsageAndLimits, - ProcessWorkingSetWatch, - ProcessUserModeIOPL, - ProcessEnableAlignmentFaultFixup, - ProcessPriorityClass, - ProcessWx86Information, - ProcessHandleCount, - ProcessAffinityMask, - ProcessPriorityBoost, - ProcessDeviceMap, - ProcessSessionInformation, - ProcessForegroundInformation, - _ProcessWow64Information, - /* added after XP+ */ - ProcessImageFileName, - ProcessLUIDDeviceMapsEnabled, - ProcessBreakOnTermination, - ProcessDebugObjectHandle, - ProcessDebugFlags, - ProcessHandleTracing, - ProcessIoPriority, - ProcessExecuteFlags, - ProcessResourceManagement, - ProcessCookie, - ProcessImageInformation, - MaxProcessInfoClass -} PROCESSINFOCLASS2; - -#define PROCESSINFOCLASS PROCESSINFOCLASS2 -#define ProcessBasicInformation _ProcessBasicInformation -#define ProcessWow64Information _ProcessWow64Information - -#endif // __NTEXTAPI_H__ diff --git a/python/psutil/psutil/arch/windows/process_handles.c b/python/psutil/psutil/arch/windows/process_handles.c deleted file mode 100644 index b3f480af5..000000000 --- a/python/psutil/psutil/arch/windows/process_handles.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - */ -#include "process_handles.h" - -static _NtQuerySystemInformation __NtQuerySystemInformation = NULL; -static _NtQueryObject __NtQueryObject = NULL; - -CRITICAL_SECTION g_cs; -BOOL g_initialized = FALSE; -NTSTATUS g_status; -HANDLE g_hFile = NULL; -HANDLE g_hEvtStart = NULL; -HANDLE g_hEvtFinish = NULL; -HANDLE g_hThread = NULL; -PUNICODE_STRING g_pNameBuffer = NULL; -ULONG g_dwSize = 0; -ULONG g_dwLength = 0; -PVOID g_fiber = NULL; - - -PVOID -GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName) -{ - return GetProcAddress(GetModuleHandleA(LibraryName), ProcName); -} - -PyObject * -psutil_get_open_files(long dwPid, HANDLE hProcess) -{ - OSVERSIONINFO osvi; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFO)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); - GetVersionEx(&osvi); - - // Threaded version only works for Vista+ - if (osvi.dwMajorVersion >= 6) - return psutil_get_open_files_ntqueryobject(dwPid, hProcess); - else - return psutil_get_open_files_getmappedfilename(dwPid, hProcess); -} - -VOID -psutil_get_open_files_init(BOOL threaded) -{ - if (g_initialized == TRUE) - return; - - // Resolve the Windows API calls - __NtQuerySystemInformation = - GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation"); - __NtQueryObject = GetLibraryProcAddress("ntdll.dll", "NtQueryObject"); - - // Create events for signalling work between threads - if (threaded == TRUE) { - g_hEvtStart = CreateEvent(NULL, FALSE, FALSE, NULL); - g_hEvtFinish = CreateEvent(NULL, FALSE, FALSE, NULL); - InitializeCriticalSection(&g_cs); - } - - g_initialized = TRUE; -} - -PyObject * -psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess) -{ - NTSTATUS status; - PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL; - DWORD dwInfoSize = 0x10000; - DWORD dwRet = 0; - PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL; - DWORD i = 0; - BOOLEAN error = FALSE; - PyObject* pyListFiles = NULL; - PyObject* pyFilePath = NULL; - DWORD dwWait = 0; - - if (g_initialized == FALSE) - psutil_get_open_files_init(TRUE); - - // Due to the use of global variables, ensure only 1 call - // to psutil_get_open_files() is running - EnterCriticalSection(&g_cs); - - if (__NtQuerySystemInformation == NULL || - __NtQueryObject == NULL || - g_hEvtStart == NULL || - g_hEvtFinish == NULL) - - { - PyErr_SetFromWindowsErr(0); - error = TRUE; - goto cleanup; - } - - // Py_BuildValue raises an exception if NULL is returned - pyListFiles = PyList_New(0); - if (pyListFiles == NULL) { - error = TRUE; - goto cleanup; - } - - do { - if (pHandleInfo != NULL) { - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - } - - // NtQuerySystemInformation won't give us the correct buffer size, - // so we guess by doubling the buffer size. - dwInfoSize *= 2; - pHandleInfo = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwInfoSize); - - if (pHandleInfo == NULL) { - PyErr_NoMemory(); - error = TRUE; - goto cleanup; - } - } while ((status = __NtQuerySystemInformation( - SystemExtendedHandleInformation, - pHandleInfo, - dwInfoSize, - &dwRet)) == STATUS_INFO_LENGTH_MISMATCH); - - // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH - if (!NT_SUCCESS(status)) { - PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status)); - error = TRUE; - goto cleanup; - } - - for (i = 0; i < pHandleInfo->NumberOfHandles; i++) { - hHandle = &pHandleInfo->Handles[i]; - - // Check if this hHandle belongs to the PID the user specified. - if (hHandle->UniqueProcessId != (HANDLE)dwPid || - hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE) - goto loop_cleanup; - - if (!DuplicateHandle(hProcess, - hHandle->HandleValue, - GetCurrentProcess(), - &g_hFile, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) - { - /* - printf("[%d] DuplicateHandle (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - // Guess buffer size is MAX_PATH + 1 - g_dwLength = (MAX_PATH+1) * sizeof(WCHAR); - - do { - // Release any previously allocated buffer - if (g_pNameBuffer != NULL) { - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - } - - // NtQueryObject puts the required buffer size in g_dwLength - // WinXP edge case puts g_dwLength == 0, just skip this handle - if (g_dwLength == 0) - goto loop_cleanup; - - g_dwSize = g_dwLength; - if (g_dwSize > 0) { - g_pNameBuffer = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - g_dwSize); - - if (g_pNameBuffer == NULL) - goto loop_cleanup; - } - - dwWait = psutil_NtQueryObject(); - - // If the call does not return, skip this handle - if (dwWait != WAIT_OBJECT_0) - goto loop_cleanup; - - } while (g_status == STATUS_INFO_LENGTH_MISMATCH); - - // NtQueryObject stopped returning STATUS_INFO_LENGTH_MISMATCH - if (!NT_SUCCESS(g_status)) - goto loop_cleanup; - - // Convert to PyUnicode and append it to the return list - if (g_pNameBuffer->Length > 0) { - /* - printf("[%d] Filename (%#x) %#d bytes: %S\n", - dwPid, - hHandle->HandleValue, - g_pNameBuffer->Length, - g_pNameBuffer->Buffer); - */ - - pyFilePath = PyUnicode_FromWideChar(g_pNameBuffer->Buffer, - g_pNameBuffer->Length/2); - if (pyFilePath == NULL) { - /* - printf("[%d] PyUnicode_FromWideChar (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - - if (PyList_Append(pyListFiles, pyFilePath)) { - /* - printf("[%d] PyList_Append (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - } - -loop_cleanup: - Py_XDECREF(pyFilePath); - pyFilePath = NULL; - - if (g_pNameBuffer != NULL) - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - g_dwLength = 0; - - if (g_hFile != NULL) - CloseHandle(g_hFile); - g_hFile = NULL; - } - -cleanup: - if (g_pNameBuffer != NULL) - HeapFree(GetProcessHeap(), 0, g_pNameBuffer); - g_pNameBuffer = NULL; - g_dwSize = 0; - g_dwLength = 0; - - if (g_hFile != NULL) - CloseHandle(g_hFile); - g_hFile = NULL; - - if (pHandleInfo != NULL) - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - - if (error) { - Py_XDECREF(pyListFiles); - pyListFiles = NULL; - } - - LeaveCriticalSection(&g_cs); - - return pyListFiles; -} - -DWORD -psutil_NtQueryObject() -{ - DWORD dwWait = 0; - - if (g_hThread == NULL) - g_hThread = CreateThread(NULL, - 0, - (LPTHREAD_START_ROUTINE)psutil_NtQueryObjectThread, - NULL, - 0, - NULL); - if (g_hThread == NULL) - return GetLastError(); - - // Signal the worker thread to start - SetEvent(g_hEvtStart); - - // Wait for the worker thread to finish - dwWait = WaitForSingleObject(g_hEvtFinish, NTQO_TIMEOUT); - - // If the thread hangs, kill it and cleanup - if (dwWait == WAIT_TIMEOUT) { - SuspendThread(g_hThread); - TerminateThread(g_hThread, 1); - WaitForSingleObject(g_hThread, INFINITE); - CloseHandle(g_hThread); - - // Cleanup Fiber - if (g_fiber != NULL) - DeleteFiber(g_fiber); - g_fiber = NULL; - - g_hThread = NULL; - } - - return dwWait; -} - -void -psutil_NtQueryObjectThread() -{ - // Prevent the thread stack from leaking when this - // thread gets terminated due to NTQueryObject hanging - g_fiber = ConvertThreadToFiber(NULL); - - // Loop infinitely waiting for work - while (TRUE) { - WaitForSingleObject(g_hEvtStart, INFINITE); - - g_status = __NtQueryObject(g_hFile, - ObjectNameInformation, - g_pNameBuffer, - g_dwSize, - &g_dwLength); - SetEvent(g_hEvtFinish); - } -} - -PyObject * -psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess) -{ - NTSTATUS status; - PSYSTEM_HANDLE_INFORMATION_EX pHandleInfo = NULL; - DWORD dwInfoSize = 0x10000; - DWORD dwRet = 0; - PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX hHandle = NULL; - HANDLE hFile = NULL; - HANDLE hMap = NULL; - DWORD i = 0; - BOOLEAN error = FALSE; - PyObject* pyListFiles = NULL; - PyObject* pyFilePath = NULL; - ULONG dwSize = 0; - LPVOID pMem = NULL; - TCHAR pszFilename[MAX_PATH+1]; - - if (g_initialized == FALSE) - psutil_get_open_files_init(FALSE); - - if (__NtQuerySystemInformation == NULL || __NtQueryObject == NULL) { - PyErr_SetFromWindowsErr(0); - error = TRUE; - goto cleanup; - } - - // Py_BuildValue raises an exception if NULL is returned - pyListFiles = PyList_New(0); - if (pyListFiles == NULL) { - error = TRUE; - goto cleanup; - } - - do { - if (pHandleInfo != NULL) { - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - } - - // NtQuerySystemInformation won't give us the correct buffer size, - // so we guess by doubling the buffer size. - dwInfoSize *= 2; - pHandleInfo = HeapAlloc(GetProcessHeap(), - HEAP_ZERO_MEMORY, - dwInfoSize); - - if (pHandleInfo == NULL) { - PyErr_NoMemory(); - error = TRUE; - goto cleanup; - } - } while ((status = __NtQuerySystemInformation( - SystemExtendedHandleInformation, - pHandleInfo, - dwInfoSize, - &dwRet)) == STATUS_INFO_LENGTH_MISMATCH); - - // NtQuerySystemInformation stopped giving us STATUS_INFO_LENGTH_MISMATCH - if (!NT_SUCCESS(status)) { - PyErr_SetFromWindowsErr(HRESULT_FROM_NT(status)); - error = TRUE; - goto cleanup; - } - - for (i = 0; i < pHandleInfo->NumberOfHandles; i++) { - hHandle = &pHandleInfo->Handles[i]; - - // Check if this hHandle belongs to the PID the user specified. - if (hHandle->UniqueProcessId != (HANDLE)dwPid || - hHandle->ObjectTypeIndex != HANDLE_TYPE_FILE) - goto loop_cleanup; - - if (!DuplicateHandle(hProcess, - hHandle->HandleValue, - GetCurrentProcess(), - &hFile, - 0, - TRUE, - DUPLICATE_SAME_ACCESS)) - { - /* - printf("[%d] DuplicateHandle (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - hMap = CreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - if (hMap == NULL) { - /* - printf("[%d] CreateFileMapping (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - pMem = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 1); - - if (pMem == NULL) { - /* - printf("[%d] MapViewOfFile (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - dwSize = GetMappedFileName(GetCurrentProcess(), pMem, pszFilename, MAX_PATH); - if (dwSize == 0) { - /* - printf("[%d] GetMappedFileName (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - goto loop_cleanup; - } - - pszFilename[dwSize] = '\0'; - /* - printf("[%d] Filename (%#x) %#d bytes: %S\n", - dwPid, - hHandle->HandleValue, - dwSize, - pszFilename); - */ - - pyFilePath = PyUnicode_FromWideChar(pszFilename, dwSize); - if (pyFilePath == NULL) { - /* - printf("[%d] PyUnicode_FromStringAndSize (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - - if (PyList_Append(pyListFiles, pyFilePath)) { - /* - printf("[%d] PyList_Append (%#x): %#x \n", - dwPid, - hHandle->HandleValue, - GetLastError()); - */ - error = TRUE; - goto loop_cleanup; - } - -loop_cleanup: - Py_XDECREF(pyFilePath); - pyFilePath = NULL; - - if (pMem != NULL) - UnmapViewOfFile(pMem); - pMem = NULL; - - if (hMap != NULL) - CloseHandle(hMap); - hMap = NULL; - - if (hFile != NULL) - CloseHandle(hFile); - hFile = NULL; - - dwSize = 0; - } - -cleanup: - if (pMem != NULL) - UnmapViewOfFile(pMem); - pMem = NULL; - - if (hMap != NULL) - CloseHandle(hMap); - hMap = NULL; - - if (hFile != NULL) - CloseHandle(hFile); - hFile = NULL; - - if (pHandleInfo != NULL) - HeapFree(GetProcessHeap(), 0, pHandleInfo); - pHandleInfo = NULL; - - if (error) { - Py_XDECREF(pyListFiles); - pyListFiles = NULL; - } - - return pyListFiles; -} diff --git a/python/psutil/psutil/arch/windows/process_handles.h b/python/psutil/psutil/arch/windows/process_handles.h deleted file mode 100644 index 4cf4023ec..000000000 --- a/python/psutil/psutil/arch/windows/process_handles.h +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef __PROCESS_HANDLES_H__ -#define __PROCESS_HANDLES_H__ - -#ifndef UNICODE -#define UNICODE -#endif - -#include <Python.h> -#include <stdio.h> -#include <windows.h> -#include <strsafe.h> -#include <winternl.h> -#include <psapi.h> - - -#ifndef NT_SUCCESS -#define NT_SUCCESS(x) ((x) >= 0) -#endif - -#define STATUS_INFO_LENGTH_MISMATCH 0xc0000004 -#define ObjectBasicInformation 0 -#define ObjectNameInformation 1 -#define ObjectTypeInformation 2 -#define HANDLE_TYPE_FILE 28 -#define NTQO_TIMEOUT 100 - -typedef NTSTATUS (NTAPI *_NtQuerySystemInformation)( - ULONG SystemInformationClass, - PVOID SystemInformation, - ULONG SystemInformationLength, - PULONG ReturnLength -); - -typedef NTSTATUS (NTAPI *_NtQueryObject)( - HANDLE ObjectHandle, - ULONG ObjectInformationClass, - PVOID ObjectInformation, - ULONG ObjectInformationLength, - PULONG ReturnLength -); - -// Undocumented FILE_INFORMATION_CLASS: FileNameInformation -static const SYSTEM_INFORMATION_CLASS SystemExtendedHandleInformation = (SYSTEM_INFORMATION_CLASS)64; - -typedef struct _SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX -{ - PVOID Object; - HANDLE UniqueProcessId; - HANDLE HandleValue; - ULONG GrantedAccess; - USHORT CreatorBackTraceIndex; - USHORT ObjectTypeIndex; - ULONG HandleAttributes; - ULONG Reserved; -} SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX, *PSYSTEM_HANDLE_TABLE_ENTRY_INFO_EX; - -typedef struct _SYSTEM_HANDLE_INFORMATION_EX -{ - ULONG_PTR NumberOfHandles; - ULONG_PTR Reserved; - SYSTEM_HANDLE_TABLE_ENTRY_INFO_EX Handles[1]; -} SYSTEM_HANDLE_INFORMATION_EX, *PSYSTEM_HANDLE_INFORMATION_EX; - -typedef enum _POOL_TYPE { - NonPagedPool, - PagedPool, - NonPagedPoolMustSucceed, - DontUseThisType, - NonPagedPoolCacheAligned, - PagedPoolCacheAligned, - NonPagedPoolCacheAlignedMustS -} POOL_TYPE, *PPOOL_TYPE; - -typedef struct _OBJECT_TYPE_INFORMATION { - UNICODE_STRING Name; - ULONG TotalNumberOfObjects; - ULONG TotalNumberOfHandles; - ULONG TotalPagedPoolUsage; - ULONG TotalNonPagedPoolUsage; - ULONG TotalNamePoolUsage; - ULONG TotalHandleTableUsage; - ULONG HighWaterNumberOfObjects; - ULONG HighWaterNumberOfHandles; - ULONG HighWaterPagedPoolUsage; - ULONG HighWaterNonPagedPoolUsage; - ULONG HighWaterNamePoolUsage; - ULONG HighWaterHandleTableUsage; - ULONG InvalidAttributes; - GENERIC_MAPPING GenericMapping; - ULONG ValidAccess; - BOOLEAN SecurityRequired; - BOOLEAN MaintainHandleCount; - USHORT MaintainTypeList; - POOL_TYPE PoolType; - ULONG PagedPoolUsage; - ULONG NonPagedPoolUsage; -} OBJECT_TYPE_INFORMATION, *POBJECT_TYPE_INFORMATION; - -PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName); -VOID psutil_get_open_files_init(BOOL threaded); -PyObject* psutil_get_open_files(long pid, HANDLE processHandle); -PyObject* psutil_get_open_files_ntqueryobject(long dwPid, HANDLE hProcess); -PyObject* psutil_get_open_files_getmappedfilename(long dwPid, HANDLE hProcess); -DWORD psutil_NtQueryObject(void); -void psutil_NtQueryObjectThread(void); - -#endif // __PROCESS_HANDLES_H__ diff --git a/python/psutil/psutil/arch/windows/process_info.c b/python/psutil/psutil/arch/windows/process_info.c deleted file mode 100644 index a59cce47a..000000000 --- a/python/psutil/psutil/arch/windows/process_info.c +++ /dev/null @@ -1,435 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Helper functions related to fetching process information. Used by - * _psutil_windows module methods. - */ - -#include <Python.h> -#include <windows.h> -#include <Psapi.h> -#include <tlhelp32.h> - -#include "security.h" -#include "process_info.h" -#include "ntextapi.h" -#include "../../_psutil_common.h" - - -/* - * A wrapper around OpenProcess setting NSP exception if process - * no longer exists. - * "pid" is the process pid, "dwDesiredAccess" is the first argument - * exptected by OpenProcess. - * Return a process handle or NULL. - */ -HANDLE -psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess) -{ - HANDLE hProcess; - DWORD processExitCode = 0; - - if (pid == 0) { - // otherwise we'd get NoSuchProcess - return AccessDenied(); - } - - hProcess = OpenProcess(dwDesiredAccess, FALSE, pid); - if (hProcess == NULL) { - if (GetLastError() == ERROR_INVALID_PARAMETER) - NoSuchProcess(); - else - PyErr_SetFromWindowsErr(0); - return NULL; - } - - // make sure the process is running - GetExitCodeProcess(hProcess, &processExitCode); - if (processExitCode == 0) { - NoSuchProcess(); - CloseHandle(hProcess); - return NULL; - } - return hProcess; -} - - -/* - * Same as psutil_handle_from_pid_waccess but implicitly uses - * PROCESS_QUERY_INFORMATION | PROCESS_VM_READ as dwDesiredAccess - * parameter for OpenProcess. - */ -HANDLE -psutil_handle_from_pid(DWORD pid) { - DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ; - return psutil_handle_from_pid_waccess(pid, dwDesiredAccess); -} - - -// fetch the PEB base address from NtQueryInformationProcess() -PVOID -psutil_get_peb_address(HANDLE ProcessHandle) -{ - _NtQueryInformationProcess NtQueryInformationProcess = - (_NtQueryInformationProcess)GetProcAddress( - GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess"); - PROCESS_BASIC_INFORMATION pbi; - - NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL); - return pbi.PebBaseAddress; -} - - -DWORD * -psutil_get_pids(DWORD *numberOfReturnedPIDs) { - // Win32 SDK says the only way to know if our process array - // wasn't large enough is to check the returned size and make - // sure that it doesn't match the size of the array. - // If it does we allocate a larger array and try again - - // Stores the actual array - DWORD *procArray = NULL; - DWORD procArrayByteSz; - int procArraySz = 0; - - // Stores the byte size of the returned array from enumprocesses - DWORD enumReturnSz = 0; - - do { - procArraySz += 1024; - free(procArray); - procArrayByteSz = procArraySz * sizeof(DWORD); - procArray = malloc(procArrayByteSz); - if (procArray == NULL) { - PyErr_NoMemory(); - return NULL; - } - if (! EnumProcesses(procArray, procArrayByteSz, &enumReturnSz)) { - free(procArray); - PyErr_SetFromWindowsErr(0); - return NULL; - } - } while (enumReturnSz == procArraySz * sizeof(DWORD)); - - // The number of elements is the returned size / size of each element - *numberOfReturnedPIDs = enumReturnSz / sizeof(DWORD); - - return procArray; -} - - -int -psutil_pid_is_running(DWORD pid) -{ - HANDLE hProcess; - DWORD exitCode; - - // Special case for PID 0 System Idle Process - if (pid == 0) - return 1; - if (pid < 0) - return 0; - - hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, - FALSE, pid); - if (NULL == hProcess) { - // invalid parameter is no such process - if (GetLastError() == ERROR_INVALID_PARAMETER) { - CloseHandle(hProcess); - return 0; - } - - // access denied obviously means there's a process to deny access to... - if (GetLastError() == ERROR_ACCESS_DENIED) { - CloseHandle(hProcess); - return 1; - } - - CloseHandle(hProcess); - PyErr_SetFromWindowsErr(0); - return -1; - } - - if (GetExitCodeProcess(hProcess, &exitCode)) { - CloseHandle(hProcess); - return (exitCode == STILL_ACTIVE); - } - - // access denied means there's a process there so we'll assume - // it's running - if (GetLastError() == ERROR_ACCESS_DENIED) { - CloseHandle(hProcess); - return 1; - } - - PyErr_SetFromWindowsErr(0); - CloseHandle(hProcess); - return -1; -} - - -int -psutil_pid_in_proclist(DWORD pid) -{ - DWORD *proclist = NULL; - DWORD numberOfReturnedPIDs; - DWORD i; - - proclist = psutil_get_pids(&numberOfReturnedPIDs); - if (proclist == NULL) - return -1; - for (i = 0; i < numberOfReturnedPIDs; i++) { - if (pid == proclist[i]) { - free(proclist); - return 1; - } - } - - free(proclist); - return 0; -} - - -// Check exit code from a process handle. Return FALSE on an error also -// XXX - not used anymore -int -handlep_is_running(HANDLE hProcess) -{ - DWORD dwCode; - - if (NULL == hProcess) - return 0; - if (GetExitCodeProcess(hProcess, &dwCode)) { - if (dwCode == STILL_ACTIVE) - return 1; - } - return 0; -} - - -/* - * returns a Python list representing the arguments for the process - * with given pid or NULL on error. - */ -PyObject * -psutil_get_arg_list(long pid) -{ - int nArgs, i; - LPWSTR *szArglist = NULL; - HANDLE hProcess = NULL; - PVOID pebAddress; - PVOID rtlUserProcParamsAddress; - UNICODE_STRING commandLine; - WCHAR *commandLineContents = NULL; - PyObject *arg = NULL; - PyObject *arg_from_wchar = NULL; - PyObject *argList = NULL; - - hProcess = psutil_handle_from_pid(pid); - if (hProcess == NULL) - return NULL; - pebAddress = psutil_get_peb_address(hProcess); - - // get the address of ProcessParameters -#ifdef _WIN64 - if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 32, - &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) -#else - if (!ReadProcessMemory(hProcess, (PCHAR)pebAddress + 0x10, - &rtlUserProcParamsAddress, sizeof(PVOID), NULL)) -#endif - { - ////printf("Could not read the address of ProcessParameters!\n"); - PyErr_SetFromWindowsErr(0); - goto error; - } - - // read the CommandLine UNICODE_STRING structure -#ifdef _WIN64 - if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 112, - &commandLine, sizeof(commandLine), NULL)) -#else - if (!ReadProcessMemory(hProcess, (PCHAR)rtlUserProcParamsAddress + 0x40, - &commandLine, sizeof(commandLine), NULL)) -#endif - { - PyErr_SetFromWindowsErr(0); - goto error; - } - - - // allocate memory to hold the command line - commandLineContents = (WCHAR *)malloc(commandLine.Length + 1); - if (commandLineContents == NULL) { - PyErr_NoMemory(); - goto error; - } - - // read the command line - if (!ReadProcessMemory(hProcess, commandLine.Buffer, - commandLineContents, commandLine.Length, NULL)) - { - PyErr_SetFromWindowsErr(0); - goto error; - } - - // Null-terminate the string to prevent wcslen from returning - // incorrect length the length specifier is in characters, but - // commandLine.Length is in bytes. - commandLineContents[(commandLine.Length / sizeof(WCHAR))] = '\0'; - - // attempt tp parse the command line using Win32 API, fall back - // on string cmdline version otherwise - szArglist = CommandLineToArgvW(commandLineContents, &nArgs); - if (NULL == szArglist) { - // failed to parse arglist - // encode as a UTF8 Python string object from WCHAR string - arg_from_wchar = PyUnicode_FromWideChar(commandLineContents, - commandLine.Length / 2); - if (arg_from_wchar == NULL) - goto error; -#if PY_MAJOR_VERSION >= 3 - argList = Py_BuildValue("N", PyUnicode_AsUTF8String(arg_from_wchar)); -#else - argList = Py_BuildValue("N", PyUnicode_FromObject(arg_from_wchar)); -#endif - if (!argList) - goto error; - } - else { - // arglist parsed as array of UNICODE_STRING, so convert each to - // Python string object and add to arg list - argList = Py_BuildValue("[]"); - if (argList == NULL) - goto error; - for (i = 0; i < nArgs; i++) { - arg_from_wchar = NULL; - arg = NULL; - arg_from_wchar = PyUnicode_FromWideChar(szArglist[i], - wcslen(szArglist[i])); - if (arg_from_wchar == NULL) - goto error; -#if PY_MAJOR_VERSION >= 3 - arg = PyUnicode_FromObject(arg_from_wchar); -#else - arg = PyUnicode_AsUTF8String(arg_from_wchar); -#endif - if (arg == NULL) - goto error; - Py_XDECREF(arg_from_wchar); - if (PyList_Append(argList, arg)) - goto error; - Py_XDECREF(arg); - } - } - - if (szArglist != NULL) - LocalFree(szArglist); - free(commandLineContents); - CloseHandle(hProcess); - return argList; - -error: - Py_XDECREF(arg); - Py_XDECREF(arg_from_wchar); - Py_XDECREF(argList); - if (hProcess != NULL) - CloseHandle(hProcess); - if (commandLineContents != NULL) - free(commandLineContents); - if (szArglist != NULL) - LocalFree(szArglist); - return NULL; -} - - -#define PH_FIRST_PROCESS(Processes) ((PSYSTEM_PROCESS_INFORMATION)(Processes)) -#define PH_NEXT_PROCESS(Process) ( \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset ? \ - (PSYSTEM_PROCESS_INFORMATION)((PCHAR)(Process) + \ - ((PSYSTEM_PROCESS_INFORMATION)(Process))->NextEntryOffset) : \ - NULL) - -const int STATUS_INFO_LENGTH_MISMATCH = 0xC0000004; -const int STATUS_BUFFER_TOO_SMALL = 0xC0000023L; - -/* - * Given a process PID and a PSYSTEM_PROCESS_INFORMATION structure - * fills the structure with various process information by using - * NtQuerySystemInformation. - * We use this as a fallback when faster functions fail with access - * denied. This is slower because it iterates over all processes. - * On success return 1, else 0 with Python exception already set. - */ -int -psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer) -{ - static ULONG initialBufferSize = 0x4000; - NTSTATUS status; - PVOID buffer; - ULONG bufferSize; - PSYSTEM_PROCESS_INFORMATION process; - - // get NtQuerySystemInformation - typedef DWORD (_stdcall * NTQSI_PROC) (int, PVOID, ULONG, PULONG); - NTQSI_PROC NtQuerySystemInformation; - HINSTANCE hNtDll; - hNtDll = LoadLibrary(TEXT("ntdll.dll")); - NtQuerySystemInformation = (NTQSI_PROC)GetProcAddress( - hNtDll, "NtQuerySystemInformation"); - - bufferSize = initialBufferSize; - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - - while (TRUE) { - status = NtQuerySystemInformation(SystemProcessInformation, buffer, - bufferSize, &bufferSize); - - if (status == STATUS_BUFFER_TOO_SMALL || - status == STATUS_INFO_LENGTH_MISMATCH) - { - free(buffer); - buffer = malloc(bufferSize); - if (buffer == NULL) { - PyErr_NoMemory(); - goto error; - } - } - else { - break; - } - } - - if (status != 0) { - PyErr_Format(PyExc_RuntimeError, "NtQuerySystemInformation() failed"); - goto error; - } - - if (bufferSize <= 0x20000) - initialBufferSize = bufferSize; - - process = PH_FIRST_PROCESS(buffer); - do { - if (process->UniqueProcessId == (HANDLE)pid) { - *retProcess = process; - *retBuffer = buffer; - return 1; - } - } while ( (process = PH_NEXT_PROCESS(process)) ); - - NoSuchProcess(); - goto error; - -error: - FreeLibrary(hNtDll); - if (buffer != NULL) - free(buffer); - return 0; -} diff --git a/python/psutil/psutil/arch/windows/process_info.h b/python/psutil/psutil/arch/windows/process_info.h deleted file mode 100644 index a44c4aced..000000000 --- a/python/psutil/psutil/arch/windows/process_info.h +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#if !defined(__PROCESS_INFO_H) -#define __PROCESS_INFO_H - -#include <Python.h> -#include <windows.h> -#include "security.h" -#include "ntextapi.h" - -DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs); -HANDLE psutil_handle_from_pid(DWORD pid); -HANDLE psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess); -int psutil_handlep_is_running(HANDLE hProcess); -int psutil_pid_in_proclist(DWORD pid); -int psutil_pid_is_running(DWORD pid); -PVOID psutil_get_peb_address(HANDLE ProcessHandle); -PyObject* psutil_get_arg_list(long pid); -int psutil_get_proc_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, - PVOID *retBuffer); - -#endif diff --git a/python/psutil/psutil/arch/windows/security.c b/python/psutil/psutil/arch/windows/security.c deleted file mode 100644 index 3aabffd0c..000000000 --- a/python/psutil/psutil/arch/windows/security.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Security related functions for Windows platform (Set privileges such as - * SeDebug), as well as security helper functions. - */ - -#include <windows.h> -#include <Python.h> - - -/* - * Convert a process handle to a process token handle. - */ -HANDLE -psutil_token_from_handle(HANDLE hProcess) { - HANDLE hToken = NULL; - - if (! OpenProcessToken(hProcess, TOKEN_QUERY, &hToken)) - return PyErr_SetFromWindowsErr(0); - return hToken; -} - - -/* - * http://www.ddj.com/windows/184405986 - * - * There's a way to determine whether we're running under the Local System - * account. However (you guessed it), we have to call more Win32 functions to - * determine this. Backing up through the code listing, we need to make another - * call to GetTokenInformation, but instead of passing through the TOKEN_USER - * constant, we pass through the TOKEN_PRIVILEGES constant. This value returns - * an array of privileges that the account has in the environment. Iterating - * through the array, we call the function LookupPrivilegeName looking for the - * string SeTcbPrivilege. If the function returns this string, then this - * account has Local System privileges - */ -int -psutil_has_system_privilege(HANDLE hProcess) { - DWORD i; - DWORD dwSize = 0; - DWORD dwRetval = 0; - TCHAR privName[256]; - DWORD dwNameSize = 256; - // PTOKEN_PRIVILEGES tp = NULL; - BYTE *pBuffer = NULL; - TOKEN_PRIVILEGES *tp = NULL; - HANDLE hToken = psutil_token_from_handle(hProcess); - - if (NULL == hToken) - return -1; - // call GetTokenInformation first to get the buffer size - if (! GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &dwSize)) { - dwRetval = GetLastError(); - // if it failed for a reason other than the buffer, bail out - if (dwRetval != ERROR_INSUFFICIENT_BUFFER ) { - PyErr_SetFromWindowsErr(dwRetval); - return 0; - } - } - - // allocate buffer and call GetTokenInformation again - // tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize); - pBuffer = (BYTE *) malloc(dwSize); - if (pBuffer == NULL) { - PyErr_NoMemory(); - return -1; - } - - if (! GetTokenInformation(hToken, TokenPrivileges, pBuffer, - dwSize, &dwSize)) - { - PyErr_SetFromWindowsErr(0); - free(pBuffer); - return -1; - } - - // convert the BYTE buffer to a TOKEN_PRIVILEGES struct pointer - tp = (TOKEN_PRIVILEGES *)pBuffer; - - // check all the privileges looking for SeTcbPrivilege - for (i = 0; i < tp->PrivilegeCount; i++) { - // reset the buffer contents and the buffer size - strcpy(privName, ""); - dwNameSize = sizeof(privName) / sizeof(TCHAR); - if (! LookupPrivilegeName(NULL, - &tp->Privileges[i].Luid, - (LPTSTR)privName, - &dwNameSize)) - { - PyErr_SetFromWindowsErr(0); - free(pBuffer); - return -1; - } - - // if we find the SeTcbPrivilege then it's a LocalSystem process - if (! lstrcmpi(privName, TEXT("SeTcbPrivilege"))) { - free(pBuffer); - return 1; - } - } - - free(pBuffer); - return 0; -} - - -BOOL -psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege) -{ - TOKEN_PRIVILEGES tp; - LUID luid; - TOKEN_PRIVILEGES tpPrevious; - DWORD cbPrevious = sizeof(TOKEN_PRIVILEGES); - - if (!LookupPrivilegeValue( NULL, Privilege, &luid )) return FALSE; - - // first pass. get current privilege setting - tp.PrivilegeCount = 1; - tp.Privileges[0].Luid = luid; - tp.Privileges[0].Attributes = 0; - - AdjustTokenPrivileges( - hToken, - FALSE, - &tp, - sizeof(TOKEN_PRIVILEGES), - &tpPrevious, - &cbPrevious - ); - - if (GetLastError() != ERROR_SUCCESS) return FALSE; - - // second pass. set privilege based on previous setting - tpPrevious.PrivilegeCount = 1; - tpPrevious.Privileges[0].Luid = luid; - - if (bEnablePrivilege) - tpPrevious.Privileges[0].Attributes |= (SE_PRIVILEGE_ENABLED); - else - tpPrevious.Privileges[0].Attributes ^= - (SE_PRIVILEGE_ENABLED & tpPrevious.Privileges[0].Attributes); - - AdjustTokenPrivileges( - hToken, - FALSE, - &tpPrevious, - cbPrevious, - NULL, - NULL - ); - - if (GetLastError() != ERROR_SUCCESS) return FALSE; - - return TRUE; -} - - -int -psutil_set_se_debug() -{ - HANDLE hToken; - if (! OpenThreadToken(GetCurrentThread(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - FALSE, - &hToken) - ) { - if (GetLastError() == ERROR_NO_TOKEN) { - if (!ImpersonateSelf(SecurityImpersonation)) { - CloseHandle(hToken); - return 0; - } - if (!OpenThreadToken(GetCurrentThread(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - FALSE, - &hToken) - ) { - RevertToSelf(); - CloseHandle(hToken); - return 0; - } - } - } - - // enable SeDebugPrivilege (open any process) - if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, TRUE)) { - RevertToSelf(); - CloseHandle(hToken); - return 0; - } - - RevertToSelf(); - CloseHandle(hToken); - return 1; -} - - -int -psutil_unset_se_debug() -{ - HANDLE hToken; - if (! OpenThreadToken(GetCurrentThread(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - FALSE, - &hToken) - ) { - if (GetLastError() == ERROR_NO_TOKEN) { - if (! ImpersonateSelf(SecurityImpersonation)) - return 0; - if (!OpenThreadToken(GetCurrentThread(), - TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, - FALSE, - &hToken)) - { - return 0; - } - } - } - - // now disable SeDebug - if (! psutil_set_privilege(hToken, SE_DEBUG_NAME, FALSE)) - return 0; - - CloseHandle(hToken); - return 1; -} diff --git a/python/psutil/psutil/arch/windows/security.h b/python/psutil/psutil/arch/windows/security.h deleted file mode 100644 index aa8a22ad1..000000000 --- a/python/psutil/psutil/arch/windows/security.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2009, Jay Loden, Giampaolo Rodola'. All rights reserved. - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - * - * Security related functions for Windows platform (Set privileges such as - * SeDebug), as well as security helper functions. - */ - -#include <windows.h> - -BOOL psutil_set_privilege(HANDLE hToken, LPCTSTR Privilege, BOOL bEnablePrivilege); -HANDLE psutil_token_from_handle(HANDLE hProcess); -int psutil_has_system_privilege(HANDLE hProcess); -int psutil_set_se_debug(); -int psutil_unset_se_debug(); - diff --git a/python/psutil/setup.cfg b/python/psutil/setup.cfg deleted file mode 100644 index 861a9f554..000000000 --- a/python/psutil/setup.cfg +++ /dev/null @@ -1,5 +0,0 @@ -[egg_info] -tag_build = -tag_date = 0 -tag_svn_revision = 0 - diff --git a/python/psutil/setup.py b/python/psutil/setup.py deleted file mode 100644 index 4c42548ef..000000000 --- a/python/psutil/setup.py +++ /dev/null @@ -1,206 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""psutil is a cross-platform library for retrieving information on -running processes and system utilization (CPU, memory, disks, network) -in Python. -""" - -import os -import sys -try: - from setuptools import setup, Extension -except ImportError: - from distutils.core import setup, Extension - - -HERE = os.path.abspath(os.path.dirname(__file__)) - - -def get_version(): - INIT = os.path.join(HERE, 'psutil/__init__.py') - with open(INIT, 'r') as f: - for line in f: - if line.startswith('__version__'): - ret = eval(line.strip().split(' = ')[1]) - assert ret.count('.') == 2, ret - for num in ret.split('.'): - assert num.isdigit(), ret - return ret - else: - raise ValueError("couldn't find version string") - - -def get_description(): - README = os.path.join(HERE, 'README.rst') - with open(README, 'r') as f: - return f.read() - - -VERSION = get_version() -VERSION_MACRO = ('PSUTIL_VERSION', int(VERSION.replace('.', ''))) - - -# POSIX -if os.name == 'posix': - libraries = [] - if sys.platform.startswith("sunos"): - libraries.append('socket') - - posix_extension = Extension( - 'psutil._psutil_posix', - sources=['psutil/_psutil_posix.c'], - libraries=libraries, - ) -# Windows -if sys.platform.startswith("win32"): - - def get_winver(): - maj, min = sys.getwindowsversion()[0:2] - return '0x0%s' % ((maj * 100) + min) - - extensions = [Extension( - 'psutil._psutil_windows', - sources=[ - 'psutil/_psutil_windows.c', - 'psutil/_psutil_common.c', - 'psutil/arch/windows/process_info.c', - 'psutil/arch/windows/process_handles.c', - 'psutil/arch/windows/security.c', - 'psutil/arch/windows/inet_ntop.c', - ], - define_macros=[ - VERSION_MACRO, - # be nice to mingw, see: - # http://www.mingw.org/wiki/Use_more_recent_defined_functions - ('_WIN32_WINNT', get_winver()), - ('_AVAIL_WINVER_', get_winver()), - ('_CRT_SECURE_NO_WARNINGS', None), - # see: https://github.com/giampaolo/psutil/issues/348 - ('PSAPI_VERSION', 1), - ], - libraries=[ - "psapi", "kernel32", "advapi32", "shell32", "netapi32", "iphlpapi", - "wtsapi32", "ws2_32", - ], - # extra_compile_args=["/Z7"], - # extra_link_args=["/DEBUG"] - )] -# OS X -elif sys.platform.startswith("darwin"): - extensions = [Extension( - 'psutil._psutil_osx', - sources=[ - 'psutil/_psutil_osx.c', - 'psutil/_psutil_common.c', - 'psutil/arch/osx/process_info.c' - ], - define_macros=[VERSION_MACRO], - extra_link_args=[ - '-framework', 'CoreFoundation', '-framework', 'IOKit' - ], - ), - posix_extension, - ] -# FreeBSD -elif sys.platform.startswith("freebsd"): - extensions = [Extension( - 'psutil._psutil_bsd', - sources=[ - 'psutil/_psutil_bsd.c', - 'psutil/_psutil_common.c', - 'psutil/arch/bsd/process_info.c' - ], - define_macros=[VERSION_MACRO], - libraries=["devstat"]), - posix_extension, - ] -# Linux -elif sys.platform.startswith("linux"): - extensions = [Extension( - 'psutil._psutil_linux', - sources=['psutil/_psutil_linux.c'], - define_macros=[VERSION_MACRO]), - posix_extension, - ] -# Solaris -elif sys.platform.lower().startswith('sunos'): - extensions = [Extension( - 'psutil._psutil_sunos', - sources=['psutil/_psutil_sunos.c'], - define_macros=[VERSION_MACRO], - libraries=['kstat', 'nsl', 'socket']), - posix_extension, - ] -else: - sys.exit('platform %s is not supported' % sys.platform) - - -def main(): - setup_args = dict( - name='psutil', - version=VERSION, - description=__doc__.replace('\n', '').strip(), - long_description=get_description(), - keywords=[ - 'ps', 'top', 'kill', 'free', 'lsof', 'netstat', 'nice', 'tty', - 'ionice', 'uptime', 'taskmgr', 'process', 'df', 'iotop', 'iostat', - 'ifconfig', 'taskset', 'who', 'pidof', 'pmap', 'smem', 'pstree', - 'monitoring', 'ulimit', 'prlimit', - ], - author='Giampaolo Rodola', - author_email='g.rodola <at> gmail <dot> com', - url='https://github.com/giampaolo/psutil', - platforms='Platform Independent', - license='BSD', - packages=['psutil'], - # see: python setup.py register --list-classifiers - classifiers=[ - 'Development Status :: 5 - Production/Stable', - 'Environment :: Console', - 'Environment :: Win32 (MS Windows)', - 'Intended Audience :: Developers', - 'Intended Audience :: Information Technology', - 'Intended Audience :: System Administrators', - 'License :: OSI Approved :: BSD License', - 'Operating System :: MacOS :: MacOS X', - 'Operating System :: Microsoft :: Windows :: Windows NT/2000', - 'Operating System :: Microsoft', - 'Operating System :: OS Independent', - 'Operating System :: POSIX :: BSD :: FreeBSD', - 'Operating System :: POSIX :: Linux', - 'Operating System :: POSIX :: SunOS/Solaris', - 'Operating System :: POSIX', - 'Programming Language :: C', - 'Programming Language :: Python :: 2', - 'Programming Language :: Python :: 2.6', - 'Programming Language :: Python :: 2.7', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.0', - 'Programming Language :: Python :: 3.1', - 'Programming Language :: Python :: 3.2', - 'Programming Language :: Python :: 3.3', - 'Programming Language :: Python :: 3.4', - 'Programming Language :: Python :: Implementation :: CPython', - 'Programming Language :: Python :: Implementation :: PyPy', - 'Programming Language :: Python', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: Software Development :: Libraries', - 'Topic :: System :: Benchmark', - 'Topic :: System :: Hardware', - 'Topic :: System :: Monitoring', - 'Topic :: System :: Networking :: Monitoring', - 'Topic :: System :: Networking', - 'Topic :: System :: Systems Administration', - 'Topic :: Utilities', - ], - ) - if extensions is not None: - setup_args["ext_modules"] = extensions - setup(**setup_args) - -if __name__ == '__main__': - main() diff --git a/python/psutil/test/README.rst b/python/psutil/test/README.rst deleted file mode 100644 index 3f2a468ef..000000000 --- a/python/psutil/test/README.rst +++ /dev/null @@ -1,21 +0,0 @@ -- The recommended way to run tests (also on Windows) is to cd into parent - directory and run ``make test`` - -- Dependencies for running tests: - - python 2.6: ipaddress, mock, unittest2 - - python 2.7: ipaddress, mock - - python 3.2: ipaddress, mock - - python 3.3: ipaddress - - python >= 3.4: no deps required - -- The main test script is ``test_psutil.py``, which also imports platform-specific - ``_*.py`` scripts (which should be ignored). - -- ``test_memory_leaks.py`` looks for memory leaks into C extension modules and must - be run separately with ``make test-memleaks``. - -- To run tests on all supported Python version install tox (pip install tox) - then run ``tox``. - -- Every time a commit is pushed tests are automatically run on Travis: - https://travis-ci.org/giampaolo/psutil/ diff --git a/python/psutil/test/_bsd.py b/python/psutil/test/_bsd.py deleted file mode 100644 index e4a3225d2..000000000 --- a/python/psutil/test/_bsd.py +++ /dev/null @@ -1,252 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -# TODO: add test for comparing connections with 'sockstat' cmd - -"""BSD specific tests. These are implicitly run by test_psutil.py.""" - -import os -import subprocess -import sys -import time - -import psutil - -from psutil._compat import PY3 -from test_psutil import (TOLERANCE, BSD, sh, get_test_subprocess, which, - retry_before_failing, reap_children, unittest) - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") -if os.getuid() == 0: # muse requires root privileges - MUSE_AVAILABLE = which('muse') -else: - MUSE_AVAILABLE = False - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - result = sh("sysctl " + cmdline) - result = result[result.find(": ") + 2:] - try: - return int(result) - except ValueError: - return result - - -def muse(field): - """Thin wrapper around 'muse' cmdline utility.""" - out = sh('muse') - for line in out.split('\n'): - if line.startswith(field): - break - else: - raise ValueError("line not found") - return int(line.split()[1]) - - -@unittest.skipUnless(BSD, "not a BSD system") -class BSDSpecificTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_boot_time(self): - s = sysctl('sysctl kern.boottime') - s = s[s.find(" sec = ") + 7:] - s = s[:s.find(',')] - btime = int(s) - self.assertEqual(btime, psutil.boot_time()) - - def test_process_create_time(self): - cmdline = "ps -o lstart -p %s" % self.pid - p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) - output = p.communicate()[0] - if PY3: - output = str(output, sys.stdout.encoding) - start_ps = output.replace('STARTED', '').strip() - start_psutil = psutil.Process(self.pid).create_time() - start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", - time.localtime(start_psutil)) - self.assertEqual(start_ps, start_psutil) - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - @retry_before_failing() - def test_memory_maps(self): - out = sh('procstat -v %s' % self.pid) - maps = psutil.Process(self.pid).memory_maps(grouped=False) - lines = out.split('\n')[1:] - while lines: - line = lines.pop() - fields = line.split() - _, start, stop, perms, res = fields[:5] - map = maps.pop() - self.assertEqual("%s-%s" % (start, stop), map.addr) - self.assertEqual(int(res), map.rss) - if not map.path.startswith('['): - self.assertEqual(fields[10], map.path) - - def test_exe(self): - out = sh('procstat -b %s' % self.pid) - self.assertEqual(psutil.Process(self.pid).exe(), - out.split('\n')[1].split()[-1]) - - def test_cmdline(self): - out = sh('procstat -c %s' % self.pid) - self.assertEqual(' '.join(psutil.Process(self.pid).cmdline()), - ' '.join(out.split('\n')[1].split()[2:])) - - def test_uids_gids(self): - out = sh('procstat -s %s' % self.pid) - euid, ruid, suid, egid, rgid, sgid = out.split('\n')[1].split()[2:8] - p = psutil.Process(self.pid) - uids = p.uids() - gids = p.gids() - self.assertEqual(uids.real, int(ruid)) - self.assertEqual(uids.effective, int(euid)) - self.assertEqual(uids.saved, int(suid)) - self.assertEqual(gids.real, int(rgid)) - self.assertEqual(gids.effective, int(egid)) - self.assertEqual(gids.saved, int(sgid)) - - # --- virtual_memory(); tests against sysctl - - def test_vmem_total(self): - syst = sysctl("sysctl vm.stats.vm.v_page_count") * PAGESIZE - self.assertEqual(psutil.virtual_memory().total, syst) - - @retry_before_failing() - def test_vmem_active(self): - syst = sysctl("vm.stats.vm.v_active_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().active, syst, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_inactive(self): - syst = sysctl("vm.stats.vm.v_inactive_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().inactive, syst, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_wired(self): - syst = sysctl("vm.stats.vm.v_wire_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().wired, syst, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_cached(self): - syst = sysctl("vm.stats.vm.v_cache_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().cached, syst, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_free(self): - syst = sysctl("vm.stats.vm.v_free_count") * PAGESIZE - self.assertAlmostEqual(psutil.virtual_memory().free, syst, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_buffers(self): - syst = sysctl("vfs.bufspace") - self.assertAlmostEqual(psutil.virtual_memory().buffers, syst, - delta=TOLERANCE) - - def test_cpu_count_logical(self): - syst = sysctl("hw.ncpu") - self.assertEqual(psutil.cpu_count(logical=True), syst) - - # --- virtual_memory(); tests against muse - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - def test_total(self): - num = muse('Total') - self.assertEqual(psutil.virtual_memory().total, num) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_active(self): - num = muse('Active') - self.assertAlmostEqual(psutil.virtual_memory().active, num, - delta=TOLERANCE) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_inactive(self): - num = muse('Inactive') - self.assertAlmostEqual(psutil.virtual_memory().inactive, num, - delta=TOLERANCE) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_wired(self): - num = muse('Wired') - self.assertAlmostEqual(psutil.virtual_memory().wired, num, - delta=TOLERANCE) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_cached(self): - num = muse('Cache') - self.assertAlmostEqual(psutil.virtual_memory().cached, num, - delta=TOLERANCE) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_free(self): - num = muse('Free') - self.assertAlmostEqual(psutil.virtual_memory().free, num, - delta=TOLERANCE) - - @unittest.skipUnless(MUSE_AVAILABLE, "muse cmdline tool is not available") - @retry_before_failing() - def test_buffers(self): - num = muse('Buffer') - self.assertAlmostEqual(psutil.virtual_memory().buffers, num, - delta=TOLERANCE) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(BSDSpecificTestCase)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/_linux.py b/python/psutil/test/_linux.py deleted file mode 100644 index c1927ea8b..000000000 --- a/python/psutil/test/_linux.py +++ /dev/null @@ -1,473 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Linux specific tests. These are implicitly run by test_psutil.py.""" - -from __future__ import division -import contextlib -import errno -import fcntl -import io -import os -import pprint -import re -import socket -import struct -import sys -import tempfile -import time -import warnings - -try: - from unittest import mock # py3 -except ImportError: - import mock # requires "pip install mock" - -from test_psutil import POSIX, TOLERANCE, TRAVIS, LINUX -from test_psutil import (skip_on_not_implemented, sh, get_test_subprocess, - retry_before_failing, get_kernel_version, unittest, - which, call_until) - -import psutil -import psutil._pslinux -from psutil._compat import PY3, u - - -SIOCGIFADDR = 0x8915 -SIOCGIFCONF = 0x8912 -SIOCGIFHWADDR = 0x8927 - - -def get_ipv4_address(ifname): - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - return socket.inet_ntoa( - fcntl.ioctl(s.fileno(), - SIOCGIFADDR, - struct.pack('256s', ifname))[20:24]) - - -def get_mac_address(ifname): - ifname = ifname[:15] - if PY3: - ifname = bytes(ifname, 'ascii') - s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) - with contextlib.closing(s): - info = fcntl.ioctl( - s.fileno(), SIOCGIFHWADDR, struct.pack('256s', ifname)) - if PY3: - def ord(x): - return x - else: - import __builtin__ - ord = __builtin__.ord - return ''.join(['%02x:' % ord(char) for char in info[18:24]])[:-1] - - -@unittest.skipUnless(LINUX, "not a Linux system") -class LinuxSpecificTestCase(unittest.TestCase): - - @unittest.skipIf( - POSIX and not hasattr(os, 'statvfs'), - reason="os.statvfs() function not available on this platform") - @skip_on_not_implemented() - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -P -B 1 "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total, used, free = int(total), int(used), int(free) - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.free, free)) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % (usage.used, used)) - - def test_memory_maps(self): - sproc = get_test_subprocess() - time.sleep(1) - p = psutil.Process(sproc.pid) - maps = p.memory_maps(grouped=False) - pmap = sh('pmap -x %s' % p.pid).split('\n') - # get rid of header - del pmap[0] - del pmap[0] - while maps and pmap: - this = maps.pop(0) - other = pmap.pop(0) - addr, _, rss, dirty, mode, path = other.split(None, 5) - if not path.startswith('[') and not path.endswith(']'): - self.assertEqual(path, os.path.basename(this.path)) - self.assertEqual(int(rss) * 1024, this.rss) - # test only rwx chars, ignore 's' and 'p' - self.assertEqual(mode[:3], this.perms[:3]) - - def test_vmem_total(self): - lines = sh('free').split('\n')[1:] - total = int(lines[0].split()[1]) * 1024 - self.assertEqual(total, psutil.virtual_memory().total) - - @retry_before_failing() - def test_vmem_used(self): - lines = sh('free').split('\n')[1:] - used = int(lines[0].split()[2]) * 1024 - self.assertAlmostEqual(used, psutil.virtual_memory().used, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_free(self): - lines = sh('free').split('\n')[1:] - free = int(lines[0].split()[3]) * 1024 - self.assertAlmostEqual(free, psutil.virtual_memory().free, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_buffers(self): - lines = sh('free').split('\n')[1:] - buffers = int(lines[0].split()[5]) * 1024 - self.assertAlmostEqual(buffers, psutil.virtual_memory().buffers, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_cached(self): - lines = sh('free').split('\n')[1:] - cached = int(lines[0].split()[6]) * 1024 - self.assertAlmostEqual(cached, psutil.virtual_memory().cached, - delta=TOLERANCE) - - def test_swapmem_total(self): - lines = sh('free').split('\n')[1:] - total = int(lines[2].split()[1]) * 1024 - self.assertEqual(total, psutil.swap_memory().total) - - @retry_before_failing() - def test_swapmem_used(self): - lines = sh('free').split('\n')[1:] - used = int(lines[2].split()[2]) * 1024 - self.assertAlmostEqual(used, psutil.swap_memory().used, - delta=TOLERANCE) - - @retry_before_failing() - def test_swapmem_free(self): - lines = sh('free').split('\n')[1:] - free = int(lines[2].split()[3]) * 1024 - self.assertAlmostEqual(free, psutil.swap_memory().free, - delta=TOLERANCE) - - @unittest.skipIf(TRAVIS, "unknown failure on travis") - def test_cpu_times(self): - fields = psutil.cpu_times()._fields - kernel_ver = re.findall('\d+\.\d+\.\d+', os.uname()[2])[0] - kernel_ver_info = tuple(map(int, kernel_ver.split('.'))) - if kernel_ver_info >= (2, 6, 11): - self.assertIn('steal', fields) - else: - self.assertNotIn('steal', fields) - if kernel_ver_info >= (2, 6, 24): - self.assertIn('guest', fields) - else: - self.assertNotIn('guest', fields) - if kernel_ver_info >= (3, 2, 0): - self.assertIn('guest_nice', fields) - else: - self.assertNotIn('guest_nice', fields) - - def test_net_if_addrs_ips(self): - for name, addrs in psutil.net_if_addrs().items(): - for addr in addrs: - if addr.family == psutil.AF_LINK: - self.assertEqual(addr.address, get_mac_address(name)) - elif addr.family == socket.AF_INET: - self.assertEqual(addr.address, get_ipv4_address(name)) - # TODO: test for AF_INET6 family - - @unittest.skipUnless(which('ip'), "'ip' utility not available") - @unittest.skipIf(TRAVIS, "skipped on Travis") - def test_net_if_names(self): - out = sh("ip addr").strip() - nics = psutil.net_if_addrs() - found = 0 - for line in out.split('\n'): - line = line.strip() - if re.search("^\d+:", line): - found += 1 - name = line.split(':')[1].strip() - self.assertIn(name, nics.keys()) - self.assertEqual(len(nics), found, msg="%s\n---\n%s" % ( - pprint.pformat(nics), out)) - - @unittest.skipUnless(which("nproc"), "nproc utility not available") - def test_cpu_count_logical_w_nproc(self): - num = int(sh("nproc --all")) - self.assertEqual(psutil.cpu_count(logical=True), num) - - @unittest.skipUnless(which("lscpu"), "lscpu utility not available") - def test_cpu_count_logical_w_lscpu(self): - out = sh("lscpu -p") - num = len([x for x in out.split('\n') if not x.startswith('#')]) - self.assertEqual(psutil.cpu_count(logical=True), num) - - # --- mocked tests - - def test_virtual_memory_mocked_warnings(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil._pslinux.virtual_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - self.assertTrue(w.filename.endswith('psutil/_pslinux.py')) - self.assertIn( - "'cached', 'active' and 'inactive' memory stats couldn't " - "be determined", str(w.message)) - self.assertEqual(ret.cached, 0) - self.assertEqual(ret.active, 0) - self.assertEqual(ret.inactive, 0) - - def test_swap_memory_mocked_warnings(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - with warnings.catch_warnings(record=True) as ws: - warnings.simplefilter("always") - ret = psutil._pslinux.swap_memory() - assert m.called - self.assertEqual(len(ws), 1) - w = ws[0] - self.assertTrue(w.filename.endswith('psutil/_pslinux.py')) - self.assertIn( - "'sin' and 'sout' swap memory stats couldn't " - "be determined", str(w.message)) - self.assertEqual(ret.sin, 0) - self.assertEqual(ret.sout, 0) - - def test_cpu_count_logical_mocked(self): - import psutil._pslinux - original = psutil._pslinux.cpu_count_logical() - # Here we want to mock os.sysconf("SC_NPROCESSORS_ONLN") in - # order to cause the parsing of /proc/cpuinfo and /proc/stat. - with mock.patch( - 'psutil._pslinux.os.sysconf', side_effect=ValueError) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - assert m.called - - # Let's have open() return emtpy data and make sure None is - # returned ('cause we mimick os.cpu_count()). - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertIsNone(psutil._pslinux.cpu_count_logical()) - self.assertEqual(m.call_count, 2) - # /proc/stat should be the last one - self.assertEqual(m.call_args[0][0], '/proc/stat') - - # Let's push this a bit further and make sure /proc/cpuinfo - # parsing works as expected. - with open('/proc/cpuinfo', 'rb') as f: - cpuinfo_data = f.read() - fake_file = io.BytesIO(cpuinfo_data) - with mock.patch('psutil._pslinux.open', - return_value=fake_file, create=True) as m: - self.assertEqual(psutil._pslinux.cpu_count_logical(), original) - - def test_cpu_count_physical_mocked(self): - # Have open() return emtpy data and make sure None is returned - # ('cause we want to mimick os.cpu_count()) - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertIsNone(psutil._pslinux.cpu_count_physical()) - assert m.called - - def test_proc_open_files_file_gone(self): - # simulates a file which gets deleted during open_files() - # execution - p = psutil.Process() - files = p.open_files() - with tempfile.NamedTemporaryFile(): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.ENOENT, "")) as m: - files = p.open_files() - assert not files - assert m.called - # also simulate the case where os.readlink() returns EINVAL - # in which case psutil is supposed to 'continue' - with mock.patch('psutil._pslinux.os.readlink', - side_effect=OSError(errno.EINVAL, "")) as m: - self.assertEqual(p.open_files(), []) - assert m.called - - def test_proc_terminal_mocked(self): - with mock.patch('psutil._pslinux._psposix._get_terminal_map', - return_value={}) as m: - self.assertIsNone(psutil._pslinux.Process(os.getpid()).terminal()) - assert m.called - - def test_proc_num_ctx_switches_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).num_ctx_switches) - assert m.called - - def test_proc_num_threads_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).num_threads) - assert m.called - - def test_proc_ppid_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).ppid) - assert m.called - - def test_proc_uids_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).uids) - assert m.called - - def test_proc_gids_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).gids) - assert m.called - - def test_proc_cmdline_mocked(self): - # see: https://github.com/giampaolo/psutil/issues/639 - p = psutil.Process() - fake_file = io.StringIO(u('foo\x00bar\x00')) - with mock.patch('psutil._pslinux.open', - return_value=fake_file, create=True) as m: - p.cmdline() == ['foo', 'bar'] - assert m.called - fake_file = io.StringIO(u('foo\x00bar\x00\x00')) - with mock.patch('psutil._pslinux.open', - return_value=fake_file, create=True) as m: - p.cmdline() == ['foo', 'bar', ''] - assert m.called - - def test_proc_io_counters_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - NotImplementedError, - psutil._pslinux.Process(os.getpid()).io_counters) - assert m.called - - def test_boot_time_mocked(self): - with mock.patch('psutil._pslinux.open', create=True) as m: - self.assertRaises( - RuntimeError, - psutil._pslinux.boot_time) - assert m.called - - def test_users_mocked(self): - # Make sure ':0' and ':0.0' (returned by C ext) are converted - # to 'localhost'. - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0', - 1436573184.0, True)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', ':0.0', - 1436573184.0, True)]) as m: - self.assertEqual(psutil.users()[0].host, 'localhost') - assert m.called - # ...otherwise it should be returned as-is - with mock.patch('psutil._pslinux.cext.users', - return_value=[('giampaolo', 'pts/2', 'foo', - 1436573184.0, True)]) as m: - self.assertEqual(psutil.users()[0].host, 'foo') - assert m.called - - def test_disk_partitions_mocked(self): - # Test that ZFS partitions are returned. - with open("/proc/filesystems", "r") as f: - data = f.read() - if 'zfs' in data: - for part in psutil.disk_partitions(): - if part.fstype == 'zfs': - break - else: - self.fail("couldn't find any ZFS partition") - else: - # No ZFS partitions on this system. Let's fake one. - fake_file = io.StringIO(u("nodev\tzfs\n")) - with mock.patch('psutil._pslinux.open', - return_value=fake_file, create=True) as m1: - with mock.patch( - 'psutil._pslinux.cext.disk_partitions', - return_value=[('/dev/sdb3', '/', 'zfs', 'rw')]) as m2: - ret = psutil.disk_partitions() - assert m1.called - assert m2.called - assert ret - self.assertEqual(ret[0].fstype, 'zfs') - - # --- tests for specific kernel versions - - @unittest.skipUnless( - get_kernel_version() >= (2, 6, 36), - "prlimit() not available on this Linux kernel version") - def test_prlimit_availability(self): - # prlimit() should be available starting from kernel 2.6.36 - p = psutil.Process(os.getpid()) - p.rlimit(psutil.RLIMIT_NOFILE) - # if prlimit() is supported *at least* these constants should - # be available - self.assertTrue(hasattr(psutil, "RLIM_INFINITY")) - self.assertTrue(hasattr(psutil, "RLIMIT_AS")) - self.assertTrue(hasattr(psutil, "RLIMIT_CORE")) - self.assertTrue(hasattr(psutil, "RLIMIT_CPU")) - self.assertTrue(hasattr(psutil, "RLIMIT_DATA")) - self.assertTrue(hasattr(psutil, "RLIMIT_FSIZE")) - self.assertTrue(hasattr(psutil, "RLIMIT_LOCKS")) - self.assertTrue(hasattr(psutil, "RLIMIT_MEMLOCK")) - self.assertTrue(hasattr(psutil, "RLIMIT_NOFILE")) - self.assertTrue(hasattr(psutil, "RLIMIT_NPROC")) - self.assertTrue(hasattr(psutil, "RLIMIT_RSS")) - self.assertTrue(hasattr(psutil, "RLIMIT_STACK")) - - @unittest.skipUnless( - get_kernel_version() >= (3, 0), - "prlimit constants not available on this Linux kernel version") - def test_resource_consts_kernel_v(self): - # more recent constants - self.assertTrue(hasattr(psutil, "RLIMIT_MSGQUEUE")) - self.assertTrue(hasattr(psutil, "RLIMIT_NICE")) - self.assertTrue(hasattr(psutil, "RLIMIT_RTPRIO")) - self.assertTrue(hasattr(psutil, "RLIMIT_RTTIME")) - self.assertTrue(hasattr(psutil, "RLIMIT_SIGPENDING")) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(LinuxSpecificTestCase)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/_osx.py b/python/psutil/test/_osx.py deleted file mode 100644 index 6e6e4380e..000000000 --- a/python/psutil/test/_osx.py +++ /dev/null @@ -1,160 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""OSX specific tests. These are implicitly run by test_psutil.py.""" - -import os -import re -import subprocess -import sys -import time - -import psutil - -from psutil._compat import PY3 -from test_psutil import (TOLERANCE, OSX, sh, get_test_subprocess, - reap_children, retry_before_failing, unittest) - - -PAGESIZE = os.sysconf("SC_PAGE_SIZE") - - -def sysctl(cmdline): - """Expects a sysctl command with an argument and parse the result - returning only the value of interest. - """ - p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) - result = p.communicate()[0].strip().split()[1] - if PY3: - result = str(result, sys.stdout.encoding) - try: - return int(result) - except ValueError: - return result - - -def vm_stat(field): - """Wrapper around 'vm_stat' cmdline utility.""" - out = sh('vm_stat') - for line in out.split('\n'): - if field in line: - break - else: - raise ValueError("line not found") - return int(re.search('\d+', line).group(0)) * PAGESIZE - - -@unittest.skipUnless(OSX, "not an OSX system") -class OSXSpecificTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_process_create_time(self): - cmdline = "ps -o lstart -p %s" % self.pid - p = subprocess.Popen(cmdline, shell=1, stdout=subprocess.PIPE) - output = p.communicate()[0] - if PY3: - output = str(output, sys.stdout.encoding) - start_ps = output.replace('STARTED', '').strip() - start_psutil = psutil.Process(self.pid).create_time() - start_psutil = time.strftime("%a %b %e %H:%M:%S %Y", - time.localtime(start_psutil)) - self.assertEqual(start_ps, start_psutil) - - def test_disks(self): - # test psutil.disk_usage() and psutil.disk_partitions() - # against "df -a" - def df(path): - out = sh('df -k "%s"' % path).strip() - lines = out.split('\n') - lines.pop(0) - line = lines.pop(0) - dev, total, used, free = line.split()[:4] - if dev == 'none': - dev = '' - total = int(total) * 1024 - used = int(used) * 1024 - free = int(free) * 1024 - return dev, total, used, free - - for part in psutil.disk_partitions(all=False): - usage = psutil.disk_usage(part.mountpoint) - dev, total, used, free = df(part.mountpoint) - self.assertEqual(part.device, dev) - self.assertEqual(usage.total, total) - # 10 MB tollerance - if abs(usage.free - free) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.free, free) - if abs(usage.used - used) > 10 * 1024 * 1024: - self.fail("psutil=%s, df=%s" % usage.used, used) - - # --- virtual mem - - def test_vmem_total(self): - sysctl_hwphymem = sysctl('sysctl hw.memsize') - self.assertEqual(sysctl_hwphymem, psutil.virtual_memory().total) - - @retry_before_failing() - def test_vmem_free(self): - num = vm_stat("free") - self.assertAlmostEqual(psutil.virtual_memory().free, num, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_active(self): - num = vm_stat("active") - self.assertAlmostEqual(psutil.virtual_memory().active, num, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_inactive(self): - num = vm_stat("inactive") - self.assertAlmostEqual(psutil.virtual_memory().inactive, num, - delta=TOLERANCE) - - @retry_before_failing() - def test_vmem_wired(self): - num = vm_stat("wired") - self.assertAlmostEqual(psutil.virtual_memory().wired, num, - delta=TOLERANCE) - - # --- swap mem - - def test_swapmem_sin(self): - num = vm_stat("Pageins") - self.assertEqual(psutil.swap_memory().sin, num) - - def test_swapmem_sout(self): - num = vm_stat("Pageouts") - self.assertEqual(psutil.swap_memory().sout, num) - - def test_swapmem_total(self): - tot1 = psutil.swap_memory().total - tot2 = 0 - # OSX uses multiple cache files: - # http://en.wikipedia.org/wiki/Paging#OS_X - for name in os.listdir("/var/vm/"): - file = os.path.join("/var/vm", name) - if os.path.isfile(file): - tot2 += os.path.getsize(file) - self.assertEqual(tot1, tot2) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(OSXSpecificTestCase)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/_posix.py b/python/psutil/test/_posix.py deleted file mode 100644 index e6c56aac3..000000000 --- a/python/psutil/test/_posix.py +++ /dev/null @@ -1,258 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""POSIX specific tests. These are implicitly run by test_psutil.py.""" - -import datetime -import os -import subprocess -import sys -import time - -import psutil - -from psutil._compat import PY3, callable -from test_psutil import LINUX, SUNOS, OSX, BSD, PYTHON, POSIX, TRAVIS -from test_psutil import (get_test_subprocess, skip_on_access_denied, - retry_before_failing, reap_children, sh, unittest, - get_kernel_version, wait_for_pid) - - -def ps(cmd): - """Expects a ps command with a -o argument and parse the result - returning only the value of interest. - """ - if not LINUX: - cmd = cmd.replace(" --no-headers ", " ") - if SUNOS: - cmd = cmd.replace("-o command", "-o comm") - cmd = cmd.replace("-o start", "-o stime") - p = subprocess.Popen(cmd, shell=1, stdout=subprocess.PIPE) - output = p.communicate()[0].strip() - if PY3: - output = str(output, sys.stdout.encoding) - if not LINUX: - output = output.split('\n')[1].strip() - try: - return int(output) - except ValueError: - return output - - -@unittest.skipUnless(POSIX, "not a POSIX system") -class PosixSpecificTestCase(unittest.TestCase): - """Compare psutil results against 'ps' command line utility.""" - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess([PYTHON, "-E", "-O"], - stdin=subprocess.PIPE).pid - wait_for_pid(cls.pid) - - @classmethod - def tearDownClass(cls): - reap_children() - - # for ps -o arguments see: http://unixhelp.ed.ac.uk/CGI/man-cgi?ps - - def test_process_parent_pid(self): - ppid_ps = ps("ps --no-headers -o ppid -p %s" % self.pid) - ppid_psutil = psutil.Process(self.pid).ppid() - self.assertEqual(ppid_ps, ppid_psutil) - - def test_process_uid(self): - uid_ps = ps("ps --no-headers -o uid -p %s" % self.pid) - uid_psutil = psutil.Process(self.pid).uids().real - self.assertEqual(uid_ps, uid_psutil) - - def test_process_gid(self): - gid_ps = ps("ps --no-headers -o rgid -p %s" % self.pid) - gid_psutil = psutil.Process(self.pid).gids().real - self.assertEqual(gid_ps, gid_psutil) - - def test_process_username(self): - username_ps = ps("ps --no-headers -o user -p %s" % self.pid) - username_psutil = psutil.Process(self.pid).username() - self.assertEqual(username_ps, username_psutil) - - @skip_on_access_denied() - @retry_before_failing() - def test_process_rss_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - rss_ps = ps("ps --no-headers -o rss -p %s" % self.pid) - rss_psutil = psutil.Process(self.pid).memory_info()[0] / 1024 - self.assertEqual(rss_ps, rss_psutil) - - @skip_on_access_denied() - @retry_before_failing() - def test_process_vsz_memory(self): - # give python interpreter some time to properly initialize - # so that the results are the same - time.sleep(0.1) - vsz_ps = ps("ps --no-headers -o vsz -p %s" % self.pid) - vsz_psutil = psutil.Process(self.pid).memory_info()[1] / 1024 - self.assertEqual(vsz_ps, vsz_psutil) - - def test_process_name(self): - # use command + arg since "comm" keyword not supported on all platforms - name_ps = ps("ps --no-headers -o command -p %s" % ( - self.pid)).split(' ')[0] - # remove path if there is any, from the command - name_ps = os.path.basename(name_ps).lower() - name_psutil = psutil.Process(self.pid).name().lower() - self.assertEqual(name_ps, name_psutil) - - @unittest.skipIf(OSX or BSD, - 'ps -o start not available') - def test_process_create_time(self): - time_ps = ps("ps --no-headers -o start -p %s" % self.pid).split(' ')[0] - time_psutil = psutil.Process(self.pid).create_time() - time_psutil_tstamp = datetime.datetime.fromtimestamp( - time_psutil).strftime("%H:%M:%S") - # sometimes ps shows the time rounded up instead of down, so we check - # for both possible values - round_time_psutil = round(time_psutil) - round_time_psutil_tstamp = datetime.datetime.fromtimestamp( - round_time_psutil).strftime("%H:%M:%S") - self.assertIn(time_ps, [time_psutil_tstamp, round_time_psutil_tstamp]) - - def test_process_exe(self): - ps_pathname = ps("ps --no-headers -o command -p %s" % - self.pid).split(' ')[0] - psutil_pathname = psutil.Process(self.pid).exe() - try: - self.assertEqual(ps_pathname, psutil_pathname) - except AssertionError: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - adjusted_ps_pathname = ps_pathname[:len(ps_pathname)] - self.assertEqual(ps_pathname, adjusted_ps_pathname) - - def test_process_cmdline(self): - ps_cmdline = ps("ps --no-headers -o command -p %s" % self.pid) - psutil_cmdline = " ".join(psutil.Process(self.pid).cmdline()) - if SUNOS: - # ps on Solaris only shows the first part of the cmdline - psutil_cmdline = psutil_cmdline.split(" ")[0] - self.assertEqual(ps_cmdline, psutil_cmdline) - - @retry_before_failing() - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - if SUNOS: - cmd = ["ps", "ax"] - else: - cmd = ["ps", "ax", "-o", "pid"] - p = get_test_subprocess(cmd, stdout=subprocess.PIPE) - output = p.communicate()[0].strip() - if PY3: - output = str(output, sys.stdout.encoding) - pids_ps = [] - for line in output.split('\n')[1:]: - if line: - pid = int(line.split()[0].strip()) - pids_ps.append(pid) - # remove ps subprocess pid which is supposed to be dead in meantime - pids_ps.remove(p.pid) - pids_psutil = psutil.pids() - pids_ps.sort() - pids_psutil.sort() - - # on OSX ps doesn't show pid 0 - if OSX and 0 not in pids_ps: - pids_ps.insert(0, 0) - - if pids_ps != pids_psutil: - difference = [x for x in pids_psutil if x not in pids_ps] + \ - [x for x in pids_ps if x not in pids_psutil] - self.fail("difference: " + str(difference)) - - # for some reason ifconfig -a does not report all interfaces - # returned by psutil - @unittest.skipIf(SUNOS, "test not reliable on SUNOS") - @unittest.skipIf(TRAVIS, "test not reliable on Travis") - def test_nic_names(self): - p = subprocess.Popen("ifconfig -a", shell=1, stdout=subprocess.PIPE) - output = p.communicate()[0].strip() - if PY3: - output = str(output, sys.stdout.encoding) - for nic in psutil.net_io_counters(pernic=True).keys(): - for line in output.split(): - if line.startswith(nic): - break - else: - self.fail( - "couldn't find %s nic in 'ifconfig -a' output\n%s" % ( - nic, output)) - - @retry_before_failing() - def test_users(self): - out = sh("who") - lines = out.split('\n') - users = [x.split()[0] for x in lines] - self.assertEqual(len(users), len(psutil.users())) - terminals = [x.split()[1] for x in lines] - for u in psutil.users(): - self.assertTrue(u.name in users, u.name) - self.assertTrue(u.terminal in terminals, u.terminal) - - def test_fds_open(self): - # Note: this fails from time to time; I'm keen on thinking - # it doesn't mean something is broken - def call(p, attr): - args = () - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - attr(*args) - else: - attr - - p = psutil.Process(os.getpid()) - failures = [] - ignored_names = ['terminate', 'kill', 'suspend', 'resume', 'nice', - 'send_signal', 'wait', 'children', 'as_dict'] - if LINUX and get_kernel_version() < (2, 6, 36): - ignored_names.append('rlimit') - if LINUX and get_kernel_version() < (2, 6, 23): - ignored_names.append('num_ctx_switches') - for name in dir(psutil.Process): - if (name.startswith('_') or name in ignored_names): - continue - else: - try: - num1 = p.num_fds() - for x in range(2): - call(p, name) - num2 = p.num_fds() - except psutil.AccessDenied: - pass - else: - if abs(num2 - num1) > 1: - fail = "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(PosixSpecificTestCase)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/_sunos.py b/python/psutil/test/_sunos.py deleted file mode 100644 index 3d54ccd8c..000000000 --- a/python/psutil/test/_sunos.py +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Sun OS specific tests. These are implicitly run by test_psutil.py.""" - -import sys -import os - -from test_psutil import SUNOS, sh, unittest -import psutil - - -@unittest.skipUnless(SUNOS, "not a SunOS system") -class SunOSSpecificTestCase(unittest.TestCase): - - def test_swap_memory(self): - out = sh('env PATH=/usr/sbin:/sbin:%s swap -l -k' % os.environ['PATH']) - lines = out.strip().split('\n')[1:] - if not lines: - raise ValueError('no swap device(s) configured') - total = free = 0 - for line in lines: - line = line.split() - t, f = line[-2:] - t = t.replace('K', '') - f = f.replace('K', '') - total += int(int(t) * 1024) - free += int(int(f) * 1024) - used = total - free - - psutil_swap = psutil.swap_memory() - self.assertEqual(psutil_swap.total, total) - self.assertEqual(psutil_swap.used, used) - self.assertEqual(psutil_swap.free, free) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(SunOSSpecificTestCase)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/_windows.py b/python/psutil/test/_windows.py deleted file mode 100644 index b7477bfeb..000000000 --- a/python/psutil/test/_windows.py +++ /dev/null @@ -1,464 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -"""Windows specific tests. These are implicitly run by test_psutil.py.""" - -import errno -import os -import platform -import signal -import subprocess -import sys -import time -import traceback - -from test_psutil import APPVEYOR, WINDOWS -from test_psutil import get_test_subprocess, reap_children, unittest - -import mock -try: - import wmi -except ImportError: - wmi = None -try: - import win32api - import win32con -except ImportError: - win32api = win32con = None - -from psutil._compat import PY3, callable, long -import psutil - - -cext = psutil._psplatform.cext - - -def wrap_exceptions(fun): - def wrapper(self, *args, **kwargs): - try: - return fun(self, *args, **kwargs) - except OSError as err: - from psutil._pswindows import ACCESS_DENIED_SET - if err.errno in ACCESS_DENIED_SET: - raise psutil.AccessDenied(None, None) - if err.errno == errno.ESRCH: - raise psutil.NoSuchProcess(None, None) - raise - return wrapper - - -@unittest.skipUnless(WINDOWS, "not a Windows system") -class WindowsSpecificTestCase(unittest.TestCase): - - @classmethod - def setUpClass(cls): - cls.pid = get_test_subprocess().pid - - @classmethod - def tearDownClass(cls): - reap_children() - - def test_issue_24(self): - p = psutil.Process(0) - self.assertRaises(psutil.AccessDenied, p.kill) - - def test_special_pid(self): - p = psutil.Process(4) - self.assertEqual(p.name(), 'System') - # use __str__ to access all common Process properties to check - # that nothing strange happens - str(p) - p.username() - self.assertTrue(p.create_time() >= 0.0) - try: - rss, vms = p.memory_info() - except psutil.AccessDenied: - # expected on Windows Vista and Windows 7 - if not platform.uname()[1] in ('vista', 'win-7', 'win7'): - raise - else: - self.assertTrue(rss > 0) - - def test_send_signal(self): - p = psutil.Process(self.pid) - self.assertRaises(ValueError, p.send_signal, signal.SIGINT) - - def test_nic_names(self): - p = subprocess.Popen(['ipconfig', '/all'], stdout=subprocess.PIPE) - out = p.communicate()[0] - if PY3: - out = str(out, sys.stdout.encoding) - nics = psutil.net_io_counters(pernic=True).keys() - for nic in nics: - if "pseudo-interface" in nic.replace(' ', '-').lower(): - continue - if nic not in out: - self.fail( - "%r nic wasn't found in 'ipconfig /all' output" % nic) - - def test_exe(self): - for p in psutil.process_iter(): - try: - self.assertEqual(os.path.basename(p.exe()), p.name()) - except psutil.Error: - pass - - # --- Process class tests - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_name(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(p.name(), w.Caption) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_exe(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - # Note: wmi reports the exe as a lower case string. - # Being Windows paths case-insensitive we ignore that. - self.assertEqual(p.exe().lower(), w.ExecutablePath.lower()) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_cmdline(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - self.assertEqual(' '.join(p.cmdline()), - w.CommandLine.replace('"', '')) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_username(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - domain, _, username = w.GetOwner() - username = "%s\\%s" % (domain, username) - self.assertEqual(p.username(), username) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_rss_memory(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - rss = p.memory_info().rss - self.assertEqual(rss, int(w.WorkingSetSize)) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_vms_memory(self): - time.sleep(0.1) - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - vms = p.memory_info().vms - # http://msdn.microsoft.com/en-us/library/aa394372(VS.85).aspx - # ...claims that PageFileUsage is represented in Kilo - # bytes but funnily enough on certain platforms bytes are - # returned instead. - wmi_usage = int(w.PageFileUsage) - if (vms != wmi_usage) and (vms != wmi_usage * 1024): - self.fail("wmi=%s, psutil=%s" % (wmi_usage, vms)) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_process_create_time(self): - w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - p = psutil.Process(self.pid) - wmic_create = str(w.CreationDate.split('.')[0]) - psutil_create = time.strftime("%Y%m%d%H%M%S", - time.localtime(p.create_time())) - self.assertEqual(wmic_create, psutil_create) - - # --- psutil namespace functions and constants tests - - @unittest.skipUnless('NUMBER_OF_PROCESSORS' in os.environ, - 'NUMBER_OF_PROCESSORS env var is not available') - def test_cpu_count(self): - num_cpus = int(os.environ['NUMBER_OF_PROCESSORS']) - self.assertEqual(num_cpus, psutil.cpu_count()) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_total_phymem(self): - w = wmi.WMI().Win32_ComputerSystem()[0] - self.assertEqual(int(w.TotalPhysicalMemory), - psutil.virtual_memory().total) - - # @unittest.skipIf(wmi is None, "wmi module is not installed") - # def test__UPTIME(self): - # # _UPTIME constant is not public but it is used internally - # # as value to return for pid 0 creation time. - # # WMI behaves the same. - # w = wmi.WMI().Win32_Process(ProcessId=self.pid)[0] - # p = psutil.Process(0) - # wmic_create = str(w.CreationDate.split('.')[0]) - # psutil_create = time.strftime("%Y%m%d%H%M%S", - # time.localtime(p.create_time())) - # - - # Note: this test is not very reliable - @unittest.skipIf(wmi is None, "wmi module is not installed") - @unittest.skipIf(APPVEYOR, "test not relieable on appveyor") - def test_pids(self): - # Note: this test might fail if the OS is starting/killing - # other processes in the meantime - w = wmi.WMI().Win32_Process() - wmi_pids = set([x.ProcessId for x in w]) - psutil_pids = set(psutil.pids()) - self.assertEqual(wmi_pids, psutil_pids) - - @unittest.skipIf(wmi is None, "wmi module is not installed") - def test_disks(self): - ps_parts = psutil.disk_partitions(all=True) - wmi_parts = wmi.WMI().Win32_LogicalDisk() - for ps_part in ps_parts: - for wmi_part in wmi_parts: - if ps_part.device.replace('\\', '') == wmi_part.DeviceID: - if not ps_part.mountpoint: - # this is usually a CD-ROM with no disk inserted - break - try: - usage = psutil.disk_usage(ps_part.mountpoint) - except OSError as err: - if err.errno == errno.ENOENT: - # usually this is the floppy - break - else: - raise - self.assertEqual(usage.total, int(wmi_part.Size)) - wmi_free = int(wmi_part.FreeSpace) - self.assertEqual(usage.free, wmi_free) - # 10 MB tollerance - if abs(usage.free - wmi_free) > 10 * 1024 * 1024: - self.fail("psutil=%s, wmi=%s" % ( - usage.free, wmi_free)) - break - else: - self.fail("can't find partition %s" % repr(ps_part)) - - @unittest.skipIf(win32api is None, "pywin32 module is not installed") - def test_num_handles(self): - p = psutil.Process(os.getpid()) - before = p.num_handles() - handle = win32api.OpenProcess(win32con.PROCESS_QUERY_INFORMATION, - win32con.FALSE, os.getpid()) - after = p.num_handles() - self.assertEqual(after, before + 1) - win32api.CloseHandle(handle) - self.assertEqual(p.num_handles(), before) - - @unittest.skipIf(win32api is None, "pywin32 module is not installed") - def test_num_handles_2(self): - # Note: this fails from time to time; I'm keen on thinking - # it doesn't mean something is broken - def call(p, attr): - attr = getattr(p, name, None) - if attr is not None and callable(attr): - attr() - else: - attr - - p = psutil.Process(self.pid) - failures = [] - for name in dir(psutil.Process): - if name.startswith('_') \ - or name in ('terminate', 'kill', 'suspend', 'resume', - 'nice', 'send_signal', 'wait', 'children', - 'as_dict'): - continue - else: - try: - call(p, name) - num1 = p.num_handles() - call(p, name) - num2 = p.num_handles() - except (psutil.NoSuchProcess, psutil.AccessDenied): - pass - else: - if num2 > num1: - fail = \ - "failure while processing Process.%s method " \ - "(before=%s, after=%s)" % (name, num1, num2) - failures.append(fail) - if failures: - self.fail('\n' + '\n'.join(failures)) - - def test_name_always_available(self): - # On Windows name() is never supposed to raise AccessDenied, - # see https://github.com/giampaolo/psutil/issues/627 - for p in psutil.process_iter(): - try: - p.name() - except psutil.NoSuchProcess(): - pass - - -@unittest.skipUnless(WINDOWS, "not a Windows system") -class TestDualProcessImplementation(unittest.TestCase): - """ - Certain APIs on Windows have 2 internal implementations, one - based on documented Windows APIs, another one based - NtQuerySystemInformation() which gets called as fallback in - case the first fails because of limited permission error. - Here we test that the two methods return the exact same value, - see: - https://github.com/giampaolo/psutil/issues/304 - """ - - fun_names = [ - # function name, tolerance - ('proc_cpu_times', 0.2), - ('proc_create_time', 0.5), - ('proc_num_handles', 1), # 1 because impl #1 opens a handle - ('proc_memory_info', 1024), # KB - ('proc_io_counters', 0), - ] - - def test_compare_values(self): - def assert_ge_0(obj): - if isinstance(obj, tuple): - for value in obj: - self.assertGreaterEqual(value, 0, msg=obj) - elif isinstance(obj, (int, long, float)): - self.assertGreaterEqual(obj, 0) - else: - assert 0 # case not handled which needs to be fixed - - def compare_with_tolerance(ret1, ret2, tolerance): - if ret1 == ret2: - return - else: - if isinstance(ret2, (int, long, float)): - diff = abs(ret1 - ret2) - self.assertLessEqual(diff, tolerance) - elif isinstance(ret2, tuple): - for a, b in zip(ret1, ret2): - diff = abs(a - b) - self.assertLessEqual(diff, tolerance) - - from psutil._pswindows import ntpinfo - failures = [] - for p in psutil.process_iter(): - try: - nt = ntpinfo(*cext.proc_info(p.pid)) - except psutil.NoSuchProcess: - continue - assert_ge_0(nt) - - for name, tolerance in self.fun_names: - if name == 'proc_memory_info' and p.pid == os.getpid(): - continue - if name == 'proc_create_time' and p.pid in (0, 4): - continue - meth = wrap_exceptions(getattr(cext, name)) - try: - ret = meth(p.pid) - except (psutil.NoSuchProcess, psutil.AccessDenied): - continue - # compare values - try: - if name == 'proc_cpu_times': - compare_with_tolerance(ret[0], nt.user_time, tolerance) - compare_with_tolerance(ret[1], - nt.kernel_time, tolerance) - elif name == 'proc_create_time': - compare_with_tolerance(ret, nt.create_time, tolerance) - elif name == 'proc_num_handles': - compare_with_tolerance(ret, nt.num_handles, tolerance) - elif name == 'proc_io_counters': - compare_with_tolerance(ret[0], nt.io_rcount, tolerance) - compare_with_tolerance(ret[1], nt.io_wcount, tolerance) - compare_with_tolerance(ret[2], nt.io_rbytes, tolerance) - compare_with_tolerance(ret[3], nt.io_wbytes, tolerance) - elif name == 'proc_memory_info': - try: - rawtupl = cext.proc_memory_info_2(p.pid) - except psutil.NoSuchProcess: - continue - compare_with_tolerance(ret, rawtupl, tolerance) - except AssertionError: - trace = traceback.format_exc() - msg = '%s\npid=%s, method=%r, ret_1=%r, ret_2=%r' % ( - trace, p.pid, name, ret, nt) - failures.append(msg) - break - - if failures: - self.fail('\n\n'.join(failures)) - - # --- - # same tests as above but mimicks the AccessDenied failure of - # the first (fast) method failing with AD. - # TODO: currently does not take tolerance into account. - - def test_name(self): - name = psutil.Process().name() - with mock.patch("psutil._psplatform.cext.proc_exe", - side_effect=psutil.AccessDenied(os.getpid())) as fun: - psutil.Process().name() == name - assert fun.called - - def test_memory_info(self): - mem = psutil.Process().memory_info() - with mock.patch("psutil._psplatform.cext.proc_memory_info", - side_effect=OSError(errno.EPERM, "msg")) as fun: - psutil.Process().memory_info() == mem - assert fun.called - - def test_create_time(self): - ctime = psutil.Process().create_time() - with mock.patch("psutil._psplatform.cext.proc_create_time", - side_effect=OSError(errno.EPERM, "msg")) as fun: - psutil.Process().create_time() == ctime - assert fun.called - - def test_cpu_times(self): - cpu_times = psutil.Process().cpu_times() - with mock.patch("psutil._psplatform.cext.proc_cpu_times", - side_effect=OSError(errno.EPERM, "msg")) as fun: - psutil.Process().cpu_times() == cpu_times - assert fun.called - - def test_io_counters(self): - io_counters = psutil.Process().io_counters() - with mock.patch("psutil._psplatform.cext.proc_io_counters", - side_effect=OSError(errno.EPERM, "msg")) as fun: - psutil.Process().io_counters() == io_counters - assert fun.called - - def test_num_handles(self): - io_counters = psutil.Process().io_counters() - with mock.patch("psutil._psplatform.cext.proc_io_counters", - side_effect=OSError(errno.EPERM, "msg")) as fun: - psutil.Process().io_counters() == io_counters - assert fun.called - - # --- other tests - - def test_compare_name_exe(self): - for p in psutil.process_iter(): - try: - a = os.path.basename(p.exe()) - b = p.name() - except (psutil.NoSuchProcess, psutil.AccessDenied): - pass - else: - self.assertEqual(a, b) - - def test_zombies(self): - # test that NPS is raised by the 2nd implementation in case a - # process no longer exists - ZOMBIE_PID = max(psutil.pids()) + 5000 - for name, _ in self.fun_names: - meth = wrap_exceptions(getattr(cext, name)) - self.assertRaises(psutil.NoSuchProcess, meth, ZOMBIE_PID) - - -def main(): - test_suite = unittest.TestSuite() - test_suite.addTest(unittest.makeSuite(WindowsSpecificTestCase)) - test_suite.addTest(unittest.makeSuite(TestDualProcessImplementation)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/test_memory_leaks.py b/python/psutil/test/test_memory_leaks.py deleted file mode 100644 index 6f02dc0ac..000000000 --- a/python/psutil/test/test_memory_leaks.py +++ /dev/null @@ -1,445 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -A test script which attempts to detect memory leaks by calling C -functions many times and compare process memory usage before and -after the calls. It might produce false positives. -""" - -import functools -import gc -import os -import socket -import sys -import threading -import time - -import psutil -import psutil._common - -from psutil._compat import xrange, callable -from test_psutil import (WINDOWS, POSIX, OSX, LINUX, SUNOS, BSD, TESTFN, - RLIMIT_SUPPORT, TRAVIS) -from test_psutil import (reap_children, supports_ipv6, safe_remove, - get_test_subprocess) - -if sys.version_info < (2, 7): - import unittest2 as unittest # https://pypi.python.org/pypi/unittest2 -else: - import unittest - - -LOOPS = 1000 -TOLERANCE = 4096 -SKIP_PYTHON_IMPL = True - - -def skip_if_linux(): - return unittest.skipIf(LINUX and SKIP_PYTHON_IMPL, - "not worth being tested on LINUX (pure python)") - - -class Base(unittest.TestCase): - proc = psutil.Process() - - def execute(self, function, *args, **kwargs): - def call_many_times(): - for x in xrange(LOOPS - 1): - self.call(function, *args, **kwargs) - del x - gc.collect() - return self.get_mem() - - self.call(function, *args, **kwargs) - self.assertEqual(gc.garbage, []) - self.assertEqual(threading.active_count(), 1) - - # RSS comparison - # step 1 - rss1 = call_many_times() - # step 2 - rss2 = call_many_times() - - difference = rss2 - rss1 - if difference > TOLERANCE: - # This doesn't necessarily mean we have a leak yet. - # At this point we assume that after having called the - # function so many times the memory usage is stabilized - # and if there are no leaks it should not increase any - # more. - # Let's keep calling fun for 3 more seconds and fail if - # we notice any difference. - stop_at = time.time() + 3 - while True: - self.call(function, *args, **kwargs) - if time.time() >= stop_at: - break - del stop_at - gc.collect() - rss3 = self.get_mem() - difference = rss3 - rss2 - if rss3 > rss2: - self.fail("rss2=%s, rss3=%s, difference=%s" - % (rss2, rss3, difference)) - - def execute_w_exc(self, exc, function, *args, **kwargs): - kwargs['_exc'] = exc - self.execute(function, *args, **kwargs) - - def get_mem(self): - return psutil.Process().memory_info()[0] - - def call(self, function, *args, **kwargs): - raise NotImplementedError("must be implemented in subclass") - - -class TestProcessObjectLeaks(Base): - """Test leaks of Process class methods and properties""" - - def setUp(self): - gc.collect() - - def tearDown(self): - reap_children() - - def call(self, function, *args, **kwargs): - if callable(function): - if '_exc' in kwargs: - exc = kwargs.pop('_exc') - self.assertRaises(exc, function, *args, **kwargs) - else: - try: - function(*args, **kwargs) - except psutil.Error: - pass - else: - meth = getattr(self.proc, function) - if '_exc' in kwargs: - exc = kwargs.pop('_exc') - self.assertRaises(exc, meth, *args, **kwargs) - else: - try: - meth(*args, **kwargs) - except psutil.Error: - pass - - @skip_if_linux() - def test_name(self): - self.execute('name') - - @skip_if_linux() - def test_cmdline(self): - self.execute('cmdline') - - @skip_if_linux() - def test_exe(self): - self.execute('exe') - - @skip_if_linux() - def test_ppid(self): - self.execute('ppid') - - @unittest.skipUnless(POSIX, "POSIX only") - @skip_if_linux() - def test_uids(self): - self.execute('uids') - - @unittest.skipUnless(POSIX, "POSIX only") - @skip_if_linux() - def test_gids(self): - self.execute('gids') - - @skip_if_linux() - def test_status(self): - self.execute('status') - - def test_nice_get(self): - self.execute('nice') - - def test_nice_set(self): - niceness = psutil.Process().nice() - self.execute('nice', niceness) - - @unittest.skipUnless(hasattr(psutil.Process, 'ionice'), - "Linux and Windows Vista only") - def test_ionice_get(self): - self.execute('ionice') - - @unittest.skipUnless(hasattr(psutil.Process, 'ionice'), - "Linux and Windows Vista only") - def test_ionice_set(self): - if WINDOWS: - value = psutil.Process().ionice() - self.execute('ionice', value) - else: - from psutil._pslinux import cext - self.execute('ionice', psutil.IOPRIO_CLASS_NONE) - fun = functools.partial(cext.proc_ioprio_set, os.getpid(), -1, 0) - self.execute_w_exc(OSError, fun) - - @unittest.skipIf(OSX or SUNOS, "feature not supported on this platform") - @skip_if_linux() - def test_io_counters(self): - self.execute('io_counters') - - @unittest.skipUnless(WINDOWS, "not worth being tested on posix") - def test_username(self): - self.execute('username') - - @skip_if_linux() - def test_create_time(self): - self.execute('create_time') - - @skip_if_linux() - def test_num_threads(self): - self.execute('num_threads') - - @unittest.skipUnless(WINDOWS, "Windows only") - def test_num_handles(self): - self.execute('num_handles') - - @unittest.skipUnless(POSIX, "POSIX only") - @skip_if_linux() - def test_num_fds(self): - self.execute('num_fds') - - @skip_if_linux() - def test_threads(self): - self.execute('threads') - - @skip_if_linux() - def test_cpu_times(self): - self.execute('cpu_times') - - @skip_if_linux() - def test_memory_info(self): - self.execute('memory_info') - - @skip_if_linux() - def test_memory_info_ex(self): - self.execute('memory_info_ex') - - @unittest.skipUnless(POSIX, "POSIX only") - @skip_if_linux() - def test_terminal(self): - self.execute('terminal') - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "not worth being tested on POSIX (pure python)") - def test_resume(self): - self.execute('resume') - - @skip_if_linux() - def test_cwd(self): - self.execute('cwd') - - @unittest.skipUnless(WINDOWS or LINUX or BSD, - "Windows or Linux or BSD only") - def test_cpu_affinity_get(self): - self.execute('cpu_affinity') - - @unittest.skipUnless(WINDOWS or LINUX or BSD, - "Windows or Linux or BSD only") - def test_cpu_affinity_set(self): - affinity = psutil.Process().cpu_affinity() - self.execute('cpu_affinity', affinity) - if not TRAVIS: - self.execute_w_exc(ValueError, 'cpu_affinity', [-1]) - - @skip_if_linux() - def test_open_files(self): - safe_remove(TESTFN) # needed after UNIX socket test has run - with open(TESTFN, 'w'): - self.execute('open_files') - - # OSX implementation is unbelievably slow - @unittest.skipIf(OSX, "OSX implementation is too slow") - @skip_if_linux() - def test_memory_maps(self): - self.execute('memory_maps') - - @unittest.skipUnless(LINUX, "Linux only") - @unittest.skipUnless(LINUX and RLIMIT_SUPPORT, - "only available on Linux >= 2.6.36") - def test_rlimit_get(self): - self.execute('rlimit', psutil.RLIMIT_NOFILE) - - @unittest.skipUnless(LINUX, "Linux only") - @unittest.skipUnless(LINUX and RLIMIT_SUPPORT, - "only available on Linux >= 2.6.36") - def test_rlimit_set(self): - limit = psutil.Process().rlimit(psutil.RLIMIT_NOFILE) - self.execute('rlimit', psutil.RLIMIT_NOFILE, limit) - self.execute_w_exc(OSError, 'rlimit', -1) - - @skip_if_linux() - # Windows implementation is based on a single system-wide function - @unittest.skipIf(WINDOWS, "tested later") - def test_connections(self): - def create_socket(family, type): - sock = socket.socket(family, type) - sock.bind(('', 0)) - if type == socket.SOCK_STREAM: - sock.listen(1) - return sock - - socks = [] - socks.append(create_socket(socket.AF_INET, socket.SOCK_STREAM)) - socks.append(create_socket(socket.AF_INET, socket.SOCK_DGRAM)) - if supports_ipv6(): - socks.append(create_socket(socket.AF_INET6, socket.SOCK_STREAM)) - socks.append(create_socket(socket.AF_INET6, socket.SOCK_DGRAM)) - if hasattr(socket, 'AF_UNIX'): - safe_remove(TESTFN) - s = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) - s.bind(TESTFN) - s.listen(1) - socks.append(s) - kind = 'all' - # TODO: UNIX sockets are temporarily implemented by parsing - # 'pfiles' cmd output; we don't want that part of the code to - # be executed. - if SUNOS: - kind = 'inet' - try: - self.execute('connections', kind=kind) - finally: - for s in socks: - s.close() - - -p = get_test_subprocess() -DEAD_PROC = psutil.Process(p.pid) -DEAD_PROC.kill() -DEAD_PROC.wait() -del p - - -class TestProcessObjectLeaksZombie(TestProcessObjectLeaks): - """Same as above but looks for leaks occurring when dealing with - zombie processes raising NoSuchProcess exception. - """ - proc = DEAD_PROC - - def call(self, *args, **kwargs): - try: - TestProcessObjectLeaks.call(self, *args, **kwargs) - except psutil.NoSuchProcess: - pass - - if not POSIX: - def test_kill(self): - self.execute('kill') - - def test_terminate(self): - self.execute('terminate') - - def test_suspend(self): - self.execute('suspend') - - def test_resume(self): - self.execute('resume') - - def test_wait(self): - self.execute('wait') - - -class TestModuleFunctionsLeaks(Base): - """Test leaks of psutil module functions.""" - - def setUp(self): - gc.collect() - - def call(self, function, *args, **kwargs): - fun = getattr(psutil, function) - fun(*args, **kwargs) - - @skip_if_linux() - def test_cpu_count_logical(self): - psutil.cpu_count = psutil._psplatform.cpu_count_logical - self.execute('cpu_count') - - @skip_if_linux() - def test_cpu_count_physical(self): - psutil.cpu_count = psutil._psplatform.cpu_count_physical - self.execute('cpu_count') - - @skip_if_linux() - def test_boot_time(self): - self.execute('boot_time') - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "not worth being tested on POSIX (pure python)") - def test_pid_exists(self): - self.execute('pid_exists', os.getpid()) - - def test_virtual_memory(self): - self.execute('virtual_memory') - - # TODO: remove this skip when this gets fixed - @unittest.skipIf(SUNOS, - "not worth being tested on SUNOS (uses a subprocess)") - def test_swap_memory(self): - self.execute('swap_memory') - - @skip_if_linux() - def test_cpu_times(self): - self.execute('cpu_times') - - @skip_if_linux() - def test_per_cpu_times(self): - self.execute('cpu_times', percpu=True) - - @unittest.skipIf(POSIX and SKIP_PYTHON_IMPL, - "not worth being tested on POSIX (pure python)") - def test_disk_usage(self): - self.execute('disk_usage', '.') - - def test_disk_partitions(self): - self.execute('disk_partitions') - - @skip_if_linux() - def test_net_io_counters(self): - self.execute('net_io_counters') - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this Linux version') - @skip_if_linux() - def test_disk_io_counters(self): - self.execute('disk_io_counters') - - # XXX - on Windows this produces a false positive - @unittest.skipIf(WINDOWS, "XXX produces a false positive on Windows") - def test_users(self): - self.execute('users') - - @unittest.skipIf(LINUX, - "not worth being tested on Linux (pure python)") - def test_net_connections(self): - self.execute('net_connections') - - def test_net_if_addrs(self): - self.execute('net_if_addrs') - - @unittest.skipIf(TRAVIS, "EPERM on travis") - def test_net_if_stats(self): - self.execute('net_if_stats') - - -def main(): - test_suite = unittest.TestSuite() - tests = [TestProcessObjectLeaksZombie, - TestProcessObjectLeaks, - TestModuleFunctionsLeaks] - for test in tests: - test_suite.addTest(unittest.makeSuite(test)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/test/test_psutil.py b/python/psutil/test/test_psutil.py deleted file mode 100644 index 3b2e3587a..000000000 --- a/python/psutil/test/test_psutil.py +++ /dev/null @@ -1,3013 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- - -# Copyright (c) 2009, Giampaolo Rodola'. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -""" -psutil test suite. Run it with: -$ make test - -If you're on Python < 2.7 unittest2 module must be installed first: -https://pypi.python.org/pypi/unittest2 -""" - -from __future__ import division - -import ast -import atexit -import collections -import contextlib -import datetime -import errno -import functools -import imp -import json -import os -import pickle -import pprint -import re -import select -import shutil -import signal -import socket -import stat -import subprocess -import sys -import tempfile -import textwrap -import threading -import time -import traceback -import types -import warnings -from socket import AF_INET, SOCK_STREAM, SOCK_DGRAM -try: - import ipaddress # python >= 3.3 -except ImportError: - ipaddress = None -try: - from unittest import mock # py3 -except ImportError: - import mock # requires "pip install mock" - -import psutil -from psutil._compat import PY3, callable, long, unicode - -if sys.version_info < (2, 7): - import unittest2 as unittest # https://pypi.python.org/pypi/unittest2 -else: - import unittest -if sys.version_info >= (3, 4): - import enum -else: - enum = None - - -# =================================================================== -# --- Constants -# =================================================================== - -# conf for retry_before_failing() decorator -NO_RETRIES = 10 -# bytes tolerance for OS memory related tests -TOLERANCE = 500 * 1024 # 500KB -# the timeout used in functions which have to wait -GLOBAL_TIMEOUT = 3 - -AF_INET6 = getattr(socket, "AF_INET6") -AF_UNIX = getattr(socket, "AF_UNIX", None) -PYTHON = os.path.realpath(sys.executable) -DEVNULL = open(os.devnull, 'r+') -TESTFN = os.path.join(os.getcwd(), "$testfile") -TESTFN_UNICODE = TESTFN + "ƒőő" -TESTFILE_PREFIX = 'psutil-test-suite-' -if not PY3: - try: - TESTFN_UNICODE = unicode(TESTFN_UNICODE, sys.getfilesystemencoding()) - except UnicodeDecodeError: - TESTFN_UNICODE = TESTFN + "???" - -EXAMPLES_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__), - '..', 'examples')) - -POSIX = os.name == 'posix' -WINDOWS = os.name == 'nt' -if WINDOWS: - WIN_VISTA = (6, 0, 0) -LINUX = sys.platform.startswith("linux") -OSX = sys.platform.startswith("darwin") -BSD = sys.platform.startswith("freebsd") -SUNOS = sys.platform.startswith("sunos") -VALID_PROC_STATUSES = [getattr(psutil, x) for x in dir(psutil) - if x.startswith('STATUS_')] -# whether we're running this test suite on Travis (https://travis-ci.org/) -TRAVIS = bool(os.environ.get('TRAVIS')) -# whether we're running this test suite on Appveyor for Windows -# (http://www.appveyor.com/) -APPVEYOR = bool(os.environ.get('APPVEYOR')) - -if TRAVIS or 'tox' in sys.argv[0]: - import ipaddress -if TRAVIS or APPVEYOR: - GLOBAL_TIMEOUT = GLOBAL_TIMEOUT * 4 - - -# =================================================================== -# --- Utility functions -# =================================================================== - -def cleanup(): - reap_children(search_all=True) - safe_remove(TESTFN) - try: - safe_rmdir(TESTFN_UNICODE) - except UnicodeEncodeError: - pass - for path in _testfiles: - safe_remove(path) - -atexit.register(cleanup) -atexit.register(lambda: DEVNULL.close()) - - -_subprocesses_started = set() - - -def get_test_subprocess(cmd=None, stdout=DEVNULL, stderr=DEVNULL, - stdin=DEVNULL, wait=False): - """Return a subprocess.Popen object to use in tests. - By default stdout and stderr are redirected to /dev/null and the - python interpreter is used as test process. - If 'wait' is True attemps to make sure the process is in a - reasonably initialized state. - """ - if cmd is None: - pyline = "" - if wait: - pyline += "open(r'%s', 'w'); " % TESTFN - pyline += "import time; time.sleep(60);" - cmd_ = [PYTHON, "-c", pyline] - else: - cmd_ = cmd - sproc = subprocess.Popen(cmd_, stdout=stdout, stderr=stderr, stdin=stdin) - if wait: - if cmd is None: - stop_at = time.time() + 3 - while stop_at > time.time(): - if os.path.exists(TESTFN): - break - time.sleep(0.001) - else: - warn("couldn't make sure test file was actually created") - else: - wait_for_pid(sproc.pid) - _subprocesses_started.add(psutil.Process(sproc.pid)) - return sproc - - -_testfiles = [] - - -def pyrun(src): - """Run python code 'src' in a separate interpreter. - Return interpreter subprocess. - """ - if PY3: - src = bytes(src, 'ascii') - with tempfile.NamedTemporaryFile( - prefix=TESTFILE_PREFIX, delete=False) as f: - _testfiles.append(f.name) - f.write(src) - f.flush() - subp = get_test_subprocess([PYTHON, f.name], stdout=None, - stderr=None) - wait_for_pid(subp.pid) - return subp - - -def warn(msg): - """Raise a warning msg.""" - warnings.warn(msg, UserWarning) - - -def sh(cmdline, stdout=subprocess.PIPE, stderr=subprocess.PIPE): - """run cmd in a subprocess and return its output. - raises RuntimeError on error. - """ - p = subprocess.Popen(cmdline, shell=True, stdout=stdout, stderr=stderr) - stdout, stderr = p.communicate() - if p.returncode != 0: - raise RuntimeError(stderr) - if stderr: - warn(stderr) - if PY3: - stdout = str(stdout, sys.stdout.encoding) - return stdout.strip() - - -def which(program): - """Same as UNIX which command. Return None on command not found.""" - def is_exe(fpath): - return os.path.isfile(fpath) and os.access(fpath, os.X_OK) - - fpath, fname = os.path.split(program) - if fpath: - if is_exe(program): - return program - else: - for path in os.environ["PATH"].split(os.pathsep): - exe_file = os.path.join(path, program) - if is_exe(exe_file): - return exe_file - return None - - -if POSIX: - def get_kernel_version(): - """Return a tuple such as (2, 6, 36).""" - s = "" - uname = os.uname()[2] - for c in uname: - if c.isdigit() or c == '.': - s += c - else: - break - if not s: - raise ValueError("can't parse %r" % uname) - minor = 0 - micro = 0 - nums = s.split('.') - major = int(nums[0]) - if len(nums) >= 2: - minor = int(nums[1]) - if len(nums) >= 3: - micro = int(nums[2]) - return (major, minor, micro) - - -if LINUX: - RLIMIT_SUPPORT = get_kernel_version() >= (2, 6, 36) -else: - RLIMIT_SUPPORT = False - - -def wait_for_pid(pid, timeout=GLOBAL_TIMEOUT): - """Wait for pid to show up in the process list then return. - Used in the test suite to give time the sub process to initialize. - """ - raise_at = time.time() + timeout - while True: - if pid in psutil.pids(): - # give it one more iteration to allow full initialization - time.sleep(0.01) - return - time.sleep(0.0001) - if time.time() >= raise_at: - raise RuntimeError("Timed out") - - -def wait_for_file(fname, timeout=GLOBAL_TIMEOUT, delete_file=True): - """Wait for a file to be written on disk.""" - stop_at = time.time() + 3 - while time.time() < stop_at: - try: - with open(fname, "r") as f: - data = f.read() - if not data: - continue - if delete_file: - os.remove(fname) - return data - except IOError: - time.sleep(0.001) - raise RuntimeError("timed out (couldn't read file)") - - -def reap_children(search_all=False): - """Kill any subprocess started by this test suite and ensure that - no zombies stick around to hog resources and create problems when - looking for refleaks. - """ - global _subprocesses_started - procs = _subprocesses_started.copy() - if search_all: - this_process = psutil.Process() - for p in this_process.children(recursive=True): - procs.add(p) - for p in procs: - try: - p.terminate() - except psutil.NoSuchProcess: - pass - gone, alive = psutil.wait_procs(procs, timeout=GLOBAL_TIMEOUT) - for p in alive: - warn("couldn't terminate process %s" % p) - try: - p.kill() - except psutil.NoSuchProcess: - pass - _, alive = psutil.wait_procs(alive, timeout=GLOBAL_TIMEOUT) - if alive: - warn("couldn't not kill processes %s" % str(alive)) - _subprocesses_started = set(alive) - - -def check_ip_address(addr, family): - """Attempts to check IP address's validity.""" - if enum and PY3: - assert isinstance(family, enum.IntEnum), family - if family == AF_INET: - octs = [int(x) for x in addr.split('.')] - assert len(octs) == 4, addr - for num in octs: - assert 0 <= num <= 255, addr - if ipaddress: - if not PY3: - addr = unicode(addr) - ipaddress.IPv4Address(addr) - elif family == AF_INET6: - assert isinstance(addr, str), addr - if ipaddress: - if not PY3: - addr = unicode(addr) - ipaddress.IPv6Address(addr) - elif family == psutil.AF_LINK: - assert re.match('([a-fA-F0-9]{2}[:|\-]?){6}', addr) is not None, addr - else: - raise ValueError("unknown family %r", family) - - -def check_connection_ntuple(conn): - """Check validity of a connection namedtuple.""" - valid_conn_states = [getattr(psutil, x) for x in dir(psutil) if - x.startswith('CONN_')] - assert conn[0] == conn.fd - assert conn[1] == conn.family - assert conn[2] == conn.type - assert conn[3] == conn.laddr - assert conn[4] == conn.raddr - assert conn[5] == conn.status - assert conn.type in (SOCK_STREAM, SOCK_DGRAM), repr(conn.type) - assert conn.family in (AF_INET, AF_INET6, AF_UNIX), repr(conn.family) - assert conn.status in valid_conn_states, conn.status - - # check IP address and port sanity - for addr in (conn.laddr, conn.raddr): - if not addr: - continue - if conn.family in (AF_INET, AF_INET6): - assert isinstance(addr, tuple), addr - ip, port = addr - assert isinstance(port, int), port - assert 0 <= port <= 65535, port - check_ip_address(ip, conn.family) - elif conn.family == AF_UNIX: - assert isinstance(addr, (str, None)), addr - else: - raise ValueError("unknown family %r", conn.family) - - if conn.family in (AF_INET, AF_INET6): - # actually try to bind the local socket; ignore IPv6 - # sockets as their address might be represented as - # an IPv4-mapped-address (e.g. "::127.0.0.1") - # and that's rejected by bind() - if conn.family == AF_INET: - s = socket.socket(conn.family, conn.type) - with contextlib.closing(s): - try: - s.bind((conn.laddr[0], 0)) - except socket.error as err: - if err.errno != errno.EADDRNOTAVAIL: - raise - elif conn.family == AF_UNIX: - assert not conn.raddr, repr(conn.raddr) - assert conn.status == psutil.CONN_NONE, conn.status - - if getattr(conn, 'fd', -1) != -1: - assert conn.fd > 0, conn - if hasattr(socket, 'fromfd') and not WINDOWS: - try: - dupsock = socket.fromfd(conn.fd, conn.family, conn.type) - except (socket.error, OSError) as err: - if err.args[0] != errno.EBADF: - raise - else: - with contextlib.closing(dupsock): - assert dupsock.family == conn.family - assert dupsock.type == conn.type - - -def safe_remove(file): - "Convenience function for removing temporary test files" - try: - os.remove(file) - except OSError as err: - if err.errno != errno.ENOENT: - # file is being used by another process - if WINDOWS and isinstance(err, WindowsError) and err.errno == 13: - return - raise - - -def safe_rmdir(dir): - "Convenience function for removing temporary test directories" - try: - os.rmdir(dir) - except OSError as err: - if err.errno != errno.ENOENT: - raise - - -def call_until(fun, expr, timeout=GLOBAL_TIMEOUT): - """Keep calling function for timeout secs and exit if eval() - expression is True. - """ - stop_at = time.time() + timeout - while time.time() < stop_at: - ret = fun() - if eval(expr): - return ret - time.sleep(0.001) - raise RuntimeError('timed out (ret=%r)' % ret) - - -def retry_before_failing(ntimes=None): - """Decorator which runs a test function and retries N times before - actually failing. - """ - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - for x in range(ntimes or NO_RETRIES): - try: - return fun(*args, **kwargs) - except AssertionError: - pass - raise - return wrapper - return decorator - - -def skip_on_access_denied(only_if=None): - """Decorator to Ignore AccessDenied exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except psutil.AccessDenied: - if only_if is not None: - if not only_if: - raise - msg = "%r was skipped because it raised AccessDenied" \ - % fun.__name__ - raise unittest.SkipTest(msg) - return wrapper - return decorator - - -def skip_on_not_implemented(only_if=None): - """Decorator to Ignore NotImplementedError exceptions.""" - def decorator(fun): - @functools.wraps(fun) - def wrapper(*args, **kwargs): - try: - return fun(*args, **kwargs) - except NotImplementedError: - if only_if is not None: - if not only_if: - raise - msg = "%r was skipped because it raised NotImplementedError" \ - % fun.__name__ - raise unittest.SkipTest(msg) - return wrapper - return decorator - - -def supports_ipv6(): - """Return True if IPv6 is supported on this platform.""" - if not socket.has_ipv6 or not hasattr(socket, "AF_INET6"): - return False - sock = None - try: - sock = socket.socket(AF_INET6, SOCK_STREAM) - sock.bind(("::1", 0)) - except (socket.error, socket.gaierror): - return False - else: - return True - finally: - if sock is not None: - sock.close() - - -if WINDOWS: - def get_winver(): - wv = sys.getwindowsversion() - if hasattr(wv, 'service_pack_major'): # python >= 2.7 - sp = wv.service_pack_major or 0 - else: - r = re.search("\s\d$", wv[4]) - if r: - sp = int(r.group(0)) - else: - sp = 0 - return (wv[0], wv[1], sp) - - -class ThreadTask(threading.Thread): - """A thread object used for running process thread tests.""" - - def __init__(self): - threading.Thread.__init__(self) - self._running = False - self._interval = None - self._flag = threading.Event() - - def __repr__(self): - name = self.__class__.__name__ - return '<%s running=%s at %#x>' % (name, self._running, id(self)) - - def start(self, interval=0.001): - """Start thread and keep it running until an explicit - stop() request. Polls for shutdown every 'timeout' seconds. - """ - if self._running: - raise ValueError("already started") - self._interval = interval - threading.Thread.start(self) - self._flag.wait() - - def run(self): - self._running = True - self._flag.set() - while self._running: - time.sleep(self._interval) - - def stop(self): - """Stop thread execution and and waits until it is stopped.""" - if not self._running: - raise ValueError("already stopped") - self._running = False - self.join() - - -# =================================================================== -# --- System-related API tests -# =================================================================== - -class TestSystemAPIs(unittest.TestCase): - """Tests for system-related APIs.""" - - def setUp(self): - safe_remove(TESTFN) - - def tearDown(self): - reap_children() - - def test_process_iter(self): - self.assertIn(os.getpid(), [x.pid for x in psutil.process_iter()]) - sproc = get_test_subprocess() - self.assertIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertNotIn(sproc.pid, [x.pid for x in psutil.process_iter()]) - - def test_wait_procs(self): - def callback(p): - l.append(p.pid) - - l = [] - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - self.assertRaises(ValueError, psutil.wait_procs, procs, timeout=-1) - self.assertRaises(TypeError, psutil.wait_procs, procs, callback=1) - t = time.time() - gone, alive = psutil.wait_procs(procs, timeout=0.01, callback=callback) - - self.assertLess(time.time() - t, 0.5) - self.assertEqual(gone, []) - self.assertEqual(len(alive), 3) - self.assertEqual(l, []) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_before_failing(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 1) - self.assertEqual(len(alive), 2) - return gone, alive - - sproc3.terminate() - gone, alive = test(procs, callback) - self.assertIn(sproc3.pid, [x.pid for x in gone]) - if POSIX: - self.assertEqual(gone.pop().returncode, signal.SIGTERM) - else: - self.assertEqual(gone.pop().returncode, 1) - self.assertEqual(l, [sproc3.pid]) - for p in alive: - self.assertFalse(hasattr(p, 'returncode')) - - @retry_before_failing(30) - def test(procs, callback): - gone, alive = psutil.wait_procs(procs, timeout=0.03, - callback=callback) - self.assertEqual(len(gone), 3) - self.assertEqual(len(alive), 0) - return gone, alive - - sproc1.terminate() - sproc2.terminate() - gone, alive = test(procs, callback) - self.assertEqual(set(l), set([sproc1.pid, sproc2.pid, sproc3.pid])) - for p in gone: - self.assertTrue(hasattr(p, 'returncode')) - - def test_wait_procs_no_timeout(self): - sproc1 = get_test_subprocess() - sproc2 = get_test_subprocess() - sproc3 = get_test_subprocess() - procs = [psutil.Process(x.pid) for x in (sproc1, sproc2, sproc3)] - for p in procs: - p.terminate() - gone, alive = psutil.wait_procs(procs) - - def test_boot_time(self): - bt = psutil.boot_time() - self.assertIsInstance(bt, float) - self.assertGreater(bt, 0) - self.assertLess(bt, time.time()) - - @unittest.skipUnless(POSIX, 'posix only') - def test_PAGESIZE(self): - # pagesize is used internally to perform different calculations - # and it's determined by using SC_PAGE_SIZE; make sure - # getpagesize() returns the same value. - import resource - self.assertEqual(os.sysconf("SC_PAGE_SIZE"), resource.getpagesize()) - - def test_virtual_memory(self): - mem = psutil.virtual_memory() - assert mem.total > 0, mem - assert mem.available > 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.used > 0, mem - assert mem.free >= 0, mem - for name in mem._fields: - value = getattr(mem, name) - if name != 'percent': - self.assertIsInstance(value, (int, long)) - if name != 'total': - if not value >= 0: - self.fail("%r < 0 (%s)" % (name, value)) - if value > mem.total: - self.fail("%r > total (total=%s, %s=%s)" - % (name, mem.total, name, value)) - - def test_swap_memory(self): - mem = psutil.swap_memory() - assert mem.total >= 0, mem - assert mem.used >= 0, mem - if mem.total > 0: - # likely a system with no swap partition - assert mem.free > 0, mem - else: - assert mem.free == 0, mem - assert 0 <= mem.percent <= 100, mem - assert mem.sin >= 0, mem - assert mem.sout >= 0, mem - - def test_pid_exists(self): - sproc = get_test_subprocess(wait=True) - self.assertTrue(psutil.pid_exists(sproc.pid)) - p = psutil.Process(sproc.pid) - p.kill() - p.wait() - self.assertFalse(psutil.pid_exists(sproc.pid)) - self.assertFalse(psutil.pid_exists(-1)) - self.assertEqual(psutil.pid_exists(0), 0 in psutil.pids()) - # pid 0 - psutil.pid_exists(0) == 0 in psutil.pids() - - def test_pid_exists_2(self): - reap_children() - pids = psutil.pids() - for pid in pids: - try: - assert psutil.pid_exists(pid) - except AssertionError: - # in case the process disappeared in meantime fail only - # if it is no longer in psutil.pids() - time.sleep(.1) - if pid in psutil.pids(): - self.fail(pid) - pids = range(max(pids) + 5000, max(pids) + 6000) - for pid in pids: - self.assertFalse(psutil.pid_exists(pid), msg=pid) - - def test_pids(self): - plist = [x.pid for x in psutil.process_iter()] - pidlist = psutil.pids() - self.assertEqual(plist.sort(), pidlist.sort()) - # make sure every pid is unique - self.assertEqual(len(pidlist), len(set(pidlist))) - - def test_test(self): - # test for psutil.test() function - stdout = sys.stdout - sys.stdout = DEVNULL - try: - psutil.test() - finally: - sys.stdout = stdout - - def test_cpu_count(self): - logical = psutil.cpu_count() - self.assertEqual(logical, len(psutil.cpu_times(percpu=True))) - self.assertGreaterEqual(logical, 1) - # - if LINUX: - with open("/proc/cpuinfo") as fd: - cpuinfo_data = fd.read() - if "physical id" not in cpuinfo_data: - raise unittest.SkipTest("cpuinfo doesn't include physical id") - physical = psutil.cpu_count(logical=False) - self.assertGreaterEqual(physical, 1) - self.assertGreaterEqual(logical, physical) - - def test_sys_cpu_times(self): - total = 0 - times = psutil.cpu_times() - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - if not WINDOWS: - # CPU times are always supposed to increase over time or - # remain the same but never go backwards, see: - # https://github.com/giampaolo/psutil/issues/392 - last = psutil.cpu_times() - for x in range(100): - new = psutil.cpu_times() - for field in new._fields: - new_t = getattr(new, field) - last_t = getattr(last, field) - self.assertGreaterEqual(new_t, last_t, - msg="%s %s" % (new_t, last_t)) - last = new - - def test_sys_cpu_times2(self): - t1 = sum(psutil.cpu_times()) - time.sleep(0.1) - t2 = sum(psutil.cpu_times()) - difference = t2 - t1 - if not difference >= 0.05: - self.fail("difference %s" % difference) - - def test_sys_per_cpu_times(self): - for times in psutil.cpu_times(percpu=True): - total = 0 - sum(times) - for cp_time in times: - self.assertIsInstance(cp_time, float) - self.assertGreaterEqual(cp_time, 0.0) - total += cp_time - self.assertEqual(total, sum(times)) - str(times) - self.assertEqual(len(psutil.cpu_times(percpu=True)[0]), - len(psutil.cpu_times(percpu=False))) - - # Note: in theory CPU times are always supposed to increase over - # time or remain the same but never go backwards. In practice - # sometimes this is not the case. - # This issue seemd to be afflict Windows: - # https://github.com/giampaolo/psutil/issues/392 - # ...but it turns out also Linux (rarely) behaves the same. - # last = psutil.cpu_times(percpu=True) - # for x in range(100): - # new = psutil.cpu_times(percpu=True) - # for index in range(len(new)): - # newcpu = new[index] - # lastcpu = last[index] - # for field in newcpu._fields: - # new_t = getattr(newcpu, field) - # last_t = getattr(lastcpu, field) - # self.assertGreaterEqual( - # new_t, last_t, msg="%s %s" % (lastcpu, newcpu)) - # last = new - - def test_sys_per_cpu_times_2(self): - tot1 = psutil.cpu_times(percpu=True) - stop_at = time.time() + 0.1 - while True: - if time.time() >= stop_at: - break - tot2 = psutil.cpu_times(percpu=True) - for t1, t2 in zip(tot1, tot2): - t1, t2 = sum(t1), sum(t2) - difference = t2 - t1 - if difference >= 0.05: - return - self.fail() - - def _test_cpu_percent(self, percent, last_ret, new_ret): - try: - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - self.assertIsNot(percent, -0.0) - self.assertLessEqual(percent, 100.0 * psutil.cpu_count()) - except AssertionError as err: - raise AssertionError("\n%s\nlast=%s\nnew=%s" % ( - err, pprint.pformat(last_ret), pprint.pformat(new_ret))) - - def test_sys_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_percent(interval=None) - self._test_cpu_percent(new, last, new) - last = new - - def test_sys_per_cpu_percent(self): - last = psutil.cpu_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_percent(interval=None, percpu=True) - for percent in new: - self._test_cpu_percent(percent, last, new) - last = new - - def test_sys_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001) - for x in range(100): - new = psutil.cpu_times_percent(interval=None) - for percent in new: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(new), last, new) - last = new - - def test_sys_per_cpu_times_percent(self): - last = psutil.cpu_times_percent(interval=0.001, percpu=True) - self.assertEqual(len(last), psutil.cpu_count()) - for x in range(100): - new = psutil.cpu_times_percent(interval=None, percpu=True) - for cpu in new: - for percent in cpu: - self._test_cpu_percent(percent, last, new) - self._test_cpu_percent(sum(cpu), last, new) - last = new - - def test_sys_per_cpu_times_percent_negative(self): - # see: https://github.com/giampaolo/psutil/issues/645 - psutil.cpu_times_percent(percpu=True) - zero_times = [x._make([0 for x in range(len(x._fields))]) - for x in psutil.cpu_times(percpu=True)] - with mock.patch('psutil.cpu_times', return_value=zero_times): - for cpu in psutil.cpu_times_percent(percpu=True): - for percent in cpu: - self._test_cpu_percent(percent, None, None) - - @unittest.skipIf(POSIX and not hasattr(os, 'statvfs'), - "os.statvfs() function not available on this platform") - def test_disk_usage(self): - usage = psutil.disk_usage(os.getcwd()) - assert usage.total > 0, usage - assert usage.used > 0, usage - assert usage.free > 0, usage - assert usage.total > usage.used, usage - assert usage.total > usage.free, usage - assert 0 <= usage.percent <= 100, usage.percent - if hasattr(shutil, 'disk_usage'): - # py >= 3.3, see: http://bugs.python.org/issue12442 - shutil_usage = shutil.disk_usage(os.getcwd()) - tolerance = 5 * 1024 * 1024 # 5MB - self.assertEqual(usage.total, shutil_usage.total) - self.assertAlmostEqual(usage.free, shutil_usage.free, - delta=tolerance) - self.assertAlmostEqual(usage.used, shutil_usage.used, - delta=tolerance) - - # if path does not exist OSError ENOENT is expected across - # all platforms - fname = tempfile.mktemp() - try: - psutil.disk_usage(fname) - except OSError as err: - if err.args[0] != errno.ENOENT: - raise - else: - self.fail("OSError not raised") - - @unittest.skipIf(POSIX and not hasattr(os, 'statvfs'), - "os.statvfs() function not available on this platform") - def test_disk_usage_unicode(self): - # see: https://github.com/giampaolo/psutil/issues/416 - # XXX this test is not really reliable as it always fails on - # Python 3.X (2.X is fine) - try: - safe_rmdir(TESTFN_UNICODE) - os.mkdir(TESTFN_UNICODE) - psutil.disk_usage(TESTFN_UNICODE) - safe_rmdir(TESTFN_UNICODE) - except UnicodeEncodeError: - pass - - @unittest.skipIf(POSIX and not hasattr(os, 'statvfs'), - "os.statvfs() function not available on this platform") - @unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis") - def test_disk_partitions(self): - # all = False - ls = psutil.disk_partitions(all=False) - # on travis we get: - # self.assertEqual(p.cpu_affinity(), [n]) - # AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, 7,... != [0] - self.assertTrue(ls, msg=ls) - for disk in ls: - if WINDOWS and 'cdrom' in disk.opts: - continue - if not POSIX: - assert os.path.exists(disk.device), disk - else: - # we cannot make any assumption about this, see: - # http://goo.gl/p9c43 - disk.device - if SUNOS: - # on solaris apparently mount points can also be files - assert os.path.exists(disk.mountpoint), disk - else: - assert os.path.isdir(disk.mountpoint), disk - assert disk.fstype, disk - self.assertIsInstance(disk.opts, str) - - # all = True - ls = psutil.disk_partitions(all=True) - self.assertTrue(ls, msg=ls) - for disk in psutil.disk_partitions(all=True): - if not WINDOWS: - try: - os.stat(disk.mountpoint) - except OSError as err: - # http://mail.python.org/pipermail/python-dev/ - # 2012-June/120787.html - if err.errno not in (errno.EPERM, errno.EACCES): - raise - else: - if SUNOS: - # on solaris apparently mount points can also be files - assert os.path.exists(disk.mountpoint), disk - else: - assert os.path.isdir(disk.mountpoint), disk - self.assertIsInstance(disk.fstype, str) - self.assertIsInstance(disk.opts, str) - - def find_mount_point(path): - path = os.path.abspath(path) - while not os.path.ismount(path): - path = os.path.dirname(path) - return path - - mount = find_mount_point(__file__) - mounts = [x.mountpoint for x in psutil.disk_partitions(all=True)] - self.assertIn(mount, mounts) - psutil.disk_usage(mount) - - @skip_on_access_denied() - def test_net_connections(self): - def check(cons, families, types_): - for conn in cons: - self.assertIn(conn.family, families, msg=conn) - if conn.family != getattr(socket, 'AF_UNIX', object()): - self.assertIn(conn.type, types_, msg=conn) - - from psutil._common import conn_tmap - for kind, groups in conn_tmap.items(): - if SUNOS and kind == 'unix': - continue - families, types_ = groups - cons = psutil.net_connections(kind) - self.assertEqual(len(cons), len(set(cons))) - check(cons, families, types_) - - def test_net_io_counters(self): - def check_ntuple(nt): - self.assertEqual(nt[0], nt.bytes_sent) - self.assertEqual(nt[1], nt.bytes_recv) - self.assertEqual(nt[2], nt.packets_sent) - self.assertEqual(nt[3], nt.packets_recv) - self.assertEqual(nt[4], nt.errin) - self.assertEqual(nt[5], nt.errout) - self.assertEqual(nt[6], nt.dropin) - self.assertEqual(nt[7], nt.dropout) - assert nt.bytes_sent >= 0, nt - assert nt.bytes_recv >= 0, nt - assert nt.packets_sent >= 0, nt - assert nt.packets_recv >= 0, nt - assert nt.errin >= 0, nt - assert nt.errout >= 0, nt - assert nt.dropin >= 0, nt - assert nt.dropout >= 0, nt - - ret = psutil.net_io_counters(pernic=False) - check_ntuple(ret) - ret = psutil.net_io_counters(pernic=True) - self.assertNotEqual(ret, []) - for key in ret: - self.assertTrue(key) - check_ntuple(ret[key]) - - def test_net_if_addrs(self): - nics = psutil.net_if_addrs() - assert nics, nics - - # Not reliable on all platforms (net_if_addrs() reports more - # interfaces). - # self.assertEqual(sorted(nics.keys()), - # sorted(psutil.net_io_counters(pernic=True).keys())) - - families = set([socket.AF_INET, AF_INET6, psutil.AF_LINK]) - for nic, addrs in nics.items(): - self.assertEqual(len(set(addrs)), len(addrs)) - for addr in addrs: - self.assertIsInstance(addr.family, int) - self.assertIsInstance(addr.address, str) - self.assertIsInstance(addr.netmask, (str, type(None))) - self.assertIsInstance(addr.broadcast, (str, type(None))) - self.assertIn(addr.family, families) - if sys.version_info >= (3, 4): - self.assertIsInstance(addr.family, enum.IntEnum) - if addr.family == socket.AF_INET: - s = socket.socket(addr.family) - with contextlib.closing(s): - s.bind((addr.address, 0)) - elif addr.family == socket.AF_INET6: - info = socket.getaddrinfo( - addr.address, 0, socket.AF_INET6, socket.SOCK_STREAM, - 0, socket.AI_PASSIVE)[0] - af, socktype, proto, canonname, sa = info - s = socket.socket(af, socktype, proto) - with contextlib.closing(s): - s.bind(sa) - for ip in (addr.address, addr.netmask, addr.broadcast): - if ip is not None: - # TODO: skip AF_INET6 for now because I get: - # AddressValueError: Only hex digits permitted in - # u'c6f3%lxcbr0' in u'fe80::c8e0:fff:fe54:c6f3%lxcbr0' - if addr.family != AF_INET6: - check_ip_address(ip, addr.family) - - if BSD or OSX or SUNOS: - if hasattr(socket, "AF_LINK"): - self.assertEqual(psutil.AF_LINK, socket.AF_LINK) - elif LINUX: - self.assertEqual(psutil.AF_LINK, socket.AF_PACKET) - elif WINDOWS: - self.assertEqual(psutil.AF_LINK, -1) - - @unittest.skipIf(TRAVIS, "EPERM on travis") - def test_net_if_stats(self): - nics = psutil.net_if_stats() - assert nics, nics - all_duplexes = (psutil.NIC_DUPLEX_FULL, - psutil.NIC_DUPLEX_HALF, - psutil.NIC_DUPLEX_UNKNOWN) - for nic, stats in nics.items(): - isup, duplex, speed, mtu = stats - self.assertIsInstance(isup, bool) - self.assertIn(duplex, all_duplexes) - self.assertIn(duplex, all_duplexes) - self.assertGreaterEqual(speed, 0) - self.assertGreaterEqual(mtu, 0) - - @unittest.skipIf(LINUX and not os.path.exists('/proc/diskstats'), - '/proc/diskstats not available on this linux version') - @unittest.skipIf(APPVEYOR, - "can't find any physical disk on Appveyor") - def test_disk_io_counters(self): - def check_ntuple(nt): - self.assertEqual(nt[0], nt.read_count) - self.assertEqual(nt[1], nt.write_count) - self.assertEqual(nt[2], nt.read_bytes) - self.assertEqual(nt[3], nt.write_bytes) - self.assertEqual(nt[4], nt.read_time) - self.assertEqual(nt[5], nt.write_time) - assert nt.read_count >= 0, nt - assert nt.write_count >= 0, nt - assert nt.read_bytes >= 0, nt - assert nt.write_bytes >= 0, nt - assert nt.read_time >= 0, nt - assert nt.write_time >= 0, nt - - ret = psutil.disk_io_counters(perdisk=False) - check_ntuple(ret) - ret = psutil.disk_io_counters(perdisk=True) - # make sure there are no duplicates - self.assertEqual(len(ret), len(set(ret))) - for key in ret: - assert key, key - check_ntuple(ret[key]) - if LINUX and key[-1].isdigit(): - # if 'sda1' is listed 'sda' shouldn't, see: - # https://github.com/giampaolo/psutil/issues/338 - while key[-1].isdigit(): - key = key[:-1] - self.assertNotIn(key, ret.keys()) - - def test_users(self): - users = psutil.users() - if not APPVEYOR: - self.assertNotEqual(users, []) - for user in users: - assert user.name, user - user.terminal - user.host - assert user.started > 0.0, user - datetime.datetime.fromtimestamp(user.started) - - -# =================================================================== -# --- psutil.Process class tests -# =================================================================== - -class TestProcess(unittest.TestCase): - """Tests for psutil.Process class.""" - - def setUp(self): - safe_remove(TESTFN) - - def tearDown(self): - reap_children() - - def test_pid(self): - self.assertEqual(psutil.Process().pid, os.getpid()) - sproc = get_test_subprocess() - self.assertEqual(psutil.Process(sproc.pid).pid, sproc.pid) - - def test_kill(self): - sproc = get_test_subprocess(wait=True) - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.kill() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, signal.SIGKILL) - - def test_terminate(self): - sproc = get_test_subprocess(wait=True) - test_pid = sproc.pid - p = psutil.Process(test_pid) - p.terminate() - sig = p.wait() - self.assertFalse(psutil.pid_exists(test_pid)) - if POSIX: - self.assertEqual(sig, signal.SIGTERM) - - def test_send_signal(self): - sig = signal.SIGKILL if POSIX else signal.SIGTERM - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - exit_sig = p.wait() - self.assertFalse(psutil.pid_exists(p.pid)) - if POSIX: - self.assertEqual(exit_sig, sig) - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.ESRCH, "")) as fun: - with self.assertRaises(psutil.NoSuchProcess): - p.send_signal(sig) - assert fun.called - # - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.send_signal(sig) - with mock.patch('psutil.os.kill', - side_effect=OSError(errno.EPERM, "")) as fun: - with self.assertRaises(psutil.AccessDenied): - p.send_signal(sig) - assert fun.called - - def test_wait(self): - # check exit code signal - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.kill() - code = p.wait() - if POSIX: - self.assertEqual(code, signal.SIGKILL) - else: - self.assertEqual(code, 0) - self.assertFalse(p.is_running()) - - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - code = p.wait() - if POSIX: - self.assertEqual(code, signal.SIGTERM) - else: - self.assertEqual(code, 0) - self.assertFalse(p.is_running()) - - # check sys.exit() code - code = "import time, sys; time.sleep(0.01); sys.exit(5);" - sproc = get_test_subprocess([PYTHON, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertFalse(p.is_running()) - - # Test wait() issued twice. - # It is not supposed to raise NSP when the process is gone. - # On UNIX this should return None, on Windows it should keep - # returning the exit code. - sproc = get_test_subprocess([PYTHON, "-c", code]) - p = psutil.Process(sproc.pid) - self.assertEqual(p.wait(), 5) - self.assertIn(p.wait(), (5, None)) - - # test timeout - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.name() - self.assertRaises(psutil.TimeoutExpired, p.wait, 0.01) - - # timeout < 0 not allowed - self.assertRaises(ValueError, p.wait, -1) - - # XXX why is this skipped on Windows? - @unittest.skipUnless(POSIX, 'skipped on Windows') - def test_wait_non_children(self): - # test wait() against processes which are not our children - code = "import sys;" - code += "from subprocess import Popen, PIPE;" - code += "cmd = ['%s', '-c', 'import time; time.sleep(60)'];" % PYTHON - code += "sp = Popen(cmd, stdout=PIPE);" - code += "sys.stdout.write(str(sp.pid));" - sproc = get_test_subprocess([PYTHON, "-c", code], - stdout=subprocess.PIPE) - grandson_pid = int(sproc.stdout.read()) - grandson_proc = psutil.Process(grandson_pid) - try: - self.assertRaises(psutil.TimeoutExpired, grandson_proc.wait, 0.01) - grandson_proc.kill() - ret = grandson_proc.wait() - self.assertEqual(ret, None) - finally: - if grandson_proc.is_running(): - grandson_proc.kill() - grandson_proc.wait() - - def test_wait_timeout_0(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertRaises(psutil.TimeoutExpired, p.wait, 0) - p.kill() - stop_at = time.time() + 2 - while True: - try: - code = p.wait(0) - except psutil.TimeoutExpired: - if time.time() >= stop_at: - raise - else: - break - if POSIX: - self.assertEqual(code, signal.SIGKILL) - else: - self.assertEqual(code, 0) - self.assertFalse(p.is_running()) - - def test_cpu_percent(self): - p = psutil.Process() - p.cpu_percent(interval=0.001) - p.cpu_percent(interval=0.001) - for x in range(100): - percent = p.cpu_percent(interval=None) - self.assertIsInstance(percent, float) - self.assertGreaterEqual(percent, 0.0) - if not POSIX: - self.assertLessEqual(percent, 100.0) - else: - self.assertGreaterEqual(percent, 0.0) - - def test_cpu_times(self): - times = psutil.Process().cpu_times() - assert (times.user > 0.0) or (times.system > 0.0), times - # make sure returned values can be pretty printed with strftime - time.strftime("%H:%M:%S", time.localtime(times.user)) - time.strftime("%H:%M:%S", time.localtime(times.system)) - - # Test Process.cpu_times() against os.times() - # os.times() is broken on Python 2.6 - # http://bugs.python.org/issue1040026 - # XXX fails on OSX: not sure if it's for os.times(). We should - # try this with Python 2.7 and re-enable the test. - - @unittest.skipUnless(sys.version_info > (2, 6, 1) and not OSX, - 'os.times() is not reliable on this Python version') - def test_cpu_times2(self): - user_time, kernel_time = psutil.Process().cpu_times() - utime, ktime = os.times()[:2] - - # Use os.times()[:2] as base values to compare our results - # using a tolerance of +/- 0.1 seconds. - # It will fail if the difference between the values is > 0.1s. - if (max([user_time, utime]) - min([user_time, utime])) > 0.1: - self.fail("expected: %s, found: %s" % (utime, user_time)) - - if (max([kernel_time, ktime]) - min([kernel_time, ktime])) > 0.1: - self.fail("expected: %s, found: %s" % (ktime, kernel_time)) - - def test_create_time(self): - sproc = get_test_subprocess(wait=True) - now = time.time() - p = psutil.Process(sproc.pid) - create_time = p.create_time() - - # Use time.time() as base value to compare our result using a - # tolerance of +/- 1 second. - # It will fail if the difference between the values is > 2s. - difference = abs(create_time - now) - if difference > 2: - self.fail("expected: %s, found: %s, difference: %s" - % (now, create_time, difference)) - - # make sure returned value can be pretty printed with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(p.create_time())) - - @unittest.skipIf(WINDOWS, 'Windows only') - def test_terminal(self): - terminal = psutil.Process().terminal() - if sys.stdin.isatty(): - self.assertEqual(terminal, sh('tty')) - else: - assert terminal, repr(terminal) - - @unittest.skipUnless(LINUX or BSD or WINDOWS, - 'not available on this platform') - @skip_on_not_implemented(only_if=LINUX) - def test_io_counters(self): - p = psutil.Process() - # test reads - io1 = p.io_counters() - with open(PYTHON, 'rb') as f: - f.read() - io2 = p.io_counters() - if not BSD: - assert io2.read_count > io1.read_count, (io1, io2) - self.assertEqual(io2.write_count, io1.write_count) - assert io2.read_bytes >= io1.read_bytes, (io1, io2) - assert io2.write_bytes >= io1.write_bytes, (io1, io2) - # test writes - io1 = p.io_counters() - with tempfile.TemporaryFile(prefix=TESTFILE_PREFIX) as f: - if PY3: - f.write(bytes("x" * 1000000, 'ascii')) - else: - f.write("x" * 1000000) - io2 = p.io_counters() - assert io2.write_count >= io1.write_count, (io1, io2) - assert io2.write_bytes >= io1.write_bytes, (io1, io2) - assert io2.read_count >= io1.read_count, (io1, io2) - assert io2.read_bytes >= io1.read_bytes, (io1, io2) - - @unittest.skipUnless(LINUX or (WINDOWS and get_winver() >= WIN_VISTA), - 'Linux and Windows Vista only') - @unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis") - def test_ionice(self): - if LINUX: - from psutil import (IOPRIO_CLASS_NONE, IOPRIO_CLASS_RT, - IOPRIO_CLASS_BE, IOPRIO_CLASS_IDLE) - self.assertEqual(IOPRIO_CLASS_NONE, 0) - self.assertEqual(IOPRIO_CLASS_RT, 1) - self.assertEqual(IOPRIO_CLASS_BE, 2) - self.assertEqual(IOPRIO_CLASS_IDLE, 3) - p = psutil.Process() - try: - p.ionice(2) - ioclass, value = p.ionice() - if enum is not None: - self.assertIsInstance(ioclass, enum.IntEnum) - self.assertEqual(ioclass, 2) - self.assertEqual(value, 4) - # - p.ionice(3) - ioclass, value = p.ionice() - self.assertEqual(ioclass, 3) - self.assertEqual(value, 0) - # - p.ionice(2, 0) - ioclass, value = p.ionice() - self.assertEqual(ioclass, 2) - self.assertEqual(value, 0) - p.ionice(2, 7) - ioclass, value = p.ionice() - self.assertEqual(ioclass, 2) - self.assertEqual(value, 7) - # - self.assertRaises(ValueError, p.ionice, 2, 10) - self.assertRaises(ValueError, p.ionice, 2, -1) - self.assertRaises(ValueError, p.ionice, 4) - self.assertRaises(TypeError, p.ionice, 2, "foo") - self.assertRaisesRegexp( - ValueError, "can't specify value with IOPRIO_CLASS_NONE", - p.ionice, psutil.IOPRIO_CLASS_NONE, 1) - self.assertRaisesRegexp( - ValueError, "can't specify value with IOPRIO_CLASS_IDLE", - p.ionice, psutil.IOPRIO_CLASS_IDLE, 1) - self.assertRaisesRegexp( - ValueError, "'ioclass' argument must be specified", - p.ionice, value=1) - finally: - p.ionice(IOPRIO_CLASS_NONE) - else: - p = psutil.Process() - original = p.ionice() - self.assertIsInstance(original, int) - try: - value = 0 # very low - if original == value: - value = 1 # low - p.ionice(value) - self.assertEqual(p.ionice(), value) - finally: - p.ionice(original) - # - self.assertRaises(ValueError, p.ionice, 3) - self.assertRaises(TypeError, p.ionice, 2, 1) - - @unittest.skipUnless(LINUX and RLIMIT_SUPPORT, - "only available on Linux >= 2.6.36") - def test_rlimit_get(self): - import resource - p = psutil.Process(os.getpid()) - names = [x for x in dir(psutil) if x.startswith('RLIMIT')] - assert names, names - for name in names: - value = getattr(psutil, name) - self.assertGreaterEqual(value, 0) - if name in dir(resource): - self.assertEqual(value, getattr(resource, name)) - self.assertEqual(p.rlimit(value), resource.getrlimit(value)) - else: - ret = p.rlimit(value) - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - @unittest.skipUnless(LINUX and RLIMIT_SUPPORT, - "only available on Linux >= 2.6.36") - def test_rlimit_set(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5)) - self.assertEqual(p.rlimit(psutil.RLIMIT_NOFILE), (5, 5)) - # If pid is 0 prlimit() applies to the calling process and - # we don't want that. - with self.assertRaises(ValueError): - psutil._psplatform.Process(0).rlimit(0) - with self.assertRaises(ValueError): - p.rlimit(psutil.RLIMIT_NOFILE, (5, 5, 5)) - - def test_num_threads(self): - # on certain platforms such as Linux we might test for exact - # thread number, since we always have with 1 thread per process, - # but this does not apply across all platforms (OSX, Windows) - p = psutil.Process() - step1 = p.num_threads() - - thread = ThreadTask() - thread.start() - try: - step2 = p.num_threads() - self.assertEqual(step2, step1 + 1) - thread.stop() - finally: - if thread._running: - thread.stop() - - @unittest.skipUnless(WINDOWS, 'Windows only') - def test_num_handles(self): - # a better test is done later into test/_windows.py - p = psutil.Process() - self.assertGreater(p.num_handles(), 0) - - def test_threads(self): - p = psutil.Process() - step1 = p.threads() - - thread = ThreadTask() - thread.start() - - try: - step2 = p.threads() - self.assertEqual(len(step2), len(step1) + 1) - # on Linux, first thread id is supposed to be this process - if LINUX: - self.assertEqual(step2[0].id, os.getpid()) - athread = step2[0] - # test named tuple - self.assertEqual(athread.id, athread[0]) - self.assertEqual(athread.user_time, athread[1]) - self.assertEqual(athread.system_time, athread[2]) - # test num threads - thread.stop() - finally: - if thread._running: - thread.stop() - - def test_memory_info(self): - p = psutil.Process() - - # step 1 - get a base value to compare our results - rss1, vms1 = p.memory_info() - percent1 = p.memory_percent() - self.assertGreater(rss1, 0) - self.assertGreater(vms1, 0) - - # step 2 - allocate some memory - memarr = [None] * 1500000 - - rss2, vms2 = p.memory_info() - percent2 = p.memory_percent() - # make sure that the memory usage bumped up - self.assertGreater(rss2, rss1) - self.assertGreaterEqual(vms2, vms1) # vms might be equal - self.assertGreater(percent2, percent1) - del memarr - - # def test_memory_info_ex(self): - # # tested later in fetch all test suite - - def test_memory_maps(self): - p = psutil.Process() - maps = p.memory_maps() - paths = [x for x in maps] - self.assertEqual(len(paths), len(set(paths))) - ext_maps = p.memory_maps(grouped=False) - - for nt in maps: - if not nt.path.startswith('['): - assert os.path.isabs(nt.path), nt.path - if POSIX: - assert os.path.exists(nt.path), nt.path - else: - # XXX - On Windows we have this strange behavior with - # 64 bit dlls: they are visible via explorer but cannot - # be accessed via os.stat() (wtf?). - if '64' not in os.path.basename(nt.path): - assert os.path.exists(nt.path), nt.path - for nt in ext_maps: - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - continue - elif fname in ('addr', 'perms'): - assert value, value - else: - self.assertIsInstance(value, (int, long)) - assert value >= 0, value - - def test_memory_percent(self): - p = psutil.Process() - self.assertGreater(p.memory_percent(), 0.0) - - def test_is_running(self): - sproc = get_test_subprocess(wait=True) - p = psutil.Process(sproc.pid) - assert p.is_running() - assert p.is_running() - p.kill() - p.wait() - assert not p.is_running() - assert not p.is_running() - - def test_exe(self): - sproc = get_test_subprocess(wait=True) - exe = psutil.Process(sproc.pid).exe() - try: - self.assertEqual(exe, PYTHON) - except AssertionError: - if WINDOWS and len(exe) == len(PYTHON): - # on Windows we don't care about case sensitivity - self.assertEqual(exe.lower(), PYTHON.lower()) - else: - # certain platforms such as BSD are more accurate returning: - # "/usr/local/bin/python2.7" - # ...instead of: - # "/usr/local/bin/python" - # We do not want to consider this difference in accuracy - # an error. - ver = "%s.%s" % (sys.version_info[0], sys.version_info[1]) - self.assertEqual(exe.replace(ver, ''), PYTHON.replace(ver, '')) - - def test_cmdline(self): - cmdline = [PYTHON, "-c", "import time; time.sleep(60)"] - sproc = get_test_subprocess(cmdline, wait=True) - self.assertEqual(' '.join(psutil.Process(sproc.pid).cmdline()), - ' '.join(cmdline)) - - def test_name(self): - sproc = get_test_subprocess(PYTHON, wait=True) - name = psutil.Process(sproc.pid).name().lower() - pyexe = os.path.basename(os.path.realpath(sys.executable)).lower() - assert pyexe.startswith(name), (pyexe, name) - - @unittest.skipUnless(POSIX, "posix only") - # TODO: add support for other compilers - @unittest.skipUnless(which("gcc"), "gcc not available") - def test_prog_w_funky_name(self): - # Test that name(), exe() and cmdline() correctly handle programs - # with funky chars such as spaces and ")", see: - # https://github.com/giampaolo/psutil/issues/628 - funky_name = "/tmp/foo bar )" - _, c_file = tempfile.mkstemp(prefix='psutil-', suffix='.c', dir="/tmp") - self.addCleanup(lambda: safe_remove(c_file)) - self.addCleanup(lambda: safe_remove(funky_name)) - with open(c_file, "w") as f: - f.write("void main() { pause(); }") - subprocess.check_call(["gcc", c_file, "-o", funky_name]) - sproc = get_test_subprocess( - [funky_name, "arg1", "arg2", "", "arg3", ""]) - p = psutil.Process(sproc.pid) - # ...in order to try to prevent occasional failures on travis - wait_for_pid(p.pid) - self.assertEqual(p.name(), "foo bar )") - self.assertEqual(p.exe(), "/tmp/foo bar )") - self.assertEqual( - p.cmdline(), ["/tmp/foo bar )", "arg1", "arg2", "", "arg3", ""]) - - @unittest.skipUnless(POSIX, 'posix only') - def test_uids(self): - p = psutil.Process() - real, effective, saved = p.uids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getuid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.geteuid()) - # no such thing as os.getsuid() ("saved" uid), but starting - # from python 2.7 we have os.getresuid()[2] - if hasattr(os, "getresuid"): - self.assertEqual(saved, os.getresuid()[2]) - - @unittest.skipUnless(POSIX, 'posix only') - def test_gids(self): - p = psutil.Process() - real, effective, saved = p.gids() - # os.getuid() refers to "real" uid - self.assertEqual(real, os.getgid()) - # os.geteuid() refers to "effective" uid - self.assertEqual(effective, os.getegid()) - # no such thing as os.getsuid() ("saved" uid), but starting - # from python 2.7 we have os.getresgid()[2] - if hasattr(os, "getresuid"): - self.assertEqual(saved, os.getresgid()[2]) - - def test_nice(self): - p = psutil.Process() - self.assertRaises(TypeError, p.nice, "str") - if WINDOWS: - try: - init = p.nice() - if sys.version_info > (3, 4): - self.assertIsInstance(init, enum.IntEnum) - else: - self.assertIsInstance(init, int) - self.assertEqual(init, psutil.NORMAL_PRIORITY_CLASS) - p.nice(psutil.HIGH_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.HIGH_PRIORITY_CLASS) - p.nice(psutil.NORMAL_PRIORITY_CLASS) - self.assertEqual(p.nice(), psutil.NORMAL_PRIORITY_CLASS) - finally: - p.nice(psutil.NORMAL_PRIORITY_CLASS) - else: - try: - first_nice = p.nice() - p.nice(1) - self.assertEqual(p.nice(), 1) - # going back to previous nice value raises - # AccessDenied on OSX - if not OSX: - p.nice(0) - self.assertEqual(p.nice(), 0) - except psutil.AccessDenied: - pass - finally: - try: - p.nice(first_nice) - except psutil.AccessDenied: - pass - - def test_status(self): - p = psutil.Process() - self.assertEqual(p.status(), psutil.STATUS_RUNNING) - - def test_username(self): - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - if POSIX: - import pwd - self.assertEqual(p.username(), pwd.getpwuid(os.getuid()).pw_name) - with mock.patch("psutil.pwd.getpwuid", - side_effect=KeyError) as fun: - p.username() == str(p.uids().real) - assert fun.called - - elif WINDOWS and 'USERNAME' in os.environ: - expected_username = os.environ['USERNAME'] - expected_domain = os.environ['USERDOMAIN'] - domain, username = p.username().split('\\') - self.assertEqual(domain, expected_domain) - self.assertEqual(username, expected_username) - else: - p.username() - - def test_cwd(self): - sproc = get_test_subprocess(wait=True) - p = psutil.Process(sproc.pid) - self.assertEqual(p.cwd(), os.getcwd()) - - def test_cwd_2(self): - cmd = [PYTHON, "-c", "import os, time; os.chdir('..'); time.sleep(60)"] - sproc = get_test_subprocess(cmd, wait=True) - p = psutil.Process(sproc.pid) - call_until(p.cwd, "ret == os.path.dirname(os.getcwd())") - - @unittest.skipUnless(WINDOWS or LINUX or BSD, - 'not available on this platform') - @unittest.skipIf(LINUX and TRAVIS, "unknown failure on travis") - def test_cpu_affinity(self): - p = psutil.Process() - initial = p.cpu_affinity() - if hasattr(os, "sched_getaffinity"): - self.assertEqual(initial, list(os.sched_getaffinity(p.pid))) - self.assertEqual(len(initial), len(set(initial))) - all_cpus = list(range(len(psutil.cpu_percent(percpu=True)))) - # setting on travis doesn't seem to work (always return all - # CPUs on get): - # AssertionError: Lists differ: [0, 1, 2, 3, 4, 5, 6, ... != [0] - for n in all_cpus: - p.cpu_affinity([n]) - self.assertEqual(p.cpu_affinity(), [n]) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # - p.cpu_affinity(all_cpus) - self.assertEqual(p.cpu_affinity(), all_cpus) - if hasattr(os, "sched_getaffinity"): - self.assertEqual(p.cpu_affinity(), - list(os.sched_getaffinity(p.pid))) - # - self.assertRaises(TypeError, p.cpu_affinity, 1) - p.cpu_affinity(initial) - # it should work with all iterables, not only lists - p.cpu_affinity(set(all_cpus)) - p.cpu_affinity(tuple(all_cpus)) - invalid_cpu = [len(psutil.cpu_times(percpu=True)) + 10] - self.assertRaises(ValueError, p.cpu_affinity, invalid_cpu) - self.assertRaises(ValueError, p.cpu_affinity, range(10000, 11000)) - self.assertRaises(TypeError, p.cpu_affinity, [0, "1"]) - - # TODO - @unittest.skipIf(BSD, "broken on BSD, see #595") - @unittest.skipIf(APPVEYOR, - "can't find any process file on Appveyor") - def test_open_files(self): - # current process - p = psutil.Process() - files = p.open_files() - self.assertFalse(TESTFN in files) - with open(TESTFN, 'w'): - # give the kernel some time to see the new file - call_until(p.open_files, "len(ret) != %i" % len(files)) - filenames = [x.path for x in p.open_files()] - self.assertIn(TESTFN, filenames) - for file in filenames: - assert os.path.isfile(file), file - - # another process - cmdline = "import time; f = open(r'%s', 'r'); time.sleep(60);" % TESTFN - sproc = get_test_subprocess([PYTHON, "-c", cmdline], wait=True) - p = psutil.Process(sproc.pid) - - for x in range(100): - filenames = [x.path for x in p.open_files()] - if TESTFN in filenames: - break - time.sleep(.01) - else: - self.assertIn(TESTFN, filenames) - for file in filenames: - assert os.path.isfile(file), file - - # TODO - @unittest.skipIf(BSD, "broken on BSD, see #595") - @unittest.skipIf(APPVEYOR, - "can't find any process file on Appveyor") - def test_open_files2(self): - # test fd and path fields - with open(TESTFN, 'w') as fileobj: - p = psutil.Process() - for path, fd in p.open_files(): - if path == fileobj.name or fd == fileobj.fileno(): - break - else: - self.fail("no file found; files=%s" % repr(p.open_files())) - self.assertEqual(path, fileobj.name) - if WINDOWS: - self.assertEqual(fd, -1) - else: - self.assertEqual(fd, fileobj.fileno()) - # test positions - ntuple = p.open_files()[0] - self.assertEqual(ntuple[0], ntuple.path) - self.assertEqual(ntuple[1], ntuple.fd) - # test file is gone - self.assertTrue(fileobj.name not in p.open_files()) - - def compare_proc_sys_cons(self, pid, proc_cons): - from psutil._common import pconn - sys_cons = [] - for c in psutil.net_connections(kind='all'): - if c.pid == pid: - sys_cons.append(pconn(*c[:-1])) - if BSD: - # on BSD all fds are set to -1 - proc_cons = [pconn(*[-1] + list(x[1:])) for x in proc_cons] - self.assertEqual(sorted(proc_cons), sorted(sys_cons)) - - @skip_on_access_denied(only_if=OSX) - def test_connections(self): - def check_conn(proc, conn, family, type, laddr, raddr, status, kinds): - all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", - "tcp6", "udp", "udp4", "udp6") - check_connection_ntuple(conn) - self.assertEqual(conn.family, family) - self.assertEqual(conn.type, type) - self.assertEqual(conn.laddr, laddr) - self.assertEqual(conn.raddr, raddr) - self.assertEqual(conn.status, status) - for kind in all_kinds: - cons = proc.connections(kind=kind) - if kind in kinds: - self.assertNotEqual(cons, []) - else: - self.assertEqual(cons, []) - # compare against system-wide connections - # XXX Solaris can't retrieve system-wide UNIX - # sockets. - if not SUNOS: - self.compare_proc_sys_cons(proc.pid, [conn]) - - tcp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_STREAM) - s.bind(('$addr', 0)) - s.listen(1) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - udp_template = textwrap.dedent(""" - import socket, time - s = socket.socket($family, socket.SOCK_DGRAM) - s.bind(('$addr', 0)) - with open('$testfn', 'w') as f: - f.write(str(s.getsockname()[:2])) - time.sleep(60) - """) - - from string import Template - testfile = os.path.basename(TESTFN) - tcp4_template = Template(tcp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - udp4_template = Template(udp_template).substitute( - family=int(AF_INET), addr="127.0.0.1", testfn=testfile) - tcp6_template = Template(tcp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - udp6_template = Template(udp_template).substitute( - family=int(AF_INET6), addr="::1", testfn=testfile) - - # launch various subprocess instantiating a socket of various - # families and types to enrich psutil results - tcp4_proc = pyrun(tcp4_template) - tcp4_addr = eval(wait_for_file(testfile)) - udp4_proc = pyrun(udp4_template) - udp4_addr = eval(wait_for_file(testfile)) - if supports_ipv6(): - tcp6_proc = pyrun(tcp6_template) - tcp6_addr = eval(wait_for_file(testfile)) - udp6_proc = pyrun(udp6_template) - udp6_addr = eval(wait_for_file(testfile)) - else: - tcp6_proc = None - udp6_proc = None - tcp6_addr = None - udp6_addr = None - - for p in psutil.Process().children(): - cons = p.connections() - self.assertEqual(len(cons), 1) - for conn in cons: - # TCP v4 - if p.pid == tcp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_STREAM, tcp4_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet4", "tcp", "tcp4")) - # UDP v4 - elif p.pid == udp4_proc.pid: - check_conn(p, conn, AF_INET, SOCK_DGRAM, udp4_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet4", "udp", "udp4")) - # TCP v6 - elif p.pid == getattr(tcp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_STREAM, tcp6_addr, (), - psutil.CONN_LISTEN, - ("all", "inet", "inet6", "tcp", "tcp6")) - # UDP v6 - elif p.pid == getattr(udp6_proc, "pid", None): - check_conn(p, conn, AF_INET6, SOCK_DGRAM, udp6_addr, (), - psutil.CONN_NONE, - ("all", "inet", "inet6", "udp", "udp6")) - - @unittest.skipUnless(hasattr(socket, 'AF_UNIX'), - 'AF_UNIX is not supported') - @skip_on_access_denied(only_if=OSX) - def test_connections_unix(self): - def check(type): - safe_remove(TESTFN) - sock = socket.socket(AF_UNIX, type) - with contextlib.closing(sock): - sock.bind(TESTFN) - cons = psutil.Process().connections(kind='unix') - conn = cons[0] - check_connection_ntuple(conn) - if conn.fd != -1: # != sunos and windows - self.assertEqual(conn.fd, sock.fileno()) - self.assertEqual(conn.family, AF_UNIX) - self.assertEqual(conn.type, type) - self.assertEqual(conn.laddr, TESTFN) - if not SUNOS: - # XXX Solaris can't retrieve system-wide UNIX - # sockets. - self.compare_proc_sys_cons(os.getpid(), cons) - - check(SOCK_STREAM) - check(SOCK_DGRAM) - - @unittest.skipUnless(hasattr(socket, "fromfd"), - 'socket.fromfd() is not availble') - @unittest.skipIf(WINDOWS or SUNOS, - 'connection fd not available on this platform') - def test_connection_fromfd(self): - with contextlib.closing(socket.socket()) as sock: - sock.bind(('localhost', 0)) - sock.listen(1) - p = psutil.Process() - for conn in p.connections(): - if conn.fd == sock.fileno(): - break - else: - self.fail("couldn't find socket fd") - dupsock = socket.fromfd(conn.fd, conn.family, conn.type) - with contextlib.closing(dupsock): - self.assertEqual(dupsock.getsockname(), conn.laddr) - self.assertNotEqual(sock.fileno(), dupsock.fileno()) - - def test_connection_constants(self): - ints = [] - strs = [] - for name in dir(psutil): - if name.startswith('CONN_'): - num = getattr(psutil, name) - str_ = str(num) - assert str_.isupper(), str_ - assert str_ not in strs, str_ - assert num not in ints, num - ints.append(num) - strs.append(str_) - if SUNOS: - psutil.CONN_IDLE - psutil.CONN_BOUND - if WINDOWS: - psutil.CONN_DELETE_TCB - - @unittest.skipUnless(POSIX, 'posix only') - def test_num_fds(self): - p = psutil.Process() - start = p.num_fds() - file = open(TESTFN, 'w') - self.addCleanup(file.close) - self.assertEqual(p.num_fds(), start + 1) - sock = socket.socket() - self.addCleanup(sock.close) - self.assertEqual(p.num_fds(), start + 2) - file.close() - sock.close() - self.assertEqual(p.num_fds(), start) - - @skip_on_not_implemented(only_if=LINUX) - def test_num_ctx_switches(self): - p = psutil.Process() - before = sum(p.num_ctx_switches()) - for x in range(500000): - after = sum(p.num_ctx_switches()) - if after > before: - return - self.fail("num ctx switches still the same after 50.000 iterations") - - def test_parent_ppid(self): - this_parent = os.getpid() - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - self.assertEqual(p.ppid(), this_parent) - self.assertEqual(p.parent().pid, this_parent) - # no other process is supposed to have us as parent - for p in psutil.process_iter(): - if p.pid == sproc.pid: - continue - self.assertTrue(p.ppid() != this_parent) - - def test_children(self): - p = psutil.Process() - self.assertEqual(p.children(), []) - self.assertEqual(p.children(recursive=True), []) - sproc = get_test_subprocess() - children1 = p.children() - children2 = p.children(recursive=True) - for children in (children1, children2): - self.assertEqual(len(children), 1) - self.assertEqual(children[0].pid, sproc.pid) - self.assertEqual(children[0].ppid(), os.getpid()) - - def test_children_recursive(self): - # here we create a subprocess which creates another one as in: - # A (parent) -> B (child) -> C (grandchild) - s = "import subprocess, os, sys, time;" - s += "PYTHON = os.path.realpath(sys.executable);" - s += "cmd = [PYTHON, '-c', 'import time; time.sleep(60);'];" - s += "subprocess.Popen(cmd);" - s += "time.sleep(60);" - get_test_subprocess(cmd=[PYTHON, "-c", s]) - p = psutil.Process() - self.assertEqual(len(p.children(recursive=False)), 1) - # give the grandchild some time to start - stop_at = time.time() + GLOBAL_TIMEOUT - while time.time() < stop_at: - children = p.children(recursive=True) - if len(children) > 1: - break - self.assertEqual(len(children), 2) - self.assertEqual(children[0].ppid(), os.getpid()) - self.assertEqual(children[1].ppid(), children[0].pid) - - def test_children_duplicates(self): - # find the process which has the highest number of children - table = collections.defaultdict(int) - for p in psutil.process_iter(): - try: - table[p.ppid()] += 1 - except psutil.Error: - pass - # this is the one, now let's make sure there are no duplicates - pid = sorted(table.items(), key=lambda x: x[1])[-1][0] - p = psutil.Process(pid) - try: - c = p.children(recursive=True) - except psutil.AccessDenied: # windows - pass - else: - self.assertEqual(len(c), len(set(c))) - - def test_suspend_resume(self): - sproc = get_test_subprocess(wait=True) - p = psutil.Process(sproc.pid) - p.suspend() - for x in range(100): - if p.status() == psutil.STATUS_STOPPED: - break - time.sleep(0.01) - p.resume() - self.assertNotEqual(p.status(), psutil.STATUS_STOPPED) - - def test_invalid_pid(self): - self.assertRaises(TypeError, psutil.Process, "1") - self.assertRaises(ValueError, psutil.Process, -1) - - def test_as_dict(self): - p = psutil.Process() - d = p.as_dict(attrs=['exe', 'name']) - self.assertEqual(sorted(d.keys()), ['exe', 'name']) - - p = psutil.Process(min(psutil.pids())) - d = p.as_dict(attrs=['connections'], ad_value='foo') - if not isinstance(d['connections'], list): - self.assertEqual(d['connections'], 'foo') - - def test_halfway_terminated_process(self): - # Test that NoSuchProcess exception gets raised in case the - # process dies after we create the Process object. - # Example: - # >>> proc = Process(1234) - # >>> time.sleep(2) # time-consuming task, process dies in meantime - # >>> proc.name() - # Refers to Issue #15 - sproc = get_test_subprocess() - p = psutil.Process(sproc.pid) - p.terminate() - p.wait() - if WINDOWS: - wait_for_pid(p.pid) - self.assertFalse(p.is_running()) - self.assertFalse(p.pid in psutil.pids()) - - excluded_names = ['pid', 'is_running', 'wait', 'create_time'] - if LINUX and not RLIMIT_SUPPORT: - excluded_names.append('rlimit') - for name in dir(p): - if (name.startswith('_') or - name in excluded_names): - continue - try: - meth = getattr(p, name) - # get/set methods - if name == 'nice': - if POSIX: - ret = meth(1) - else: - ret = meth(psutil.NORMAL_PRIORITY_CLASS) - elif name == 'ionice': - ret = meth() - ret = meth(2) - elif name == 'rlimit': - ret = meth(psutil.RLIMIT_NOFILE) - ret = meth(psutil.RLIMIT_NOFILE, (5, 5)) - elif name == 'cpu_affinity': - ret = meth() - ret = meth([0]) - elif name == 'send_signal': - ret = meth(signal.SIGTERM) - else: - ret = meth() - except psutil.ZombieProcess: - self.fail("ZombieProcess for %r was not supposed to happen" % - name) - except psutil.NoSuchProcess: - pass - except NotImplementedError: - pass - else: - self.fail( - "NoSuchProcess exception not raised for %r, retval=%s" % ( - name, ret)) - - @unittest.skipUnless(POSIX, 'posix only') - def test_zombie_process(self): - def succeed_or_zombie_p_exc(fun, *args, **kwargs): - try: - fun(*args, **kwargs) - except (psutil.ZombieProcess, psutil.AccessDenied): - pass - - # Note: in this test we'll be creating two sub processes. - # Both of them are supposed to be freed / killed by - # reap_children() as they are attributable to 'us' - # (os.getpid()) via children(recursive=True). - src = textwrap.dedent("""\ - import os, sys, time, socket, contextlib - child_pid = os.fork() - if child_pid > 0: - time.sleep(3000) - else: - # this is the zombie process - s = socket.socket(socket.AF_UNIX) - with contextlib.closing(s): - s.connect('%s') - if sys.version_info < (3, ): - pid = str(os.getpid()) - else: - pid = bytes(str(os.getpid()), 'ascii') - s.sendall(pid) - """ % TESTFN) - with contextlib.closing(socket.socket(socket.AF_UNIX)) as sock: - try: - sock.settimeout(GLOBAL_TIMEOUT) - sock.bind(TESTFN) - sock.listen(1) - pyrun(src) - conn, _ = sock.accept() - select.select([conn.fileno()], [], [], GLOBAL_TIMEOUT) - zpid = int(conn.recv(1024)) - zproc = psutil.Process(zpid) - call_until(lambda: zproc.status(), - "ret == psutil.STATUS_ZOMBIE") - # A zombie process should always be instantiable - zproc = psutil.Process(zpid) - # ...and at least its status always be querable - self.assertEqual(zproc.status(), psutil.STATUS_ZOMBIE) - # ...and it should be considered 'running' - self.assertTrue(zproc.is_running()) - # ...and as_dict() shouldn't crash - zproc.as_dict() - if hasattr(zproc, "rlimit"): - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE) - succeed_or_zombie_p_exc(zproc.rlimit, psutil.RLIMIT_NOFILE, - (5, 5)) - # set methods - succeed_or_zombie_p_exc(zproc.parent) - if hasattr(zproc, 'cpu_affinity'): - succeed_or_zombie_p_exc(zproc.cpu_affinity, [0]) - succeed_or_zombie_p_exc(zproc.nice, 0) - if hasattr(zproc, 'ionice'): - if LINUX: - succeed_or_zombie_p_exc(zproc.ionice, 2, 0) - else: - succeed_or_zombie_p_exc(zproc.ionice, 0) # Windows - if hasattr(zproc, 'rlimit'): - succeed_or_zombie_p_exc(zproc.rlimit, - psutil.RLIMIT_NOFILE, (5, 5)) - succeed_or_zombie_p_exc(zproc.suspend) - succeed_or_zombie_p_exc(zproc.resume) - succeed_or_zombie_p_exc(zproc.terminate) - succeed_or_zombie_p_exc(zproc.kill) - - # ...its parent should 'see' it - # edit: not true on BSD and OSX - # descendants = [x.pid for x in psutil.Process().children( - # recursive=True)] - # self.assertIn(zpid, descendants) - # XXX should we also assume ppid be usable? Note: this - # would be an important use case as the only way to get - # rid of a zombie is to kill its parent. - # self.assertEqual(zpid.ppid(), os.getpid()) - # ...and all other APIs should be able to deal with it - self.assertTrue(psutil.pid_exists(zpid)) - self.assertIn(zpid, psutil.pids()) - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - psutil._pmap = {} - self.assertIn(zpid, [x.pid for x in psutil.process_iter()]) - finally: - reap_children(search_all=True) - - def test_pid_0(self): - # Process(0) is supposed to work on all platforms except Linux - if 0 not in psutil.pids(): - self.assertRaises(psutil.NoSuchProcess, psutil.Process, 0) - return - - p = psutil.Process(0) - self.assertTrue(p.name()) - - if POSIX: - try: - self.assertEqual(p.uids().real, 0) - self.assertEqual(p.gids().real, 0) - except psutil.AccessDenied: - pass - - self.assertRaisesRegexp( - ValueError, "preventing sending signal to process with PID 0", - p.send_signal, signal.SIGTERM) - - self.assertIn(p.ppid(), (0, 1)) - # self.assertEqual(p.exe(), "") - p.cmdline() - try: - p.num_threads() - except psutil.AccessDenied: - pass - - try: - p.memory_info() - except psutil.AccessDenied: - pass - - try: - if POSIX: - self.assertEqual(p.username(), 'root') - elif WINDOWS: - self.assertEqual(p.username(), 'NT AUTHORITY\\SYSTEM') - else: - p.username() - except psutil.AccessDenied: - pass - - self.assertIn(0, psutil.pids()) - self.assertTrue(psutil.pid_exists(0)) - - def test_Popen(self): - # Popen class test - # XXX this test causes a ResourceWarning on Python 3 because - # psutil.__subproc instance doesn't get propertly freed. - # Not sure what to do though. - cmd = [PYTHON, "-c", "import time; time.sleep(60);"] - proc = psutil.Popen(cmd, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) - try: - proc.name() - proc.stdin - self.assertTrue(hasattr(proc, 'name')) - self.assertTrue(hasattr(proc, 'stdin')) - self.assertTrue(dir(proc)) - self.assertRaises(AttributeError, getattr, proc, 'foo') - finally: - proc.kill() - proc.wait() - self.assertIsNotNone(proc.returncode) - - -# =================================================================== -# --- Featch all processes test -# =================================================================== - -class TestFetchAllProcesses(unittest.TestCase): - """Test which iterates over all running processes and performs - some sanity checks against Process API's returned values. - """ - - def setUp(self): - if POSIX: - import pwd - pall = pwd.getpwall() - self._uids = set([x.pw_uid for x in pall]) - self._usernames = set([x.pw_name for x in pall]) - - def test_fetch_all(self): - valid_procs = 0 - excluded_names = set([ - 'send_signal', 'suspend', 'resume', 'terminate', 'kill', 'wait', - 'as_dict', 'cpu_percent', 'parent', 'children', 'pid']) - if LINUX and not RLIMIT_SUPPORT: - excluded_names.add('rlimit') - attrs = [] - for name in dir(psutil.Process): - if name.startswith("_"): - continue - if name in excluded_names: - continue - attrs.append(name) - - default = object() - failures = [] - for name in attrs: - for p in psutil.process_iter(): - ret = default - try: - try: - args = () - attr = getattr(p, name, None) - if attr is not None and callable(attr): - if name == 'rlimit': - args = (psutil.RLIMIT_NOFILE,) - ret = attr(*args) - else: - ret = attr - valid_procs += 1 - except NotImplementedError: - msg = "%r was skipped because not implemented" % ( - self.__class__.__name__ + '.test_' + name) - warn(msg) - except (psutil.NoSuchProcess, psutil.AccessDenied) as err: - self.assertEqual(err.pid, p.pid) - if err.name: - # make sure exception's name attr is set - # with the actual process name - self.assertEqual(err.name, p.name()) - self.assertTrue(str(err)) - self.assertTrue(err.msg) - else: - if ret not in (0, 0.0, [], None, ''): - assert ret, ret - meth = getattr(self, name) - meth(ret) - except Exception as err: - s = '\n' + '=' * 70 + '\n' - s += "FAIL: test_%s (proc=%s" % (name, p) - if ret != default: - s += ", ret=%s)" % repr(ret) - s += ')\n' - s += '-' * 70 - s += "\n%s" % traceback.format_exc() - s = "\n".join((" " * 4) + i for i in s.splitlines()) - failures.append(s) - break - - if failures: - self.fail(''.join(failures)) - - # we should always have a non-empty list, not including PID 0 etc. - # special cases. - self.assertTrue(valid_procs > 0) - - def cmdline(self, ret): - pass - - def exe(self, ret): - if not ret: - self.assertEqual(ret, '') - else: - assert os.path.isabs(ret), ret - # Note: os.stat() may return False even if the file is there - # hence we skip the test, see: - # http://stackoverflow.com/questions/3112546/os-path-exists-lies - if POSIX and os.path.isfile(ret): - if hasattr(os, 'access') and hasattr(os, "X_OK"): - # XXX may fail on OSX - self.assertTrue(os.access(ret, os.X_OK)) - - def ppid(self, ret): - self.assertTrue(ret >= 0) - - def name(self, ret): - self.assertIsInstance(ret, (str, unicode)) - self.assertTrue(ret) - - def create_time(self, ret): - self.assertTrue(ret > 0) - # this can't be taken for granted on all platforms - # self.assertGreaterEqual(ret, psutil.boot_time()) - # make sure returned value can be pretty printed - # with strftime - time.strftime("%Y %m %d %H:%M:%S", time.localtime(ret)) - - def uids(self, ret): - for uid in ret: - self.assertTrue(uid >= 0) - self.assertIn(uid, self._uids) - - def gids(self, ret): - # note: testing all gids as above seems not to be reliable for - # gid == 30 (nodoby); not sure why. - for gid in ret: - self.assertTrue(gid >= 0) - # self.assertIn(uid, self.gids - - def username(self, ret): - self.assertTrue(ret) - if POSIX: - self.assertIn(ret, self._usernames) - - def status(self, ret): - self.assertTrue(ret != "") - self.assertTrue(ret != '?') - self.assertIn(ret, VALID_PROC_STATUSES) - - def io_counters(self, ret): - for field in ret: - if field != -1: - self.assertTrue(field >= 0) - - def ionice(self, ret): - if LINUX: - self.assertTrue(ret.ioclass >= 0) - self.assertTrue(ret.value >= 0) - else: - self.assertTrue(ret >= 0) - self.assertIn(ret, (0, 1, 2)) - - def num_threads(self, ret): - self.assertTrue(ret >= 1) - - def threads(self, ret): - for t in ret: - self.assertTrue(t.id >= 0) - self.assertTrue(t.user_time >= 0) - self.assertTrue(t.system_time >= 0) - - def cpu_times(self, ret): - self.assertTrue(ret.user >= 0) - self.assertTrue(ret.system >= 0) - - def memory_info(self, ret): - self.assertTrue(ret.rss >= 0) - self.assertTrue(ret.vms >= 0) - - def memory_info_ex(self, ret): - for name in ret._fields: - self.assertTrue(getattr(ret, name) >= 0) - if POSIX and ret.vms != 0: - # VMS is always supposed to be the highest - for name in ret._fields: - if name != 'vms': - value = getattr(ret, name) - assert ret.vms > value, ret - elif WINDOWS: - assert ret.peak_wset >= ret.wset, ret - assert ret.peak_paged_pool >= ret.paged_pool, ret - assert ret.peak_nonpaged_pool >= ret.nonpaged_pool, ret - assert ret.peak_pagefile >= ret.pagefile, ret - - def open_files(self, ret): - for f in ret: - if WINDOWS: - assert f.fd == -1, f - else: - self.assertIsInstance(f.fd, int) - assert os.path.isabs(f.path), f - assert os.path.isfile(f.path), f - - def num_fds(self, ret): - self.assertTrue(ret >= 0) - - def connections(self, ret): - self.assertEqual(len(ret), len(set(ret))) - for conn in ret: - check_connection_ntuple(conn) - - def cwd(self, ret): - if ret is not None: # BSD may return None - assert os.path.isabs(ret), ret - try: - st = os.stat(ret) - except OSError as err: - # directory has been removed in mean time - if err.errno != errno.ENOENT: - raise - else: - self.assertTrue(stat.S_ISDIR(st.st_mode)) - - def memory_percent(self, ret): - assert 0 <= ret <= 100, ret - - def is_running(self, ret): - self.assertTrue(ret) - - def cpu_affinity(self, ret): - assert ret != [], ret - - def terminal(self, ret): - if ret is not None: - assert os.path.isabs(ret), ret - assert os.path.exists(ret), ret - - def memory_maps(self, ret): - for nt in ret: - for fname in nt._fields: - value = getattr(nt, fname) - if fname == 'path': - if not value.startswith('['): - assert os.path.isabs(nt.path), nt.path - # commented as on Linux we might get - # '/foo/bar (deleted)' - # assert os.path.exists(nt.path), nt.path - elif fname in ('addr', 'perms'): - self.assertTrue(value) - else: - self.assertIsInstance(value, (int, long)) - assert value >= 0, value - - def num_handles(self, ret): - if WINDOWS: - self.assertGreaterEqual(ret, 0) - else: - self.assertGreaterEqual(ret, 0) - - def nice(self, ret): - if POSIX: - assert -20 <= ret <= 20, ret - else: - priorities = [getattr(psutil, x) for x in dir(psutil) - if x.endswith('_PRIORITY_CLASS')] - self.assertIn(ret, priorities) - - def num_ctx_switches(self, ret): - self.assertTrue(ret.voluntary >= 0) - self.assertTrue(ret.involuntary >= 0) - - def rlimit(self, ret): - self.assertEqual(len(ret), 2) - self.assertGreaterEqual(ret[0], -1) - self.assertGreaterEqual(ret[1], -1) - - -# =================================================================== -# --- Limited user tests -# =================================================================== - -@unittest.skipUnless(POSIX, "UNIX only") -@unittest.skipUnless(hasattr(os, 'getuid') and os.getuid() == 0, - "super user privileges are required") -class LimitedUserTestCase(TestProcess): - """Repeat the previous tests by using a limited user. - Executed only on UNIX and only if the user who run the test script - is root. - """ - # the uid/gid the test suite runs under - if hasattr(os, 'getuid'): - PROCESS_UID = os.getuid() - PROCESS_GID = os.getgid() - - def __init__(self, *args, **kwargs): - TestProcess.__init__(self, *args, **kwargs) - # re-define all existent test methods in order to - # ignore AccessDenied exceptions - for attr in [x for x in dir(self) if x.startswith('test')]: - meth = getattr(self, attr) - - def test_(self): - try: - meth() - except psutil.AccessDenied: - pass - setattr(self, attr, types.MethodType(test_, self)) - - def setUp(self): - safe_remove(TESTFN) - TestProcess.setUp(self) - os.setegid(1000) - os.seteuid(1000) - - def tearDown(self): - os.setegid(self.PROCESS_UID) - os.seteuid(self.PROCESS_GID) - TestProcess.tearDown(self) - - def test_nice(self): - try: - psutil.Process().nice(-1) - except psutil.AccessDenied: - pass - else: - self.fail("exception not raised") - - def test_zombie_process(self): - # causes problems if test test suite is run as root - pass - - -# =================================================================== -# --- Misc tests -# =================================================================== - -class TestMisc(unittest.TestCase): - """Misc / generic tests.""" - - def test_process__repr__(self, func=repr): - p = psutil.Process() - r = func(p) - self.assertIn("psutil.Process", r) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("name=", r) - self.assertIn(p.name(), r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.ZombieProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("zombie", r) - self.assertNotIn("name=", r) - with mock.patch.object(psutil.Process, "name", - side_effect=psutil.NoSuchProcess(os.getpid())): - p = psutil.Process() - r = func(p) - self.assertIn("pid=%s" % p.pid, r) - self.assertIn("terminated", r) - self.assertNotIn("name=", r) - - def test_process__str__(self): - self.test_process__repr__(func=str) - - def test_no_such_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.NoSuchProcess(321)), - "psutil.NoSuchProcess process no longer exists (pid=321)") - self.assertEqual( - repr(psutil.NoSuchProcess(321, name='foo')), - "psutil.NoSuchProcess process no longer exists (pid=321, " - "name='foo')") - self.assertEqual( - repr(psutil.NoSuchProcess(321, msg='foo')), - "psutil.NoSuchProcess foo") - - def test_zombie_process__repr__(self, func=repr): - self.assertEqual( - repr(psutil.ZombieProcess(321)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321)") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo')), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo')") - self.assertEqual( - repr(psutil.ZombieProcess(321, name='foo', ppid=1)), - "psutil.ZombieProcess process still exists but it's a zombie " - "(pid=321, name='foo', ppid=1)") - self.assertEqual( - repr(psutil.ZombieProcess(321, msg='foo')), - "psutil.ZombieProcess foo") - - def test_access_denied__repr__(self, func=repr): - self.assertEqual( - repr(psutil.AccessDenied(321)), - "psutil.AccessDenied (pid=321)") - self.assertEqual( - repr(psutil.AccessDenied(321, name='foo')), - "psutil.AccessDenied (pid=321, name='foo')") - self.assertEqual( - repr(psutil.AccessDenied(321, msg='foo')), - "psutil.AccessDenied foo") - - def test_timeout_expired__repr__(self, func=repr): - self.assertEqual( - repr(psutil.TimeoutExpired(321)), - "psutil.TimeoutExpired timeout after 321 seconds") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111)), - "psutil.TimeoutExpired timeout after 321 seconds (pid=111)") - self.assertEqual( - repr(psutil.TimeoutExpired(321, pid=111, name='foo')), - "psutil.TimeoutExpired timeout after 321 seconds " - "(pid=111, name='foo')") - - def test_process__eq__(self): - p1 = psutil.Process() - p2 = psutil.Process() - self.assertEqual(p1, p2) - p2._ident = (0, 0) - self.assertNotEqual(p1, p2) - self.assertNotEqual(p1, 'foo') - - def test_process__hash__(self): - s = set([psutil.Process(), psutil.Process()]) - self.assertEqual(len(s), 1) - - def test__all__(self): - dir_psutil = dir(psutil) - for name in dir_psutil: - if name in ('callable', 'error', 'namedtuple', - 'long', 'test', 'NUM_CPUS', 'BOOT_TIME', - 'TOTAL_PHYMEM'): - continue - if not name.startswith('_'): - try: - __import__(name) - except ImportError: - if name not in psutil.__all__: - fun = getattr(psutil, name) - if fun is None: - continue - if (fun.__doc__ is not None and - 'deprecated' not in fun.__doc__.lower()): - self.fail('%r not in psutil.__all__' % name) - - # Import 'star' will break if __all__ is inconsistent, see: - # https://github.com/giampaolo/psutil/issues/656 - # Can't do `from psutil import *` as it won't work on python 3 - # so we simply iterate over __all__. - for name in psutil.__all__: - self.assertIn(name, dir_psutil) - - def test_version(self): - self.assertEqual('.'.join([str(x) for x in psutil.version_info]), - psutil.__version__) - - def test_memoize(self): - from psutil._common import memoize - - @memoize - def foo(*args, **kwargs): - "foo docstring" - calls.append(None) - return (args, kwargs) - - calls = [] - # no args - for x in range(2): - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 1) - # with args - for x in range(2): - ret = foo(1) - expected = ((1, ), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 2) - # with args + kwargs - for x in range(2): - ret = foo(1, bar=2) - expected = ((1, ), {'bar': 2}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 3) - # clear cache - foo.cache_clear() - ret = foo() - expected = ((), {}) - self.assertEqual(ret, expected) - self.assertEqual(len(calls), 4) - # docstring - self.assertEqual(foo.__doc__, "foo docstring") - - def test_isfile_strict(self): - from psutil._common import isfile_strict - this_file = os.path.abspath(__file__) - assert isfile_strict(this_file) - assert not isfile_strict(os.path.dirname(this_file)) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EPERM, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EACCES, "foo")): - self.assertRaises(OSError, isfile_strict, this_file) - with mock.patch('psutil._common.os.stat', - side_effect=OSError(errno.EINVAL, "foo")): - assert not isfile_strict(this_file) - with mock.patch('psutil._common.stat.S_ISREG', return_value=False): - assert not isfile_strict(this_file) - - def test_serialization(self): - def check(ret): - if json is not None: - json.loads(json.dumps(ret)) - a = pickle.dumps(ret) - b = pickle.loads(a) - self.assertEqual(ret, b) - - check(psutil.Process().as_dict()) - check(psutil.virtual_memory()) - check(psutil.swap_memory()) - check(psutil.cpu_times()) - check(psutil.cpu_times_percent(interval=0)) - check(psutil.net_io_counters()) - if LINUX and not os.path.exists('/proc/diskstats'): - pass - else: - if not APPVEYOR: - check(psutil.disk_io_counters()) - check(psutil.disk_partitions()) - check(psutil.disk_usage(os.getcwd())) - check(psutil.users()) - - def test_setup_script(self): - here = os.path.abspath(os.path.dirname(__file__)) - setup_py = os.path.realpath(os.path.join(here, '..', 'setup.py')) - module = imp.load_source('setup', setup_py) - self.assertRaises(SystemExit, module.setup) - self.assertEqual(module.get_version(), psutil.__version__) - - def test_ad_on_process_creation(self): - # We are supposed to be able to instantiate Process also in case - # of zombie processes or access denied. - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.AccessDenied) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=psutil.ZombieProcess(1)) as meth: - psutil.Process() - assert meth.called - with mock.patch.object(psutil.Process, 'create_time', - side_effect=ValueError) as meth: - with self.assertRaises(ValueError): - psutil.Process() - assert meth.called - - -# =================================================================== -# --- Example script tests -# =================================================================== - -class TestExampleScripts(unittest.TestCase): - """Tests for scripts in the examples directory.""" - - def assert_stdout(self, exe, args=None): - exe = os.path.join(EXAMPLES_DIR, exe) - if args: - exe = exe + ' ' + args - try: - out = sh(sys.executable + ' ' + exe).strip() - except RuntimeError as err: - if 'AccessDenied' in str(err): - return str(err) - else: - raise - assert out, out - return out - - def assert_syntax(self, exe, args=None): - exe = os.path.join(EXAMPLES_DIR, exe) - with open(exe, 'r') as f: - src = f.read() - ast.parse(src) - - def test_check_presence(self): - # make sure all example scripts have a test method defined - meths = dir(self) - for name in os.listdir(EXAMPLES_DIR): - if name.endswith('.py'): - if 'test_' + os.path.splitext(name)[0] not in meths: - # self.assert_stdout(name) - self.fail('no test defined for %r script' - % os.path.join(EXAMPLES_DIR, name)) - - def test_disk_usage(self): - self.assert_stdout('disk_usage.py') - - def test_free(self): - self.assert_stdout('free.py') - - def test_meminfo(self): - self.assert_stdout('meminfo.py') - - def test_process_detail(self): - self.assert_stdout('process_detail.py') - - @unittest.skipIf(APPVEYOR, "can't find users on Appveyor") - def test_who(self): - self.assert_stdout('who.py') - - def test_ps(self): - self.assert_stdout('ps.py') - - def test_pstree(self): - self.assert_stdout('pstree.py') - - def test_netstat(self): - self.assert_stdout('netstat.py') - - @unittest.skipIf(TRAVIS, "permission denied on travis") - def test_ifconfig(self): - self.assert_stdout('ifconfig.py') - - def test_pmap(self): - self.assert_stdout('pmap.py', args=str(os.getpid())) - - @unittest.skipIf(ast is None, - 'ast module not available on this python version') - def test_killall(self): - self.assert_syntax('killall.py') - - @unittest.skipIf(ast is None, - 'ast module not available on this python version') - def test_nettop(self): - self.assert_syntax('nettop.py') - - @unittest.skipIf(ast is None, - 'ast module not available on this python version') - def test_top(self): - self.assert_syntax('top.py') - - @unittest.skipIf(ast is None, - 'ast module not available on this python version') - def test_iotop(self): - self.assert_syntax('iotop.py') - - def test_pidof(self): - output = self.assert_stdout('pidof.py %s' % psutil.Process().name()) - self.assertIn(str(os.getpid()), output) - - -def main(): - tests = [] - test_suite = unittest.TestSuite() - tests.append(TestSystemAPIs) - tests.append(TestProcess) - tests.append(TestFetchAllProcesses) - tests.append(TestMisc) - tests.append(TestExampleScripts) - tests.append(LimitedUserTestCase) - - if POSIX: - from _posix import PosixSpecificTestCase - tests.append(PosixSpecificTestCase) - - # import the specific platform test suite - stc = None - if LINUX: - from _linux import LinuxSpecificTestCase as stc - elif WINDOWS: - from _windows import WindowsSpecificTestCase as stc - from _windows import TestDualProcessImplementation - tests.append(TestDualProcessImplementation) - elif OSX: - from _osx import OSXSpecificTestCase as stc - elif BSD: - from _bsd import BSDSpecificTestCase as stc - elif SUNOS: - from _sunos import SunOSSpecificTestCase as stc - if stc is not None: - tests.append(stc) - - for test_class in tests: - test_suite.addTest(unittest.makeSuite(test_class)) - result = unittest.TextTestRunner(verbosity=2).run(test_suite) - return result.wasSuccessful() - -if __name__ == '__main__': - if not main(): - sys.exit(1) diff --git a/python/psutil/tox.ini b/python/psutil/tox.ini deleted file mode 100644 index d80dd174b..000000000 --- a/python/psutil/tox.ini +++ /dev/null @@ -1,32 +0,0 @@ -# Tox (http://tox.testrun.org/) is a tool for running tests -# in multiple virtualenvs. This configuration file will run the -# test suite on all supported python versions. -# To use it run "pip install tox" and then run "tox" from this -# directory. - -[tox] -envlist = py26, py27, py32, py33, py34 - -[testenv] -deps = - flake8 - pytest - py26: ipaddress - py26: mock==1.0.1 - py26: unittest2 - py27: ipaddress - py27: mock - py32: ipaddress - py32: mock - py33: ipaddress - -setenv = - PYTHONPATH = {toxinidir}/test - -commands = - py.test {posargs} - git ls-files | grep \\.py$ | xargs flake8 - -# suppress "WARNING: 'git' command found but not installed in testenv -whitelist_externals = git -usedevelop = True |