mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 870575 - Upgrade psutil to 0.7.1; rs=me
Archive obtained from https://psutil.googlecode.com/files/psutil-0.7.1.tar.gz and checked in with no modifications.
This commit is contained in:
parent
09d57c5181
commit
04177dc5e6
@ -18,6 +18,7 @@ Maintainers
|
||||
N: Giampaolo Rodola'
|
||||
C: Italy
|
||||
E: g.rodola@gmail.com
|
||||
W: http://www.linkedin.com/in/grodola
|
||||
|
||||
N: Jay Loden
|
||||
C: NJ, USA
|
||||
@ -78,7 +79,7 @@ I: 248
|
||||
|
||||
N: Amoser
|
||||
E: amoser@google.com
|
||||
I: 266, 267
|
||||
I: 266, 267, 340
|
||||
|
||||
N: Matthew Grant
|
||||
E: matthewgrant5@gmail.com
|
||||
@ -117,3 +118,47 @@ 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
|
||||
|
@ -1,17 +1,91 @@
|
||||
Bug tracker at http://code.google.com/p/psutil/issues
|
||||
|
||||
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
|
||||
------------------
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* #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
|
||||
------------------
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 316: process cmdline property now makes a better job at guessing the
|
||||
process executable from the cmdline.
|
||||
* #316: process cmdline property now makes a better job at guessing the process
|
||||
executable from the cmdline.
|
||||
|
||||
BUG FIXES
|
||||
|
||||
* Issue 316: process exe was resolved in case it was a symlink.
|
||||
* Issue 318: python 2.4 compatibility was broken.
|
||||
* #316: process exe was resolved in case it was a symlink.
|
||||
* #318: python 2.4 compatibility was broken.
|
||||
|
||||
API CHANGES
|
||||
|
||||
@ -24,78 +98,78 @@ API CHANGES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 216: (UNIX) get_connections() UNIX sockets support.
|
||||
* Issue 220: (BSD) get_connections() has been rewritten in C and no longer
|
||||
requires lsof.
|
||||
* Issue 222: (OSX) add support for process cwd.
|
||||
* Issue 261: process extended memory info.
|
||||
* Issue 295: (OSX) process executable path is now determined by asking the OS
|
||||
instead of being guessed from process cmdline.
|
||||
* Issue 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()
|
||||
* Issue 300: examples/pmap.py script.
|
||||
* Issue 301: process_iter() now yields processes sorted by their PIDs.
|
||||
* Issue 302: process number of voluntary and involuntary context switches.
|
||||
* Issue 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()
|
||||
* Issue 305: add examples/netstat.py script.
|
||||
* Issue 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 (UNIX)
|
||||
- inactive (UNIX)
|
||||
- buffers (BSD, Linux)
|
||||
- cached (BSD, OSX)
|
||||
- wired (OSX, BSD)
|
||||
- shared (BSD)
|
||||
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.
|
||||
* Issue 312: psutil.network_io_counters() namedtuple includes 4 new fields:
|
||||
errin, errout dropin and dropout, reflecting the number of packets dropped
|
||||
and with errors.
|
||||
* #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
|
||||
|
||||
* Issue 298: (OSX - BSD) memory leak in get_num_fds().
|
||||
* Issue 299: potential memory leak every time PyList_New(0) is used.
|
||||
* Issue 303: (Windows) potential heap corruption in get_num_threads() and
|
||||
get_status() Process methods.
|
||||
* Issue 305: (BSD) psutil can't compile on FreeBSD 9 due to removal of utmp.h.
|
||||
* Issue 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.
|
||||
* Issue 307: (BSD) values returned by psutil.network_io_counters() are wrong.
|
||||
* Issue 308: (BSD / Windows) psutil.virtmem_usage() wasn't actually returning
|
||||
information about swap memory usage as it was supposed to do. It does now.
|
||||
* Issue 309: get_open_files() might not return files which can not be accessed
|
||||
due to limited permissions. AccessDenied is now raised instead.
|
||||
* #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
|
||||
|
||||
@ -103,7 +177,7 @@ API CHANGES
|
||||
* 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
|
||||
* [Windows and BSD] psutil.virtmem_usage() now returns information about swap
|
||||
memory instead of virtual memory.
|
||||
|
||||
|
||||
@ -112,13 +186,13 @@ API CHANGES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 293: (Windows) process executable path is now determined by asking the
|
||||
OS instead of being guessed from process cmdline.
|
||||
* #293: [Windows] process executable path is now determined by asking the OS
|
||||
instead of being guessed from process cmdline.
|
||||
|
||||
BUGFIXES
|
||||
|
||||
* Issue 292: (Linux) race condition in process files/threads/connections.
|
||||
* Issue 294: (Windows) Process CPU affinity is only able to set CPU #0.
|
||||
* #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
|
||||
@ -126,57 +200,57 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue #195: (Windows) number of handles opened by process.
|
||||
* Issue #209: psutil.disk_partitions() now provides also mount options.
|
||||
* Issue #229: list users currently connected on the system (psutil.get_users()).
|
||||
* Issue #238: (Linux, Windows) process CPU affinity (get and set).
|
||||
* Issue #242: Process.get_children(recursive=True): return all process
|
||||
descendants.
|
||||
* Issue #245: (POSIX) Process.wait() incrementally consumes less CPU cycles.
|
||||
* Issue #257: (Windows) removed Windows 2000 support.
|
||||
* Issue #258: (Linux) Process.get_memory_info() is now 0.5x faster.
|
||||
* Issue #260: process's mapped memory regions. (Windows patch by wj32.64, OSX
|
||||
patch by Jeremy Whitlock)
|
||||
* Issue #262: (Windows) psutil.disk_partitions() was slow due to inspecting
|
||||
the floppy disk drive also when "all" argument was False.
|
||||
* Issue #273: psutil.get_process_list() is deprecated.
|
||||
* Issue #274: psutil no longer requires 2to3 at installation time in order to
|
||||
work with Python 3.
|
||||
* Issue #278: new Process.as_dict() method.
|
||||
* Issue #281: ppid, name, exe, cmdline and create_time properties of Process
|
||||
class are now cached after being accessed.
|
||||
* Issue #282: psutil.STATUS_* constants can now be compared by using their
|
||||
string representation.
|
||||
* Issue #283: speedup Process.is_running() by caching its return value in case
|
||||
the process is terminated.
|
||||
* Issue #284: (POSIX) per-process number of opened file descriptors.
|
||||
* Issue #287: psutil.process_iter() now caches Process instances between calls.
|
||||
* Issue #290: Process.nice property is deprecated in favor of new get_nice()
|
||||
and set_nice() methods.
|
||||
* #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
|
||||
|
||||
* Issue #193: psutil.Popen constructor can throw an exception if the spawned
|
||||
process terminates quickly.
|
||||
* Issue #240: (OSX) incorrect use of free() for Process.get_connections().
|
||||
* Issue #244: (POSIX) Process.wait() can hog CPU resources if called against
|
||||
a process which is not our children.
|
||||
* Issue #248: (Linux) psutil.network_io_counters() might return erroneous NIC
|
||||
names.
|
||||
* Issue #252: (Windows) process getcwd() erroneously raise NoSuchProcess for
|
||||
processes owned by another user. It now raises AccessDenied instead.
|
||||
* Issue #266: (Windows) psutil.get_pid_list() only shows 1024 processes.
|
||||
(patch by Amoser)
|
||||
* Issue #267: (OSX) Process.get_connections() - an erroneous remote address
|
||||
was returned. (Patch by Amoser)
|
||||
* Issue #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.
|
||||
* Issue #275: (Linux) Process.get_io_counters() erroneously raise NoSuchProcess
|
||||
on old Linux versions. Where not available it now raises NotImplementedError.
|
||||
* Issue #286: Process.is_running() doesn't actually check whether PID has been
|
||||
reused.
|
||||
* Issue #314: Process.get_children() can sometimes return non-children.
|
||||
* #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
|
||||
|
||||
@ -195,12 +269,12 @@ API CHANGES
|
||||
|
||||
BUGFIXES
|
||||
|
||||
* Issue 228: some example scripts were not working with python 3.
|
||||
* Issue 230: (Windows / OSX) memory leak in Process.get_connections().
|
||||
* Issue 232: (Linux) psutil.phymem_usage() can report erroneous values which
|
||||
are different than "free" command.
|
||||
* Issue 236: (Windows) memory/handle leak in Process's get_memory_info(),
|
||||
suspend() and resume() methods.
|
||||
* #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
|
||||
@ -208,38 +282,38 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 150: network I/O counters. (OSX and Windows patch by Jeremy Whitlock)
|
||||
* Issue 154: (FreeBSD) add support for process getcwd()
|
||||
* Issue 157: (Windows) provide installer for Python 3.2 64-bit.
|
||||
* Issue 198: Process.wait(timeout=0) can now be used to make wait() return
|
||||
immediately.
|
||||
* Issue 206: disk I/O counters. (OSX and Windows patch by Jeremy Whitlock)
|
||||
* Issue 213: examples/iotop.py script.
|
||||
* Issue 217: Process.get_connections() now has a "kind" argument to filter
|
||||
* #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.
|
||||
* Issue 221: (FreeBSD) Process.get_open_files has been rewritten in C and no
|
||||
longer relies on lsof.
|
||||
* Issue 223: examples/top.py script.
|
||||
* Issue 227: examples/nettop.py script.
|
||||
* #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
|
||||
|
||||
* Issue 135: (OS X) psutil cannot create Process object
|
||||
* Issue 144: (Linux) no longer support 0 special PID.
|
||||
* Issue 188: (Linux) psutil import error on Linux ARM architectures.
|
||||
* Issue 194: (POSIX) psutil.Process.get_cpu_percent() now reports a percentage
|
||||
over 100 on multicore processors.
|
||||
* Issue 197: (Linux) Process.get_connections() is broken on platforms not
|
||||
supporting IPv6.
|
||||
* Issue 200: (Linux) psutil.NUM_CPUS not working on armel and sparc
|
||||
architectures and causing crash on module import.
|
||||
* Issue 201: (Linux) Process.get_connections() is broken on big-endian
|
||||
architectures.
|
||||
* Issue 211: Process instance can unexpectedly raise NoSuchProcess if tested
|
||||
for equality with another object.
|
||||
* Issue 218: (Linux) crash at import time on Debian 64-bit because of a missing
|
||||
line in /proc/meminfo.
|
||||
* Issue 226: (FreeBSD) crash at import time on FreeBSD 7 and minor.
|
||||
* #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
|
||||
@ -247,28 +321,27 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 125: system per-cpu percentage utilization and times.
|
||||
* Issue 163: per-process associated terminal (TTY).
|
||||
* Issue 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.
|
||||
* Issue 172: disk usage statistics.
|
||||
* Issue 174: mounted disk partitions.
|
||||
* Issue 179: setuptools is now used in setup.py
|
||||
* #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
|
||||
|
||||
* Issue 159: SetSeDebug() does not close handles or unset impersonation on
|
||||
return.
|
||||
* Issue 164: wait function raises a TimeoutException when a process returns
|
||||
-1 (Windows).
|
||||
* Issue 165: process.status raises an unhandled exception.
|
||||
* Issue 166: get_memory_info() leaks handles hogging system resources.
|
||||
* Issue 168: psutil.cpu_percent() returns erroneous results when used in
|
||||
non-blocking mode. (patch by Philip Roberts)
|
||||
* Issue 178: OSX - Process.get_threads() leaks memory
|
||||
* Issue 180: Windows - Process's get_num_threads() and get_threads() methods
|
||||
can raise NoSuchProcess exception while process still exists.
|
||||
* #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
|
||||
@ -276,35 +349,35 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 64: per-process I/O counters.
|
||||
* Issue 116: per-process wait() (wait for process to terminate and return its
|
||||
exit code).
|
||||
* Issue 134: per-process get_threads() returning information (id, user and
|
||||
kernel times) about threads opened by process.
|
||||
* Issue 136: process executable path on FreeBSD is now determined by asking
|
||||
the kernel instead of guessing it from cmdline[0].
|
||||
* Issue 137: per-process real, effective and saved user and group ids.
|
||||
* Issue 140: system boot time.
|
||||
* Issue 142: per-process get and set niceness (priority).
|
||||
* Issue 143: per-process status.
|
||||
* Issue 147: per-process I/O nice (priority) - Linux only.
|
||||
* Issue 148: psutil.Popen class which tidies up subprocess.Popen and
|
||||
psutil.Process in a unique interface.
|
||||
* Issue 152: (OSX) get_process_open_files() implementation has been rewritten
|
||||
in C and no longer relies on lsof resulting in a 3x speedup.
|
||||
* Issue 153: (OSX) get_process_connection() implementation has been rewritten
|
||||
in C and no longer relies on lsof resulting in a 3x speedup.
|
||||
* #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
|
||||
|
||||
* Issue 83: process cmdline is empty on OSX 64-bit.
|
||||
* Issue 130: a race condition can cause IOError exception be raised on
|
||||
Linux if process disappears between open() and subsequent read() calls.
|
||||
* Issue 145: WindowsError was raised instead of psutil.AccessDenied when using
|
||||
process resume() or suspend() on Windows.
|
||||
* Issue 146: 'exe' property on Linux can raise TypeError if path contains NULL
|
||||
bytes.
|
||||
* Issue 151: exe and getcwd() for PID 0 on Linux return inconsistent data.
|
||||
* #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
|
||||
|
||||
@ -317,43 +390,43 @@ API CHANGES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 79: per-process open files.
|
||||
* Issue 88: total system physical cached memory.
|
||||
* Issue 88: total system physical memory buffers used by the kernel.
|
||||
* Issue 91: per-process send_signal() and terminate() methods.
|
||||
* Issue 95: NoSuchProcess and AccessDenied exception classes now provide "pid",
|
||||
"name" and "msg" attributes.
|
||||
* Issue 97: per-process children.
|
||||
* Issue 98: Process.get_cpu_times() and Process.get_memory_info now return
|
||||
a namedtuple instead of a tuple.
|
||||
* Issue 103: per-process opened TCP and UDP connections.
|
||||
* Issue 107: add support for Windows 64 bit. (patch by cjgohlke)
|
||||
* Issue 111: per-process executable name.
|
||||
* Issue 113: exception messages now include process name and pid.
|
||||
* Issue 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)
|
||||
* Issue 117: added support for Windows 2000.
|
||||
* Issue 123: psutil.cpu_percent() and psutil.Process.cpu_percent() accept a
|
||||
new 'interval' parameter.
|
||||
* Issue 129: per-process number of threads.
|
||||
* #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
|
||||
|
||||
* Issue 80: fixed warnings when installing psutil with easy_install.
|
||||
* Issue 81: psutil fails to compile with Visual Studio.
|
||||
* Issue 94: suspend() raises OSError instead of AccessDenied.
|
||||
* Issue 86: psutil didn't compile against FreeBSD 6.x.
|
||||
* Issue 102: orphaned process handles obtained by using OpenProcess in C were
|
||||
left behind every time Process class was instantiated.
|
||||
* Issue 111: path and name Process properties report truncated or erroneous
|
||||
values on UNIX.
|
||||
* Issue 120: cpu_percent() always returning 100% on OS X.
|
||||
* Issue 112: uid and gid properties don't change if process changes effective
|
||||
user/group id at some point.
|
||||
* Issue 126: ppid, uid, gid, name, exe, cmdline and create_time properties are
|
||||
no longer cached and correctly raise NoSuchProcess exception if the process
|
||||
disappears.
|
||||
* #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
|
||||
|
||||
@ -377,28 +450,28 @@ API CHANGES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 14: per-process username
|
||||
* Issue 51: per-process current working directory (Windows and Linux only)
|
||||
* Issue 59: Process.is_running() is now 10 times faster
|
||||
* Issue 61: added supoprt for FreeBSD 64 bit
|
||||
* Issue 71: implemented suspend/resume process
|
||||
* Issue 75: python 3 support
|
||||
* #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
|
||||
|
||||
* Issue 36: process cpu_times() and memory_info() functions succeeded also for
|
||||
dead processes while a NoSuchProcess exception is supposed to be raised.
|
||||
* Issue 48: incorrect size for mib array defined in getcmdargs for BSD
|
||||
* Issue 49: possible memory leak due to missing free() on error condition on
|
||||
* Issue 50: fixed getcmdargs() memory fragmentation on BSD
|
||||
* Issue 55: test_pid_4 was failing on Windows Vista
|
||||
* Issue 57: some unit tests were failing on systems where no swap memory is
|
||||
available
|
||||
* Issue 58: is_running() is now called before kill() to make sure we are going
|
||||
to kill the correct process.
|
||||
* Issue 73: virtual memory size reported on OS X includes shared library size
|
||||
* Issue 77: NoSuchProcess wasn't raised on Process.create_time if kill() was
|
||||
used first.
|
||||
* #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
|
||||
@ -406,21 +479,21 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 32: Per-process CPU user/kernel times
|
||||
* Issue 33: Process create time
|
||||
* Issue 34: Per-process CPU utilization percentage
|
||||
* Issue 38: Per-process memory usage (bytes)
|
||||
* Issue 41: Per-process memory utilization (percent)
|
||||
* Issue 39: System uptime
|
||||
* Issue 43: Total system virtual memory
|
||||
* Issue 46: Total system physical memory
|
||||
* Issue 44: Total system used/free virtual and physical memory
|
||||
* #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
|
||||
|
||||
* Issue 36: NoSuchProcess not raised on Windows when accessing timing methods
|
||||
* Issue 40: test_get_cpu_times() failing on FreeBSD and OS X
|
||||
* Issue 42: get_memory_percent() raises AccessDenied on Windows
|
||||
* #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
|
||||
@ -428,33 +501,34 @@ BUGFIXES
|
||||
|
||||
NEW FEATURES
|
||||
|
||||
* Issue 4: FreeBSD support for all functions of psutil
|
||||
* Issue 9: Process.uid and Process.gid now retrieve process UID and GID.
|
||||
* Issue 11: Support for parent/ppid - Process.parent property returns a
|
||||
Process object representing the parent process, and Process.ppid returns
|
||||
the parent PID.
|
||||
* Issue 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.
|
||||
* Issue 21: AccessDenied exception created for raising access denied errors
|
||||
from OSError or WindowsError on individual platforms.
|
||||
* Issue 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).
|
||||
* #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
|
||||
|
||||
* Issue 16: Special case for Windows' "System Idle Process" (PID 0) which
|
||||
otherwise would return an "invalid parameter" exception.
|
||||
* Issue 17: get_process_list() ignores NoSuchProcess and AccessDenied
|
||||
exceptions during building of the list.
|
||||
* Issue 22: Process(0).kill() was failing on Windows with an unset exception
|
||||
* Issue 23: Special case for pid_exists(0)
|
||||
* Issue 24: Process(0).kill() now raises AccessDenied exception instead of
|
||||
WindowsError.
|
||||
* Issue 30: psutil.get_pid_list() was returning two instances of PID 0 on OS
|
||||
X and FreeBSD platforms.
|
||||
* #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 OS
|
||||
X and FreeBSD platforms.
|
||||
|
||||
|
||||
0.1.0 - 2009-01-27
|
||||
|
@ -1,110 +0,0 @@
|
||||
==================
|
||||
Using easy_install
|
||||
==================
|
||||
|
||||
The easiest way to install psutil from sources is using easy_install.
|
||||
Get the latest easy_install version from http://pypi.python.org/pypi/setuptools
|
||||
and just run:
|
||||
|
||||
easy_install psutil
|
||||
|
||||
This should get the most updated psutil version from the Python pypi repository,
|
||||
unpack it, compile it and install it automatically.
|
||||
|
||||
|
||||
===================================
|
||||
Installing on Windows using mingw32
|
||||
===================================
|
||||
|
||||
After the mingw [1] environment is properly set up on your system you can
|
||||
compile Windows sources by entering:
|
||||
|
||||
setup.py build -c mingw32
|
||||
|
||||
To compile and install just append the "install" keyword at the end of the
|
||||
command line above, like this:
|
||||
|
||||
setup.py build -c mingw32 install
|
||||
|
||||
It might be possible that distutils will complain about missing gcc executable.
|
||||
That means you have to add mingw bin PATH variable first.
|
||||
Entering this line in the command prompt should do the work:
|
||||
|
||||
SET PATH=C:\MinGW\bin;%PATH%
|
||||
|
||||
NOTE: this assumes MinGW is installed in C:\MinGW, if not simply replace the
|
||||
path in the command above with an appropriate location.
|
||||
|
||||
[1] http://www.mingw.org/
|
||||
|
||||
|
||||
=========================================
|
||||
Installing on Windows using Visual Studio
|
||||
=========================================
|
||||
|
||||
To use Visual Studio to install psutil, you must have the same version of
|
||||
Visual Studio used to compile your installation of Python. For older versions
|
||||
of Python that will be Visual Studio 2003. For 2.6 and later it should be
|
||||
Visual Studio 2008. If you do not have the requisite version of Visual Studio
|
||||
available then it is recommended to use MinGW to compile psutil instead.
|
||||
If you do have Visual Studio installed, you can use the basic distutils
|
||||
commands:
|
||||
|
||||
setup.py build
|
||||
|
||||
...or to install and build:
|
||||
|
||||
setup.py install
|
||||
|
||||
distutils should take care of any necessary magic to compile from there.
|
||||
|
||||
|
||||
==================
|
||||
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
|
||||
|
||||
NOTE: due to developer's hardware limitations psutil has only been compiled and
|
||||
tested on OS X 10.4.11 so may or may not work on other versions.
|
||||
|
||||
|
||||
=====================
|
||||
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
|
||||
|
||||
|
||||
===================
|
||||
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 Ubuntu:
|
||||
|
||||
sudo apt-get install python-dev
|
||||
|
||||
Once done, you can install/build psutil with:
|
||||
|
||||
python setup.py install
|
||||
|
@ -1,12 +1,12 @@
|
||||
Metadata-Version: 1.1
|
||||
Name: psutil
|
||||
Version: 0.6.1
|
||||
Version: 0.7.1
|
||||
Summary: A process and system utilities module for Python
|
||||
Home-page: http://code.google.com/p/psutil/
|
||||
Author: Giampaolo Rodola
|
||||
Author-email: g.rodola <at> gmail <dot> com
|
||||
License: License :: OSI Approved :: BSD License
|
||||
Download-URL: http://psutil.googlecode.com/files/psutil-0.6.1.tar.gz
|
||||
Download-URL: http://psutil.googlecode.com/files/psutil-0.7.1.tar.gz
|
||||
Description: ===========
|
||||
Quick links
|
||||
===========
|
||||
@ -238,6 +238,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: Topic :: System :: Monitoring
|
||||
Classifier: Topic :: System :: Networking
|
||||
Classifier: Topic :: System :: Networking :: Monitoring
|
||||
|
4
python/psutil/examples/disk_usage.py
Normal file → Executable file
4
python/psutil/examples/disk_usage.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: disk_usage.py 1340 2012-06-09 13:42:21Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/free.py
Normal file → Executable file
4
python/psutil/examples/free.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: free.py 1508 2012-08-13 12:30:07Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/iotop.py
Normal file → Executable file
4
python/psutil/examples/iotop.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: iotop.py 1236 2011-12-13 19:00:35Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/killall.py
Normal file → Executable file
4
python/psutil/examples/killall.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: killall.py 1143 2011-10-05 19:11:59Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/meminfo.py
Normal file → Executable file
4
python/psutil/examples/meminfo.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: meminfo.py 1509 2012-08-13 12:31:18Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/netstat.py
Normal file → Executable file
4
python/psutil/examples/netstat.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: netstat.py 1457 2012-07-14 18:09:36Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
0
python/psutil/examples/nettop.py
Normal file → Executable file
0
python/psutil/examples/nettop.py
Normal file → Executable file
4
python/psutil/examples/pmap.py
Normal file → Executable file
4
python/psutil/examples/pmap.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: pmap.py 1420 2012-07-08 12:12:01Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/process_detail.py
Normal file → Executable file
4
python/psutil/examples/process_detail.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: process_detail.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/top.py
Normal file → Executable file
4
python/psutil/examples/top.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: top.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
4
python/psutil/examples/who.py
Normal file → Executable file
4
python/psutil/examples/who.py
Normal file → Executable file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: who.py 1340 2012-06-09 13:42:21Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
@ -1,8 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# $Id: __init__.py 1525 2012-08-16 16:32:03Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -14,7 +12,7 @@ Python.
|
||||
|
||||
from __future__ import division
|
||||
|
||||
__version__ = "0.6.1"
|
||||
__version__ = "0.7.1"
|
||||
version_info = tuple([int(num) for num in __version__.split('.')])
|
||||
|
||||
__all__ = [
|
||||
@ -29,10 +27,12 @@ __all__ = [
|
||||
# classes
|
||||
"Process", "Popen",
|
||||
# functions
|
||||
"test", "pid_exists", "get_pid_list", "process_iter", "get_process_list",
|
||||
"virtual_memory", "swap_memory",
|
||||
"cpu_times", "cpu_percent", "per_cpu_percent",
|
||||
"network_io_counters", "disk_io_counters",
|
||||
"pid_exists", "get_pid_list", "process_iter", # proc
|
||||
"virtual_memory", "swap_memory", # memory
|
||||
"cpu_times", "cpu_percent", "cpu_times_percent", # cpu
|
||||
"network_io_counters", # network
|
||||
"disk_io_counters", "disk_partitions", "disk_usage", # disk
|
||||
"get_users", "get_boot_time", # others
|
||||
]
|
||||
|
||||
import sys
|
||||
@ -47,9 +47,10 @@ try:
|
||||
except ImportError:
|
||||
pwd = None
|
||||
|
||||
from psutil.error import Error, NoSuchProcess, AccessDenied, TimeoutExpired
|
||||
from psutil._compat import property, callable, defaultdict
|
||||
from psutil._error import Error, NoSuchProcess, AccessDenied, TimeoutExpired
|
||||
from psutil._common import cached_property
|
||||
from psutil._compat import (property, callable, defaultdict, namedtuple,
|
||||
wraps as _wraps, PY3 as _PY3)
|
||||
from psutil._common import (deprecated as _deprecated,
|
||||
nt_disk_iostat as _nt_disk_iostat,
|
||||
nt_net_iostat as _nt_net_iostat,
|
||||
@ -97,15 +98,56 @@ BOOT_TIME = _psplatform.BOOT_TIME
|
||||
TOTAL_PHYMEM = _psplatform.TOTAL_PHYMEM
|
||||
|
||||
|
||||
def _assert_pid_not_reused(fun):
|
||||
"""Decorator which raises NoSuchProcess in case a process is no
|
||||
longer running or its PID has been reused.
|
||||
"""
|
||||
@_wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
if not self.is_running():
|
||||
raise NoSuchProcess(self.pid, self._platform_impl._process_name)
|
||||
return fun(self, *args, **kwargs)
|
||||
return wrapper
|
||||
|
||||
|
||||
class Process(object):
|
||||
"""Represents an OS process."""
|
||||
|
||||
def __init__(self, pid):
|
||||
"""Create a new Process object for the given pid.
|
||||
Raises 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.
|
||||
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 are:
|
||||
- parent
|
||||
- get_children()
|
||||
- set_nice()
|
||||
- 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
|
||||
"""
|
||||
if not _PY3:
|
||||
if not isinstance(pid, (int, long)):
|
||||
raise TypeError('pid must be an integer')
|
||||
if pid < 0:
|
||||
raise ValueError('pid must be a positive integer')
|
||||
self._pid = pid
|
||||
self._gone = False
|
||||
self._ppid = None
|
||||
# platform-specific modules define an _psplatform.Process
|
||||
# implementation class
|
||||
self._platform_impl = _psplatform.Process(pid)
|
||||
@ -135,6 +177,8 @@ class Process(object):
|
||||
def __repr__(self):
|
||||
return "<%s at %s>" % (self.__str__(), id(self))
|
||||
|
||||
# --- utility methods
|
||||
|
||||
def as_dict(self, attrs=[], ad_value=None):
|
||||
"""Utility method returning process information as a hashable
|
||||
dictionary.
|
||||
@ -185,27 +229,46 @@ class Process(object):
|
||||
return retdict
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
"""The process pid."""
|
||||
return self._pid
|
||||
|
||||
@cached_property
|
||||
def ppid(self):
|
||||
"""The process parent pid."""
|
||||
return self._platform_impl.get_process_ppid()
|
||||
|
||||
@property
|
||||
@_assert_pid_not_reused
|
||||
def parent(self):
|
||||
"""Return the parent process as a Process object. If no parent
|
||||
pid is known return None.
|
||||
"""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:
|
||||
try:
|
||||
return Process(ppid)
|
||||
parent = Process(ppid)
|
||||
if parent.create_time <= self.create_time:
|
||||
return parent
|
||||
# ...else ppid has been reused by another process
|
||||
except NoSuchProcess:
|
||||
pass
|
||||
|
||||
# --- actual API
|
||||
|
||||
@property
|
||||
def pid(self):
|
||||
"""The process pid."""
|
||||
return self._pid
|
||||
|
||||
@property
|
||||
def ppid(self):
|
||||
"""The process parent pid."""
|
||||
# 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://code.google.com/p/psutil/issues/detail?id=321
|
||||
# http://stackoverflow.com/questions/356722/
|
||||
|
||||
# XXX should we check creation time here rather than in
|
||||
# Process.parent?
|
||||
if os.name == 'posix':
|
||||
return self._platform_impl.get_process_ppid()
|
||||
else:
|
||||
if self._ppid is None:
|
||||
self._ppid = self._platform_impl.get_process_ppid()
|
||||
return self._ppid
|
||||
|
||||
@cached_property
|
||||
def name(self):
|
||||
"""The process name."""
|
||||
@ -261,7 +324,7 @@ class Process(object):
|
||||
pass
|
||||
return exe
|
||||
|
||||
@cached_property
|
||||
@property
|
||||
def cmdline(self):
|
||||
"""The command line process has been called with."""
|
||||
return self._platform_impl.get_process_cmdline()
|
||||
@ -334,22 +397,37 @@ class Process(object):
|
||||
"""Get process niceness (priority)."""
|
||||
return self._platform_impl.get_process_nice()
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def set_nice(self, value):
|
||||
"""Set process niceness (priority)."""
|
||||
"""Set process niceness (priority) pre-emptively checking
|
||||
whether PID has been reused."""
|
||||
return self._platform_impl.set_process_nice(value)
|
||||
|
||||
# available only on Linux
|
||||
# available only on Linux and Windows >= Vista
|
||||
if hasattr(_psplatform.Process, "get_process_ionice"):
|
||||
|
||||
def get_ionice(self):
|
||||
"""Return process I/O niceness (priority) as a namedtuple."""
|
||||
"""Return process I/O niceness (priority).
|
||||
|
||||
On Linux this is a (ioclass, value) namedtuple.
|
||||
On Windows it's an integer which can be equal to 2 (normal),
|
||||
1 (low) or 0 (very low).
|
||||
|
||||
Available on Linux and Windows > Vista only.
|
||||
"""
|
||||
return self._platform_impl.get_process_ionice()
|
||||
|
||||
def set_ionice(self, ioclass, value=None):
|
||||
"""Set process I/O niceness (priority).
|
||||
ioclass is one of the IOPRIO_CLASS_* constants.
|
||||
iodata is a number which goes from 0 to 7. The higher the
|
||||
|
||||
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.
|
||||
"""
|
||||
return self._platform_impl.set_process_ionice(ioclass, value)
|
||||
|
||||
@ -399,9 +477,10 @@ class Process(object):
|
||||
"""
|
||||
return self._platform_impl.get_process_threads()
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def get_children(self, recursive=False):
|
||||
"""Return the children of this process as a list of Process
|
||||
objects.
|
||||
objects pre-emptively checking whether PID has been reused.
|
||||
If recursive is True return all the parent descendants.
|
||||
|
||||
Example (A == this process):
|
||||
@ -423,10 +502,6 @@ class Process(object):
|
||||
process Y won't be returned either as the reference to
|
||||
process A is lost.
|
||||
"""
|
||||
if not self.is_running():
|
||||
name = self._platform_impl._process_name
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
|
||||
ret = []
|
||||
if not recursive:
|
||||
for p in process_iter():
|
||||
@ -474,10 +549,22 @@ class Process(object):
|
||||
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.
|
||||
In this case is recommended for accuracy that this function be
|
||||
called with at least 0.1 seconds between calls.
|
||||
When interval is 0.0 or None compares process times to system
|
||||
CPU times elapsed since last call, returning immediately
|
||||
(non-blocking).
|
||||
In this case is recommended for accuracy that this function
|
||||
be called with at least 0.1 seconds between calls.
|
||||
|
||||
Examples:
|
||||
|
||||
>>> p = psutil.Process(os.getpid())
|
||||
>>> # blocking
|
||||
>>> p.get_cpu_percent(interval=1)
|
||||
2.0
|
||||
>>> # non-blocking (percentage since last call)
|
||||
>>> p.get_cpu_percent(interval=0)
|
||||
2.9
|
||||
>>>
|
||||
"""
|
||||
blocking = interval is not None and interval > 0.0
|
||||
if blocking:
|
||||
@ -544,8 +631,8 @@ class Process(object):
|
||||
return self._platform_impl.get_ext_memory_info()
|
||||
|
||||
def get_memory_percent(self):
|
||||
"""Compare physical system memory to process resident memory and
|
||||
calculate process memory utilization as a percentage.
|
||||
"""Compare physical system memory to process resident memory
|
||||
(RSS) and calculate process memory utilization as a percentage.
|
||||
"""
|
||||
rss = self._platform_impl.get_memory_info()[0]
|
||||
try:
|
||||
@ -607,7 +694,10 @@ class Process(object):
|
||||
return self._platform_impl.get_connections(kind)
|
||||
|
||||
def is_running(self):
|
||||
"""Return whether this process is running."""
|
||||
"""Return whether this process is running.
|
||||
It also checks if PID has been reused by another process in
|
||||
which case returns False.
|
||||
"""
|
||||
if self._gone:
|
||||
return False
|
||||
try:
|
||||
@ -621,16 +711,13 @@ class Process(object):
|
||||
self._gone = True
|
||||
return False
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def send_signal(self, sig):
|
||||
"""Send a signal to process (see signal module constants).
|
||||
"""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().
|
||||
"""
|
||||
# safety measure in case the current process has been killed in
|
||||
# meantime and the kernel reused its PID
|
||||
if not self.is_running():
|
||||
name = self._platform_impl._process_name
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
if os.name == 'posix':
|
||||
try:
|
||||
os.kill(self.pid, sig)
|
||||
@ -638,6 +725,7 @@ class Process(object):
|
||||
err = sys.exc_info()[1]
|
||||
name = self._platform_impl._process_name
|
||||
if err.errno == errno.ESRCH:
|
||||
self._gone = True
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
if err.errno == errno.EPERM:
|
||||
raise AccessDenied(self.pid, name)
|
||||
@ -648,47 +736,43 @@ class Process(object):
|
||||
else:
|
||||
raise ValueError("only SIGTERM is supported on Windows")
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def suspend(self):
|
||||
"""Suspend process execution."""
|
||||
# safety measure in case the current process has been killed in
|
||||
# meantime and the kernel reused its PID
|
||||
if not self.is_running():
|
||||
name = self._platform_impl._process_name
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
# windows
|
||||
"""Suspend process execution with SIGSTOP pre-emptively checking
|
||||
whether PID has been reused.
|
||||
On Windows it suspends all process threads.
|
||||
"""
|
||||
if hasattr(self._platform_impl, "suspend_process"):
|
||||
# windows
|
||||
self._platform_impl.suspend_process()
|
||||
else:
|
||||
# posix
|
||||
self.send_signal(signal.SIGSTOP)
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def resume(self):
|
||||
"""Resume process execution."""
|
||||
# safety measure in case the current process has been killed in
|
||||
# meantime and the kernel reused its PID
|
||||
if not self.is_running():
|
||||
name = self._platform_impl._process_name
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
# windows
|
||||
"""Resume process execution with SIGCONT pre-emptively checking
|
||||
whether PID has been reused.
|
||||
On Windows it resumes all process threads.
|
||||
"""
|
||||
if hasattr(self._platform_impl, "resume_process"):
|
||||
# windows
|
||||
self._platform_impl.resume_process()
|
||||
else:
|
||||
# posix
|
||||
self.send_signal(signal.SIGCONT)
|
||||
|
||||
def terminate(self):
|
||||
"""Terminate the process with SIGTERM.
|
||||
"""Terminate the process with SIGTERM pre-emptively checking
|
||||
whether PID has been reused.
|
||||
On Windows this is an alias for kill().
|
||||
"""
|
||||
self.send_signal(signal.SIGTERM)
|
||||
|
||||
@_assert_pid_not_reused
|
||||
def kill(self):
|
||||
"""Kill the current process."""
|
||||
# safety measure in case the current process has been killed in
|
||||
# meantime and the kernel reused its PID
|
||||
if not self.is_running():
|
||||
name = self._platform_impl._process_name
|
||||
raise NoSuchProcess(self.pid, name)
|
||||
"""Kill the current process with SIGKILL pre-emptively checking
|
||||
whether PID has been reused."""
|
||||
if os.name == 'posix':
|
||||
self.send_signal(signal.SIGKILL)
|
||||
else:
|
||||
@ -755,6 +839,7 @@ class Popen(Process):
|
||||
self.__subproc = subprocess.Popen(*args, **kwargs)
|
||||
self._pid = self.__subproc.pid
|
||||
self._gone = False
|
||||
self._ppid = None
|
||||
self._platform_impl = _psplatform.Process(self._pid)
|
||||
self._last_sys_cpu_times = None
|
||||
self._last_proc_cpu_times = None
|
||||
@ -764,7 +849,7 @@ class Popen(Process):
|
||||
pass
|
||||
except NoSuchProcess:
|
||||
raise NoSuchProcess(self._pid, None,
|
||||
"no process found with pid %s" % pid)
|
||||
"no process found with pid %s" % self._pid)
|
||||
|
||||
def __dir__(self):
|
||||
return list(set(dir(Popen) + dir(subprocess.Popen)))
|
||||
@ -796,6 +881,10 @@ def process_iter():
|
||||
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.
|
||||
"""
|
||||
@ -850,6 +939,9 @@ def cpu_times(percpu=False):
|
||||
- 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 nameduples for each CPU.
|
||||
First element of the list refers to first CPU, second element
|
||||
@ -882,6 +974,21 @@ def cpu_percent(interval=0.1, percpu=False):
|
||||
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=0)
|
||||
2.9
|
||||
>>>
|
||||
"""
|
||||
global _last_cpu_times
|
||||
global _last_per_cpu_times
|
||||
@ -925,6 +1032,68 @@ def cpu_percent(interval=0.1, percpu=False):
|
||||
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
|
||||
_ptime_cpu_perc_nt = None
|
||||
|
||||
def cpu_times_percent(interval=0.1, 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):
|
||||
global _ptime_cpu_perc_nt
|
||||
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
|
||||
nums.append(round(field_perc, 1))
|
||||
if _ptime_cpu_perc_nt is None:
|
||||
_ptime_cpu_perc_nt = namedtuple('cpupercent', ' '.join(t1._fields))
|
||||
return _ptime_cpu_perc_nt(*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
|
||||
# =====================================================================
|
||||
@ -1035,6 +1204,9 @@ def disk_io_counters(perdisk=False):
|
||||
physical disk installed on the system as a dictionary
|
||||
with partition names as the keys and the namedutuple
|
||||
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:
|
||||
@ -1083,6 +1255,12 @@ def network_io_counters(pernic=False):
|
||||
# --- other system related functions
|
||||
# =====================================================================
|
||||
|
||||
def get_boot_time():
|
||||
"""Return the system boot time expressed in seconds since the epoch.
|
||||
This is also available as psutil.BOOT_TIME.
|
||||
"""
|
||||
return _psplatform.get_system_boot_time()
|
||||
|
||||
def get_users():
|
||||
"""Return users currently connected on the system as a list of
|
||||
namedtuples including the following attributes.
|
||||
@ -1166,6 +1344,8 @@ def test():
|
||||
ctime = ctime.strftime("%H:%M")
|
||||
else:
|
||||
ctime = ctime.strftime("%b%d")
|
||||
else:
|
||||
ctime = ''
|
||||
cputime = time.strftime("%M:%S", time.localtime(sum(pinfo['cpu_times'])))
|
||||
user = pinfo['username']
|
||||
if os.name == 'nt' and '\\' in user:
|
||||
|
@ -1,7 +1,5 @@
|
||||
#/usr/bin/env python
|
||||
#
|
||||
#$Id: _common.py 1524 2012-08-16 15:06:32Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -169,7 +167,6 @@ del AF_INET, AF_INET6, AF_UNIX, SOCK_STREAM, SOCK_DGRAM, socket
|
||||
# --- namedtuples
|
||||
|
||||
# system
|
||||
nt_sys_cputimes = namedtuple('cputimes', 'user nice system idle iowait irq softirq')
|
||||
nt_sysmeminfo = namedtuple('usage', 'total used free percent')
|
||||
# XXX - would 'available' be better than 'free' as for virtual_memory() nt?
|
||||
nt_swapmeminfo = namedtuple('swap', 'total used free percent sin sout')
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _compat.py 1524 2012-08-16 15:06:32Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
73
python/psutil/psutil/_error.py
Normal file
73
python/psutil/psutil/_error.py
Normal file
@ -0,0 +1,73 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# 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.
|
||||
|
||||
"""psutil exception classes.
|
||||
Not supposed to be used / imported directly.
|
||||
Instead use psutil.NoSuchProcess, etc.
|
||||
"""
|
||||
|
||||
|
||||
class Error(Exception):
|
||||
"""Base exception class. All other psutil exceptions inherit
|
||||
from this one.
|
||||
"""
|
||||
|
||||
class NoSuchProcess(Error):
|
||||
"""Exception raised when a process with a certain PID doesn't
|
||||
or no longer exists (zombie).
|
||||
"""
|
||||
|
||||
def __init__(self, pid, name=None, msg=None):
|
||||
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
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class AccessDenied(Error):
|
||||
"""Exception raised when permission to perform an action is denied."""
|
||||
|
||||
def __init__(self, pid=None, name=None, msg=None):
|
||||
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 = ""
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class TimeoutExpired(Error):
|
||||
"""Raised on Process.wait(timeout) if timeout expires and process
|
||||
is still alive.
|
||||
"""
|
||||
|
||||
def __init__(self, pid=None, name=None):
|
||||
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
|
||||
else:
|
||||
self.msg = ""
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _psbsd.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -11,27 +9,47 @@
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import _psutil_bsd
|
||||
import _psutil_posix
|
||||
from psutil import _psposix
|
||||
from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._compat import namedtuple
|
||||
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._compat import namedtuple, wraps
|
||||
from psutil._common import *
|
||||
|
||||
__extra__all__ = []
|
||||
|
||||
# --- constants
|
||||
|
||||
NUM_CPUS = _psutil_bsd.get_num_cpus()
|
||||
BOOT_TIME = _psutil_bsd.get_system_boot_time()
|
||||
TOTAL_PHYMEM = _psutil_bsd.get_virtual_mem()[0]
|
||||
_TERMINAL_MAP = _psposix._get_terminal_map()
|
||||
# Since these constants get determined at import time we do not want to
|
||||
# crash immediately; instead we'll set them to None and most likely
|
||||
# we'll crash later as they're used for determining process CPU stats
|
||||
# and creation_time
|
||||
try:
|
||||
NUM_CPUS = _psutil_bsd.get_num_cpus()
|
||||
except Exception:
|
||||
NUM_CPUS = None
|
||||
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
|
||||
try:
|
||||
TOTAL_PHYMEM = _psutil_bsd.get_virtual_mem()[0]
|
||||
except Exception:
|
||||
TOTAL_PHYMEM = None
|
||||
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
|
||||
try:
|
||||
BOOT_TIME = _psutil_bsd.get_system_boot_time()
|
||||
except Exception:
|
||||
BOOT_TIME = None
|
||||
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
|
||||
|
||||
|
||||
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
_cputimes_ntuple = namedtuple('cputimes', 'user nice system idle irq')
|
||||
|
||||
# --- public functions
|
||||
|
||||
get_system_boot_time = _psutil_bsd.get_system_boot_time
|
||||
|
||||
nt_virtmem_info = namedtuple('vmem', ' '.join([
|
||||
# all platforms
|
||||
'total', 'available', 'percent', 'used', 'free',
|
||||
@ -124,14 +142,14 @@ network_io_counters = _psutil_bsd.get_network_io_counters
|
||||
disk_io_counters = _psutil_bsd.get_disk_io_counters
|
||||
|
||||
|
||||
def wrap_exceptions(method):
|
||||
"""Call method(self, pid) into a try/except clause so that if an
|
||||
OSError "No such process" exception is raised we assume the process
|
||||
has died and raise psutil.NoSuchProcess instead.
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return method(self, *args, **kwargs)
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ESRCH:
|
||||
@ -179,8 +197,9 @@ class Process(object):
|
||||
@wrap_exceptions
|
||||
def get_process_terminal(self):
|
||||
tty_nr = _psutil_bsd.get_process_tty_nr(self.pid)
|
||||
tmap = _psposix._get_terminal_map()
|
||||
try:
|
||||
return _TERMINAL_MAP[tty_nr]
|
||||
return tmap[tty_nr]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
180
python/psutil/psutil/_pslinux.py
Executable file → Normal file
180
python/psutil/psutil/_pslinux.py
Executable file → Normal file
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _pslinux.py 1513 2012-08-14 11:01:37Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -17,13 +15,14 @@ import struct
|
||||
import sys
|
||||
import base64
|
||||
import re
|
||||
import warnings
|
||||
|
||||
import _psutil_posix
|
||||
import _psutil_linux
|
||||
from psutil import _psposix
|
||||
from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._common import *
|
||||
from psutil._compat import PY3, xrange, long, namedtuple
|
||||
from psutil._compat import PY3, xrange, long, namedtuple, wraps
|
||||
|
||||
__extra__all__ = [
|
||||
"IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE",
|
||||
@ -31,22 +30,19 @@ __extra__all__ = [
|
||||
"phymem_buffers", "cached_phymem"]
|
||||
|
||||
|
||||
def _get_boot_time():
|
||||
"""Return system boot time (epoch in seconds)"""
|
||||
def get_system_boot_time():
|
||||
"""Return the system boot time expressed in seconds since the epoch."""
|
||||
f = open('/proc/stat', 'r')
|
||||
try:
|
||||
for line in f:
|
||||
if line.startswith('btime'):
|
||||
return float(line.strip().split()[1])
|
||||
raise RuntimeError("line not found")
|
||||
raise RuntimeError("line 'btime' not found")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
def _get_num_cpus():
|
||||
"""Return the number of CPUs on the system"""
|
||||
# we try to determine num CPUs by using different approaches.
|
||||
# SC_NPROCESSORS_ONLN seems to be the safer and it is also
|
||||
# used by multiprocessing module
|
||||
try:
|
||||
return os.sysconf("SC_NPROCESSORS_ONLN")
|
||||
except ValueError:
|
||||
@ -77,17 +73,35 @@ def _get_num_cpus():
|
||||
num += 1
|
||||
|
||||
if num == 0:
|
||||
raise RuntimeError("can't determine number of CPUs")
|
||||
raise RuntimeError("couldn't determine platform's NUM_CPUS")
|
||||
return num
|
||||
|
||||
|
||||
# Number of clock ticks per second
|
||||
_CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"])
|
||||
_CLOCK_TICKS = os.sysconf("SC_CLK_TCK")
|
||||
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
_TERMINAL_MAP = _psposix._get_terminal_map()
|
||||
BOOT_TIME = _get_boot_time()
|
||||
NUM_CPUS = _get_num_cpus()
|
||||
TOTAL_PHYMEM = _psutil_linux.get_sysinfo()[0]
|
||||
|
||||
# Since these constants get determined at import time we do not want to
|
||||
# crash immediately; instead we'll set them to None and most likely
|
||||
# we'll crash later as they're used for determining process CPU stats
|
||||
# and creation_time
|
||||
try:
|
||||
BOOT_TIME = get_system_boot_time()
|
||||
except Exception:
|
||||
BOOT_TIME = None
|
||||
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
|
||||
try:
|
||||
NUM_CPUS = _get_num_cpus()
|
||||
except Exception:
|
||||
NUM_CPUS = None
|
||||
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
|
||||
try:
|
||||
TOTAL_PHYMEM = _psutil_linux.get_sysinfo()[0]
|
||||
except Exception:
|
||||
TOTAL_PHYMEM = None
|
||||
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
|
||||
|
||||
|
||||
# ioprio_* constants http://linux.die.net/man/2/ioprio_get
|
||||
IOPRIO_CLASS_NONE = 0
|
||||
IOPRIO_CLASS_RT = 1
|
||||
@ -136,7 +150,12 @@ def virtual_memory():
|
||||
and inactive is not None:
|
||||
break
|
||||
else:
|
||||
raise RuntimeError("line(s) not found")
|
||||
# we might get here when dealing with exotic Linux flavors, see:
|
||||
# http://code.google.com/p/psutil/issues/detail?id=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
|
||||
finally:
|
||||
f.close()
|
||||
avail = free + buffers + cached
|
||||
@ -162,7 +181,12 @@ def swap_memory():
|
||||
if sin is not None and sout is not None:
|
||||
break
|
||||
else:
|
||||
raise RuntimeError("line(s) not found")
|
||||
# we might get here when dealing with exotic Linux flavors, see:
|
||||
# http://code.google.com/p/psutil/issues/detail?id=313
|
||||
msg = "'sin' and 'sout' swap memory stats couldn't " \
|
||||
"be determined and were set to 0"
|
||||
warnings.warn(msg, RuntimeWarning)
|
||||
sin = sout = 0
|
||||
finally:
|
||||
f.close()
|
||||
return nt_swapmeminfo(total, used, free, percent, sin, sout)
|
||||
@ -180,34 +204,65 @@ def phymem_buffers():
|
||||
|
||||
# --- system CPU functions
|
||||
|
||||
@memoize
|
||||
def _get_cputimes_ntuple():
|
||||
""" Return a (nt, rindex) tuple 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]]]
|
||||
"""
|
||||
f = open('/proc/stat', 'r')
|
||||
try:
|
||||
values = f.readline().split()[1:]
|
||||
finally:
|
||||
f.close()
|
||||
fields = ['user', 'nice', 'system', 'idle', 'iowait', 'irq', 'softirq']
|
||||
rindex = 8
|
||||
vlen = len(values)
|
||||
if vlen >= 8:
|
||||
# Linux >= 2.6.11
|
||||
fields.append('steal')
|
||||
rindex += 1
|
||||
if vlen >= 9:
|
||||
# Linux >= 2.6.24
|
||||
fields.append('guest')
|
||||
rindex += 1
|
||||
if vlen >= 10:
|
||||
# Linux >= 3.2.0
|
||||
fields.append('guest_nice')
|
||||
rindex += 1
|
||||
return (namedtuple('cputimes', ' '.join(fields)), rindex)
|
||||
|
||||
def get_system_cpu_times():
|
||||
"""Return a named tuple representing the following CPU times:
|
||||
user, nice, system, idle, iowait, irq, softirq.
|
||||
"""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.
|
||||
"""
|
||||
f = open('/proc/stat', 'r')
|
||||
try:
|
||||
values = f.readline().split()
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
values = values[1:8]
|
||||
values = tuple([float(x) / _CLOCK_TICKS for x in values])
|
||||
return nt_sys_cputimes(*values[:7])
|
||||
nt, rindex = _get_cputimes_ntuple()
|
||||
fields = values[1:rindex]
|
||||
fields = [float(x) / _CLOCK_TICKS for x in fields]
|
||||
return nt(*fields)
|
||||
|
||||
def get_system_per_cpu_times():
|
||||
"""Return a list of namedtuple representing the CPU times
|
||||
for every CPU available on the system.
|
||||
"""
|
||||
nt, rindex = _get_cputimes_ntuple()
|
||||
cpus = []
|
||||
f = open('/proc/stat', 'r')
|
||||
# get rid of the first line who refers to system wide CPU stats
|
||||
try:
|
||||
# get rid of the first line which refers to system wide CPU stats
|
||||
f.readline()
|
||||
for line in f.readlines():
|
||||
for line in f:
|
||||
if line.startswith('cpu'):
|
||||
values = line.split()[1:8]
|
||||
values = tuple([float(x) / _CLOCK_TICKS for x in values])
|
||||
entry = nt_sys_cputimes(*values[:7])
|
||||
fields = line.split()[1:rindex]
|
||||
fields = [float(x) / _CLOCK_TICKS for x in fields]
|
||||
entry = nt(*fields)
|
||||
cpus.append(entry)
|
||||
return cpus
|
||||
finally:
|
||||
@ -251,7 +306,7 @@ def get_system_users():
|
||||
rawlist = _psutil_linux.get_system_users()
|
||||
for item in rawlist:
|
||||
user, tty, hostname, tstamp, user_process = item
|
||||
# XXX the underlying C function includes entries about
|
||||
# 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:
|
||||
@ -317,10 +372,19 @@ def disk_io_counters():
|
||||
lines = f.readlines()[2:]
|
||||
finally:
|
||||
f.close()
|
||||
for line in lines:
|
||||
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:
|
||||
# http://code.google.com/p/psutil/issues/detail?id=338
|
||||
partitions.append(name)
|
||||
#
|
||||
retdict = {}
|
||||
f = open("/proc/diskstats", "r")
|
||||
@ -336,8 +400,6 @@ def disk_io_counters():
|
||||
wbytes = int(wbytes) * SECTOR_SIZE
|
||||
reads = int(reads)
|
||||
writes = int(writes)
|
||||
# TODO: times are expressed in milliseconds while OSX/BSD has
|
||||
# these expressed in nanoseconds; figure this out.
|
||||
rtime = int(rtime)
|
||||
wtime = int(wtime)
|
||||
retdict[name] = (reads, writes, rbytes, wbytes, rtime, wtime)
|
||||
@ -358,13 +420,14 @@ _status_map = {"R" : STATUS_RUNNING,
|
||||
|
||||
# --- decorators
|
||||
|
||||
def wrap_exceptions(callable):
|
||||
"""Call callable into a try/except clause and translate ENOENT,
|
||||
EACCES and EPERM in NoSuchProcess or AccessDenied exceptions.
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError and IOError exceptions
|
||||
into NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return callable(self, *args, **kwargs)
|
||||
return fun(self, *args, **kwargs)
|
||||
except EnvironmentError:
|
||||
# ENOENT (no such file or directory) gets raised on open().
|
||||
# ESRCH (no such process) can get raised on read() if
|
||||
@ -384,8 +447,6 @@ class Process(object):
|
||||
__slots__ = ["pid", "_process_name"]
|
||||
|
||||
def __init__(self, pid):
|
||||
if not isinstance(pid, int):
|
||||
raise TypeError('pid must be an integer')
|
||||
self.pid = pid
|
||||
self._process_name = None
|
||||
|
||||
@ -440,13 +501,14 @@ class Process(object):
|
||||
|
||||
@wrap_exceptions
|
||||
def get_process_terminal(self):
|
||||
tmap = _psposix._get_terminal_map()
|
||||
f = open("/proc/%s/stat" % self.pid)
|
||||
try:
|
||||
tty_nr = int(f.read().split(' ')[6])
|
||||
finally:
|
||||
f.close()
|
||||
try:
|
||||
return _TERMINAL_MAP[tty_nr]
|
||||
return tmap[tty_nr]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
@ -469,7 +531,8 @@ class Process(object):
|
||||
|
||||
if not os.path.exists('/proc/%s/io' % os.getpid()):
|
||||
def get_process_io_counters(self):
|
||||
raise NotImplementedError('/proc/PID/io is not available')
|
||||
raise NotImplementedError("couldn't find /proc/%s/io (kernel " \
|
||||
"too old?)" % self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def get_cpu_times(self):
|
||||
@ -583,13 +646,15 @@ class Process(object):
|
||||
path = path.strip()
|
||||
yield (addr, perms, path,
|
||||
data['Rss:'],
|
||||
data['Size:'],
|
||||
data.get('Size:', 0),
|
||||
data.get('Pss:', 0),
|
||||
data['Shared_Clean:'], data['Shared_Clean:'],
|
||||
data['Private_Clean:'], data['Private_Dirty:'],
|
||||
data['Referenced:'],
|
||||
data['Anonymous:'],
|
||||
data['Swap:'])
|
||||
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))
|
||||
f.close()
|
||||
except EnvironmentError:
|
||||
# XXX - Can't use wrap_exceptions decorator as we're
|
||||
@ -607,12 +672,12 @@ class Process(object):
|
||||
if f is not None:
|
||||
f.close()
|
||||
raise
|
||||
f.close()
|
||||
|
||||
if not os.path.exists('/proc/%s/smaps' % os.getpid()):
|
||||
def get_shared_libs(self, ext):
|
||||
msg = "this Linux version does not support /proc/PID/smaps " \
|
||||
"(kernel < 2.6.14 or CONFIG_MMU kernel configuration " \
|
||||
"option is not enabled)"
|
||||
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
|
||||
@ -635,7 +700,10 @@ class Process(object):
|
||||
unvol = int(line.split()[1])
|
||||
if vol is not None and unvol is not None:
|
||||
return nt_ctxsw(vol, unvol)
|
||||
raise RuntimeError("line not found")
|
||||
raise NotImplementedError("the '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)
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@ -646,7 +714,7 @@ class Process(object):
|
||||
for line in f:
|
||||
if line.startswith("Threads:"):
|
||||
return int(line.split()[1])
|
||||
raise RuntimeError("line not found")
|
||||
raise NotImplementedError("line not found")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@ -936,7 +1004,7 @@ class Process(object):
|
||||
if line.startswith("PPid:"):
|
||||
# PPid: nnnn
|
||||
return int(line.split()[1])
|
||||
raise RuntimeError("line not found")
|
||||
raise NotImplementedError("line not found")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@ -948,7 +1016,7 @@ class Process(object):
|
||||
if line.startswith('Uid:'):
|
||||
_, real, effective, saved, fs = line.split()
|
||||
return nt_uids(int(real), int(effective), int(saved))
|
||||
raise RuntimeError("line not found")
|
||||
raise NotImplementedError("line not found")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
@ -960,7 +1028,7 @@ class Process(object):
|
||||
if line.startswith('Gid:'):
|
||||
_, real, effective, saved, fs = line.split()
|
||||
return nt_gids(int(real), int(effective), int(saved))
|
||||
raise RuntimeError("line not found")
|
||||
raise NotImplementedError("line not found")
|
||||
finally:
|
||||
f.close()
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _psmswindows.py 1514 2012-08-14 11:16:56Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -12,12 +10,13 @@ import errno
|
||||
import os
|
||||
import sys
|
||||
import platform
|
||||
import warnings
|
||||
|
||||
import _psutil_mswindows
|
||||
from _psutil_mswindows import ERROR_ACCESS_DENIED
|
||||
from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._common import *
|
||||
from psutil._compat import PY3, xrange, long
|
||||
from psutil._compat import PY3, xrange, long, wraps
|
||||
|
||||
# Windows specific extended namespace
|
||||
__extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
|
||||
@ -27,9 +26,26 @@ __extra__all__ = ["ABOVE_NORMAL_PRIORITY_CLASS", "BELOW_NORMAL_PRIORITY_CLASS",
|
||||
|
||||
# --- module level constants (gets pushed up to psutil module)
|
||||
|
||||
NUM_CPUS = _psutil_mswindows.get_num_cpus()
|
||||
BOOT_TIME = _psutil_mswindows.get_system_uptime()
|
||||
TOTAL_PHYMEM = _psutil_mswindows.get_virtual_mem()[0]
|
||||
# Since these constants get determined at import time we do not want to
|
||||
# crash immediately; instead we'll set them to None and most likely
|
||||
# we'll crash later as they're used for determining process CPU stats
|
||||
# and creation_time
|
||||
try:
|
||||
NUM_CPUS = _psutil_mswindows.get_num_cpus()
|
||||
except Exception:
|
||||
NUM_CPUS = None
|
||||
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
|
||||
try:
|
||||
BOOT_TIME = _psutil_mswindows.get_system_boot_time()
|
||||
except Exception:
|
||||
BOOT_TIME = None
|
||||
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
|
||||
try:
|
||||
TOTAL_PHYMEM = _psutil_mswindows.get_virtual_mem()[0]
|
||||
except Exception:
|
||||
TOTAL_PHYMEM = None
|
||||
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
|
||||
|
||||
WAIT_TIMEOUT = 0x00000102 # 258 in decimal
|
||||
ACCESS_DENIED_SET = frozenset([errno.EPERM, errno.EACCES, ERROR_ACCESS_DENIED])
|
||||
|
||||
@ -60,6 +76,8 @@ def _convert_raw_path(s):
|
||||
|
||||
# --- public functions
|
||||
|
||||
get_system_boot_time = _psutil_mswindows.get_system_boot_time
|
||||
|
||||
nt_virtmem_info = namedtuple('vmem', ' '.join([
|
||||
# all platforms
|
||||
'total', 'available', 'percent', 'used', 'free']))
|
||||
@ -142,14 +160,14 @@ disk_io_counters = _psutil_mswindows.get_disk_io_counters
|
||||
|
||||
# --- decorator
|
||||
|
||||
def wrap_exceptions(callable):
|
||||
"""Call callable into a try/except clause so that if a
|
||||
WindowsError 5 AccessDenied exception is raised we translate it
|
||||
into psutil.AccessDenied
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError and WindowsError
|
||||
exceptions into NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return callable(self, *args, **kwargs)
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno in ACCESS_DENIED_SET:
|
||||
@ -359,6 +377,22 @@ class Process(object):
|
||||
def set_process_nice(self, value):
|
||||
return _psutil_mswindows.set_process_priority(self.pid, value)
|
||||
|
||||
# available on Windows >= Vista
|
||||
if hasattr(_psutil_mswindows, "get_process_io_priority"):
|
||||
@wrap_exceptions
|
||||
def get_process_ionice(self):
|
||||
return _psutil_mswindows.get_process_io_priority(self.pid)
|
||||
|
||||
@wrap_exceptions
|
||||
def set_process_ionice(self, value, _):
|
||||
if _:
|
||||
raise TypeError("set_process_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 _psutil_mswindows.set_process_io_priority(self.pid, value)
|
||||
|
||||
@wrap_exceptions
|
||||
def get_process_io_counters(self):
|
||||
try:
|
||||
@ -392,8 +426,6 @@ class Process(object):
|
||||
raise ValueError("invalid argument %r" % l)
|
||||
out = 0
|
||||
for b in l:
|
||||
if not isinstance(b, (int, long)) or b < 0:
|
||||
raise ValueError("invalid argument %r" % b)
|
||||
out |= 2**b
|
||||
return out
|
||||
|
||||
@ -403,7 +435,7 @@ class Process(object):
|
||||
allcpus = list(range(len(get_system_per_cpu_times())))
|
||||
for cpu in value:
|
||||
if cpu not in allcpus:
|
||||
raise ValueError("invalid CPU %i" % cpu)
|
||||
raise ValueError("invalid CPU %r" % cpu)
|
||||
|
||||
bitmask = to_bitmask(value)
|
||||
_psutil_mswindows.set_process_cpu_affinity(self.pid, bitmask)
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _psosx.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -11,27 +9,46 @@
|
||||
import errno
|
||||
import os
|
||||
import sys
|
||||
import warnings
|
||||
|
||||
import _psutil_osx
|
||||
import _psutil_posix
|
||||
from psutil import _psposix
|
||||
from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._compat import namedtuple
|
||||
from psutil._error import AccessDenied, NoSuchProcess, TimeoutExpired
|
||||
from psutil._compat import namedtuple, wraps
|
||||
from psutil._common import *
|
||||
|
||||
__extra__all__ = []
|
||||
|
||||
# --- constants
|
||||
|
||||
NUM_CPUS = _psutil_osx.get_num_cpus()
|
||||
BOOT_TIME = _psutil_osx.get_system_boot_time()
|
||||
TOTAL_PHYMEM = _psutil_osx.get_virtual_mem()[0]
|
||||
# Since these constants get determined at import time we do not want to
|
||||
# crash immediately; instead we'll set them to None and most likely
|
||||
# we'll crash later as they're used for determining process CPU stats
|
||||
# and creation_time
|
||||
try:
|
||||
NUM_CPUS = _psutil_osx.get_num_cpus()
|
||||
except Exception:
|
||||
NUM_CPUS = None
|
||||
warnings.warn("couldn't determine platform's NUM_CPUS", RuntimeWarning)
|
||||
try:
|
||||
BOOT_TIME = _psutil_osx.get_system_boot_time()
|
||||
except Exception:
|
||||
BOOT_TIME = None
|
||||
warnings.warn("couldn't determine platform's BOOT_TIME", RuntimeWarning)
|
||||
try:
|
||||
TOTAL_PHYMEM = _psutil_osx.get_virtual_mem()[0]
|
||||
except Exception:
|
||||
TOTAL_PHYMEM = None
|
||||
warnings.warn("couldn't determine platform's TOTAL_PHYMEM", RuntimeWarning)
|
||||
|
||||
_PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
_TERMINAL_MAP = _psposix._get_terminal_map()
|
||||
_cputimes_ntuple = namedtuple('cputimes', 'user nice system idle')
|
||||
|
||||
# --- functions
|
||||
|
||||
get_system_boot_time = _psutil_osx.get_system_boot_time
|
||||
|
||||
nt_virtmem_info = namedtuple('vmem', ' '.join([
|
||||
# all platforms
|
||||
'total', 'available', 'percent', 'used', 'free',
|
||||
@ -106,14 +123,14 @@ disk_io_counters = _psutil_osx.get_disk_io_counters
|
||||
|
||||
# --- decorator
|
||||
|
||||
def wrap_exceptions(callable):
|
||||
"""Call callable into a try/except clause so that if an
|
||||
OSError EPERM exception is raised we translate it into
|
||||
psutil.AccessDenied.
|
||||
def wrap_exceptions(fun):
|
||||
"""Decorator which translates bare OSError exceptions into
|
||||
NoSuchProcess and AccessDenied.
|
||||
"""
|
||||
@wraps(fun)
|
||||
def wrapper(self, *args, **kwargs):
|
||||
try:
|
||||
return callable(self, *args, **kwargs)
|
||||
return fun(self, *args, **kwargs)
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno == errno.ESRCH:
|
||||
@ -179,8 +196,9 @@ class Process(object):
|
||||
@wrap_exceptions
|
||||
def get_process_terminal(self):
|
||||
tty_nr = _psutil_osx.get_process_tty_nr(self.pid)
|
||||
tmap = _psposix._get_terminal_map()
|
||||
try:
|
||||
return _TERMINAL_MAP[tty_nr]
|
||||
return tmap[tty_nr]
|
||||
except KeyError:
|
||||
return None
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _psposix.py 1409 2012-07-04 08:21:06Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -15,14 +13,12 @@ import sys
|
||||
import time
|
||||
import glob
|
||||
|
||||
from psutil.error import TimeoutExpired
|
||||
from psutil._common import nt_diskinfo, usage_percent
|
||||
from psutil._error import TimeoutExpired
|
||||
from psutil._common import nt_diskinfo, usage_percent, memoize
|
||||
|
||||
|
||||
def pid_exists(pid):
|
||||
"""Check whether pid exists in the current process table."""
|
||||
if not isinstance(pid, int):
|
||||
raise TypeError('an integer is required')
|
||||
if pid < 0:
|
||||
return False
|
||||
try:
|
||||
@ -46,14 +42,15 @@ def wait_pid(pid, timeout=None):
|
||||
"""
|
||||
def check_timeout(delay):
|
||||
if timeout is not None:
|
||||
if time.time() >= stop_at:
|
||||
if timer() >= stop_at:
|
||||
raise TimeoutExpired(pid)
|
||||
time.sleep(delay)
|
||||
return min(delay * 2, 0.04)
|
||||
|
||||
timer = getattr(time, 'monotonic', time.time)
|
||||
if timeout is not None:
|
||||
waitcall = lambda: os.waitpid(pid, os.WNOHANG)
|
||||
stop_at = time.time() + timeout
|
||||
stop_at = timer() + timeout
|
||||
else:
|
||||
waitcall = lambda: os.waitpid(pid, 0)
|
||||
|
||||
@ -109,10 +106,16 @@ def get_disk_usage(path):
|
||||
# http://goo.gl/sWGbH
|
||||
return nt_diskinfo(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
|
||||
ret[os.stat(name).st_rdev] = name
|
||||
try:
|
||||
ret[os.stat(name).st_rdev] = name
|
||||
except OSError:
|
||||
err = sys.exc_info()[1]
|
||||
if err.errno != errno.ENOENT:
|
||||
raise
|
||||
return ret
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_bsd.c 1513 2012-08-14 11:01:37Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -8,6 +6,7 @@
|
||||
* FreeBSD platform-specific module methods for _psutil_bsd
|
||||
*/
|
||||
|
||||
|
||||
#include <Python.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
@ -15,6 +14,7 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/param.h>
|
||||
@ -24,19 +24,13 @@
|
||||
#include <net/route.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <sys/socketvar.h> /* for struct socket */
|
||||
#include <sys/protosw.h> /* for struct proto */
|
||||
#include <sys/domain.h> /* for struct domain */
|
||||
|
||||
#include <sys/un.h> /* for unpcb struct (UNIX sockets) */
|
||||
#include <sys/unpcb.h> /* for unpcb struct (UNIX sockets) */
|
||||
#include <sys/mbuf.h> /* for mbuf struct (UNIX sockets) */
|
||||
/* for in_pcb struct */
|
||||
#include <sys/socketvar.h> /* for struct xsocket */
|
||||
/* 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 tcpcb */
|
||||
#include <netinet/tcp_var.h> /* for struct xtcpcb */
|
||||
#include <netinet/tcp_fsm.h> /* for TCP connection states */
|
||||
#include <arpa/inet.h> /* for inet_ntop() */
|
||||
|
||||
@ -70,7 +64,7 @@
|
||||
* Utility function which fills a kinfo_proc struct based on process pid
|
||||
*/
|
||||
static int
|
||||
get_kinfo_proc(const pid_t pid, struct kinfo_proc *proc)
|
||||
psutil_get_kinfo_proc(const pid_t pid, struct kinfo_proc *proc)
|
||||
{
|
||||
int mib[4];
|
||||
size_t size;
|
||||
@ -110,7 +104,10 @@ get_pid_list(PyObject* self, PyObject* args)
|
||||
PyObject* retlist = PyList_New(0);
|
||||
PyObject* pid = NULL;
|
||||
|
||||
if (get_proc_list(&proclist, &num_processes) != 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;
|
||||
}
|
||||
@ -150,16 +147,14 @@ get_system_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;
|
||||
struct timeval boottime;
|
||||
size_t len = sizeof(boottime);
|
||||
|
||||
if (sysctl(request, 2, &result, &result_len, NULL, 0) == -1) {
|
||||
if (sysctl(request, 2, &boottime, &len, NULL, 0) == -1) {
|
||||
PyErr_SetFromErrno(0);
|
||||
return NULL;
|
||||
}
|
||||
boot_time = result.tv_sec;
|
||||
return Py_BuildValue("f", (float)boot_time);
|
||||
return Py_BuildValue("d", (double)boottime.tv_sec);
|
||||
}
|
||||
|
||||
|
||||
@ -174,7 +169,7 @@ get_process_name(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("s", kp.ki_comm);
|
||||
@ -198,10 +193,6 @@ get_process_exe(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (pid == 0) {
|
||||
// ...otherwise we'd get '\x98\xd5\xbf\xbf\xfb\xf3\x10\x08H\x01'
|
||||
return Py_BuildValue("s", "");
|
||||
}
|
||||
|
||||
mib[0] = CTL_KERN;
|
||||
mib[1] = KERN_PROC;
|
||||
@ -214,7 +205,14 @@ get_process_exe(PyObject* self, PyObject* args)
|
||||
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);
|
||||
}
|
||||
|
||||
@ -233,9 +231,9 @@ get_process_cmdline(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
// get the commandline, defined in arch/bsd/process_info.c
|
||||
arglist = get_arg_list(pid);
|
||||
arglist = psutil_get_arg_list(pid);
|
||||
|
||||
// get_arg_list() returns NULL only if getcmdargs failed with ESRCH
|
||||
// psutil_get_arg_list() returns NULL only if psutil_get_cmd_args failed with ESRCH
|
||||
// (no process with that PID)
|
||||
if (NULL == arglist) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
@ -255,7 +253,7 @@ get_process_ppid(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.ki_ppid);
|
||||
@ -273,7 +271,7 @@ get_process_status(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", (int)kp.ki_stat);
|
||||
@ -292,7 +290,7 @@ get_process_uids(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll", (long)kp.ki_ruid,
|
||||
@ -313,7 +311,7 @@ get_process_gids(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll", (long)kp.ki_rgid,
|
||||
@ -334,7 +332,7 @@ get_process_tty_nr(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", kp.ki_tdev);
|
||||
@ -352,7 +350,7 @@ get_process_num_ctx_switches(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("(ll)", kp.ki_rusage.ru_nvcsw,
|
||||
@ -372,7 +370,7 @@ get_process_num_threads(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.ki_numthreads);
|
||||
@ -398,9 +396,10 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
PyObject* retList = PyList_New(0);
|
||||
PyObject* pyTuple = NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
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.
|
||||
@ -423,7 +422,7 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
|
||||
kip = malloc(size);
|
||||
if (kip == NULL) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -474,7 +473,7 @@ get_process_cpu_times(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
// convert from microseconds to seconds
|
||||
@ -519,7 +518,7 @@ get_process_create_time(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("d", TV2DOUBLE(kp.ki_start));
|
||||
@ -538,7 +537,7 @@ get_process_io_counters(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
// there's apparently no way to determine bytes count, hence return -1.
|
||||
@ -559,7 +558,7 @@ get_process_memory_info(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("(lllll)", ptoa(kp.ki_rssize), // rss
|
||||
@ -576,11 +575,17 @@ get_process_memory_info(PyObject* self, PyObject* args)
|
||||
static PyObject*
|
||||
get_virtual_mem(PyObject* self, PyObject* args)
|
||||
{
|
||||
unsigned int total, active, inactive, wired, cached, free, buffers;
|
||||
size_t size = sizeof(total);
|
||||
struct vmtotal vm;
|
||||
int mib[] = {CTL_VM, VM_METER};
|
||||
long pagesize = getpagesize();
|
||||
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;
|
||||
@ -594,7 +599,7 @@ get_virtual_mem(PyObject* self, PyObject* args)
|
||||
goto error;
|
||||
if (sysctlbyname("vm.stats.vm.v_free_count", &free, &size, NULL, 0))
|
||||
goto error;
|
||||
if (sysctlbyname("vfs.bufspace", &buffers, &size, NULL, 0))
|
||||
if (sysctlbyname("vfs.bufspace", &buffers, &buffers_size, NULL, 0))
|
||||
goto error;
|
||||
|
||||
size = sizeof(vm);
|
||||
@ -618,6 +623,10 @@ error:
|
||||
}
|
||||
|
||||
|
||||
#ifndef _PATH_DEVNULL
|
||||
#define _PATH_DEVNULL "/dev/null"
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Return swap memory stats (see 'swapinfo' cmdline tool)
|
||||
*/
|
||||
@ -629,11 +638,20 @@ get_swap_mem(PyObject* self, PyObject* args)
|
||||
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)
|
||||
@ -698,21 +716,22 @@ get_process_open_files(PyObject* self, PyObject* args)
|
||||
{
|
||||
long pid;
|
||||
int i, cnt;
|
||||
PyObject *retList = PyList_New(0);
|
||||
PyObject *tuple = NULL;
|
||||
|
||||
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 (get_kinfo_proc(pid, &kipp) == -1)
|
||||
if (psutil_get_kinfo_proc(pid, &kipp) == -1)
|
||||
goto error;
|
||||
|
||||
freep = kinfo_getfile(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
PyErr_SetFromErrno(0);
|
||||
psutil_raise_ad_or_nsp(pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -755,12 +774,12 @@ get_process_num_fds(PyObject* self, PyObject* args)
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
return NULL;
|
||||
if (get_kinfo_proc(pid, &kipp) == -1)
|
||||
if (psutil_get_kinfo_proc(pid, &kipp) == -1)
|
||||
return NULL;
|
||||
|
||||
freep = kinfo_getfile(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
PyErr_SetFromErrno(0);
|
||||
psutil_raise_ad_or_nsp(pid);
|
||||
return NULL;
|
||||
}
|
||||
free(freep);
|
||||
@ -785,12 +804,12 @@ get_process_cwd(PyObject* self, PyObject* args)
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid))
|
||||
goto error;
|
||||
if (get_kinfo_proc(pid, &kipp) == -1)
|
||||
if (psutil_get_kinfo_proc(pid, &kipp) == -1)
|
||||
goto error;
|
||||
|
||||
freep = kinfo_getfile(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
PyErr_SetFromErrno(0);
|
||||
psutil_raise_ad_or_nsp(pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -856,53 +875,138 @@ get_connection_status(int st) {
|
||||
}
|
||||
}
|
||||
|
||||
// a kvm_read that returns true if everything is read
|
||||
#define KVM_READ(kaddr, paddr, len) \
|
||||
((len) < SSIZE_MAX && \
|
||||
kvm_read(kd, (u_long)(kaddr), (char *)(paddr), (len)) == (ssize_t)(len))
|
||||
/* The tcplist fetching and walking is borrowed from netstat/inet.c. */
|
||||
static char *
|
||||
psutil_fetch_tcplist(void)
|
||||
{
|
||||
char *buf;
|
||||
size_t len;
|
||||
int error;
|
||||
|
||||
// XXX - copied from sys/file.h to make compiler happy
|
||||
struct file {
|
||||
void *f_data; /* file descriptor specific data */
|
||||
struct fileops *f_ops; /* File operations */
|
||||
struct ucred *f_cred; /* associated credentials. */
|
||||
struct vnode *f_vnode; /* NULL or applicable vnode */
|
||||
short f_type; /* descriptor type */
|
||||
short f_vnread_flags; /* (f) Sleep lock for f_offset */
|
||||
volatile u_int f_flag; /* see fcntl.h */
|
||||
volatile u_int f_count; /* reference count */
|
||||
int f_seqcount; /* Count of sequential accesses. */
|
||||
off_t f_nextoff; /* next expected read/write offset. */
|
||||
struct cdev_privdata *f_cdevpriv; /* (d) Private data for the cdev. */
|
||||
off_t f_offset;
|
||||
void *f_label; /* Place-holder for MAC label. */
|
||||
};
|
||||
for (;;) {
|
||||
if (sysctlbyname("net.inet.tcp.pcblist", NULL, &len, NULL, 0) < 0) {
|
||||
PyErr_SetFromErrno(0);
|
||||
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(0);
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return connections opened by process.
|
||||
* fstat.c source code was used as an example.
|
||||
*/
|
||||
static PyObject*
|
||||
get_process_connections(PyObject* self, PyObject* args)
|
||||
{
|
||||
long pid;
|
||||
struct kinfo_proc *p;
|
||||
struct file **ofiles = NULL;
|
||||
char buf[_POSIX2_LINE_MAX];
|
||||
char path[PATH_MAX];
|
||||
int cnt;
|
||||
int i;
|
||||
kvm_t *kd = NULL;
|
||||
struct file file;
|
||||
struct filedesc filed;
|
||||
struct nlist nl[] = {{ "" },};
|
||||
struct socket so;
|
||||
struct protosw proto;
|
||||
struct domain dom;
|
||||
struct inpcb inpcb;
|
||||
struct tcpcb tcpcb;
|
||||
struct unpcb unpcb;
|
||||
int i, cnt;
|
||||
|
||||
struct kinfo_file *freep = NULL;
|
||||
struct kinfo_file *kif;
|
||||
struct kinfo_proc kipp;
|
||||
char *tcplist = NULL;
|
||||
struct tcpcb *tcp;
|
||||
|
||||
PyObject *retList = PyList_New(0);
|
||||
PyObject *tuple = NULL;
|
||||
@ -913,6 +1017,9 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
PyObject* _family = NULL;
|
||||
PyObject* _type = NULL;
|
||||
|
||||
if (retList == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (! PyArg_ParseTuple(args, "lOO", &pid, &af_filter, &type_filter)) {
|
||||
goto error;
|
||||
}
|
||||
@ -921,88 +1028,43 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
goto error;
|
||||
}
|
||||
|
||||
kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, buf);
|
||||
if (kd == NULL) {
|
||||
AccessDenied();
|
||||
if (psutil_get_kinfo_proc(pid, &kipp) == -1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (kvm_nlist(kd, nl) != 0) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_nlist() failed");
|
||||
freep = kinfo_getfile(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
psutil_raise_ad_or_nsp(pid);
|
||||
goto error;
|
||||
}
|
||||
|
||||
p = kvm_getprocs(kd, KERN_PROC_PID, pid, &cnt);
|
||||
if (p == NULL) {
|
||||
NoSuchProcess();
|
||||
goto error;
|
||||
}
|
||||
if (cnt != 1) {
|
||||
NoSuchProcess();
|
||||
goto error;
|
||||
}
|
||||
if (p->ki_fd == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "no usable fd found");
|
||||
goto error;
|
||||
}
|
||||
if (!KVM_READ(p->ki_fd, &filed, sizeof(filed))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() failed");
|
||||
tcplist = psutil_fetch_tcplist();
|
||||
if (tcplist == NULL) {
|
||||
PyErr_SetFromErrno(0);
|
||||
goto error;
|
||||
}
|
||||
|
||||
ofiles = malloc((filed.fd_lastfile+1) * sizeof(struct file *));
|
||||
if (ofiles == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "malloc() failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (!KVM_READ(filed.fd_ofiles, ofiles,
|
||||
(filed.fd_lastfile+1) * sizeof(struct file *))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
for (i = 0; i <= filed.fd_lastfile; i++) {
|
||||
for (i = 0; i < cnt; i++) {
|
||||
int lport, rport;
|
||||
char lip[200], rip[200];
|
||||
char path[PATH_MAX];
|
||||
char *state;
|
||||
int inseq;
|
||||
tuple = NULL;
|
||||
laddr = NULL;
|
||||
raddr = NULL;
|
||||
|
||||
if (ofiles[i] == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (!KVM_READ(ofiles[i], &file, sizeof (struct file))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() file failed");
|
||||
goto error;
|
||||
}
|
||||
if (file.f_type == DTYPE_SOCKET) {
|
||||
// fill in socket
|
||||
if (!KVM_READ(file.f_data, &so, sizeof(struct socket))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() socket failed");
|
||||
goto error;
|
||||
}
|
||||
// fill in protosw entry
|
||||
if (!KVM_READ(so.so_proto, &proto, sizeof(struct protosw))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() proto failed");
|
||||
goto error;
|
||||
}
|
||||
// fill in domain
|
||||
if (!KVM_READ(proto.pr_domain, &dom, sizeof(struct domain))) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() domain failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
kif = &freep[i];
|
||||
if (kif->kf_type == KF_TYPE_SOCKET)
|
||||
{
|
||||
// apply filters
|
||||
_family = PyLong_FromLong((long)dom.dom_family);
|
||||
_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)proto.pr_type);
|
||||
_type = PyLong_FromLong((long)kif->kf_sock_type);
|
||||
inseq = PySequence_Contains(type_filter, _type);
|
||||
Py_DECREF(_type);
|
||||
if (inseq == 0) {
|
||||
@ -1010,40 +1072,29 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
// IPv4 / IPv6 socket
|
||||
if ((dom.dom_family == AF_INET) || (dom.dom_family == AF_INET6)) {
|
||||
// fill inpcb
|
||||
if (kvm_read(kd, (u_long)so.so_pcb, (char *)&inpcb,
|
||||
sizeof(struct inpcb)) != sizeof(struct inpcb)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() addr failed");
|
||||
goto error;
|
||||
}
|
||||
|
||||
if ((kif->kf_sock_domain == AF_INET) ||
|
||||
(kif->kf_sock_domain == AF_INET6)) {
|
||||
// fill status
|
||||
if (proto.pr_type == SOCK_STREAM) {
|
||||
if (kvm_read(kd, (u_long)inpcb.inp_ppcb, (char *)&tcpcb,
|
||||
sizeof(struct tcpcb)) != sizeof(struct tcpcb)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() state failed");
|
||||
goto error;
|
||||
}
|
||||
state = get_connection_status((int)tcpcb.t_state);
|
||||
}
|
||||
else {
|
||||
state = "";
|
||||
state = "";
|
||||
if (kif->kf_sock_type == SOCK_STREAM) {
|
||||
tcp = psutil_search_tcplist(tcplist, kif);
|
||||
if (tcp != NULL)
|
||||
state = get_connection_status((int)tcp->t_state);
|
||||
}
|
||||
|
||||
// build addr and port
|
||||
if (dom.dom_family == AF_INET) {
|
||||
inet_ntop(AF_INET, &inpcb.inp_laddr.s_addr, lip, sizeof(lip));
|
||||
inet_ntop(AF_INET, &inpcb.inp_faddr.s_addr, rip, sizeof(rip));
|
||||
}
|
||||
else {
|
||||
inet_ntop(AF_INET6, &inpcb.in6p_laddr.s6_addr, lip, sizeof(lip));
|
||||
inet_ntop(AF_INET6, &inpcb.in6p_faddr.s6_addr, rip, sizeof(rip));
|
||||
}
|
||||
lport = ntohs(inpcb.inp_lport);
|
||||
rport = ntohs(inpcb.inp_fport);
|
||||
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));
|
||||
|
||||
// contruct python tuple/list
|
||||
// construct python tuple/list
|
||||
laddr = Py_BuildValue("(si)", lip, lport);
|
||||
if (!laddr)
|
||||
goto error;
|
||||
@ -1055,9 +1106,9 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
}
|
||||
if (!raddr)
|
||||
goto error;
|
||||
tuple = Py_BuildValue("(iiiNNs)", i,
|
||||
dom.dom_family,
|
||||
proto.pr_type,
|
||||
tuple = Py_BuildValue("(iiiNNs)", kif->kf_fd,
|
||||
kif->kf_sock_domain,
|
||||
kif->kf_sock_type,
|
||||
laddr,
|
||||
raddr,
|
||||
state);
|
||||
@ -1068,30 +1119,17 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
Py_DECREF(tuple);
|
||||
}
|
||||
// UNIX socket
|
||||
else if (dom.dom_family == AF_UNIX) {
|
||||
struct sockaddr_un sun;
|
||||
path[0] = '\0';
|
||||
else if (kif->kf_sock_domain == AF_UNIX) {
|
||||
struct sockaddr_un *sun;
|
||||
|
||||
if (kvm_read(kd, (u_long)so.so_pcb, (char *)&unpcb,
|
||||
sizeof(struct unpcb)) != sizeof(struct unpcb)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kvm_read() unpcb failed");
|
||||
goto error;
|
||||
}
|
||||
if (unpcb.unp_addr) {
|
||||
if (kvm_read(kd, (u_long)unpcb.unp_addr, (char *)&sun,
|
||||
sizeof(sun)) != sizeof(sun)) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"kvm_read() sockaddr_un failed");
|
||||
goto error;
|
||||
}
|
||||
sprintf(path, "%.*s",
|
||||
(sun.sun_len - (sizeof(sun) - sizeof(sun.sun_path))),
|
||||
sun.sun_path);
|
||||
}
|
||||
sun = (struct sockaddr_un *)&kif->kf_sa_local;
|
||||
snprintf(path, sizeof(path), "%.*s",
|
||||
(sun->sun_len - (sizeof(*sun) - sizeof(sun->sun_path))),
|
||||
sun->sun_path);
|
||||
|
||||
tuple = Py_BuildValue("(iiisOs)", i,
|
||||
dom.dom_family,
|
||||
proto.pr_type,
|
||||
tuple = Py_BuildValue("(iiisOs)", kif->kf_fd,
|
||||
kif->kf_sock_domain,
|
||||
kif->kf_sock_type,
|
||||
path,
|
||||
Py_None,
|
||||
"");
|
||||
@ -1104,9 +1142,8 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(ofiles);
|
||||
kvm_close(kd);
|
||||
free(freep);
|
||||
free(tcplist);
|
||||
return retList;
|
||||
|
||||
error:
|
||||
@ -1114,13 +1151,10 @@ error:
|
||||
Py_XDECREF(laddr);
|
||||
Py_XDECREF(raddr);
|
||||
Py_DECREF(retList);
|
||||
|
||||
if (kd != NULL) {
|
||||
kvm_close(kd);
|
||||
}
|
||||
if (ofiles != NULL) {
|
||||
free(ofiles);
|
||||
}
|
||||
if (freep != NULL)
|
||||
free(freep);
|
||||
if (tcplist != NULL)
|
||||
free(tcplist);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1140,6 +1174,9 @@ get_system_per_cpu_times(PyObject* self, PyObject* args)
|
||||
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) {
|
||||
@ -1189,6 +1226,16 @@ error:
|
||||
}
|
||||
|
||||
|
||||
// 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.
|
||||
@ -1200,26 +1247,28 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
int ptrwidth;
|
||||
int i, cnt;
|
||||
char addr[30];
|
||||
char perms[10];
|
||||
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);
|
||||
|
||||
ptrwidth = 2*sizeof(void *);
|
||||
|
||||
if (retlist == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
goto error;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
freep = kinfo_getvmmap(pid, &cnt);
|
||||
if (freep == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "kinfo_getvmmap() failed");
|
||||
psutil_raise_ad_or_nsp(pid);
|
||||
goto error;
|
||||
}
|
||||
for (i = 0; i < cnt; i++) {
|
||||
@ -1229,6 +1278,7 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
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" : "-",
|
||||
@ -1236,6 +1286,7 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
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:
|
||||
@ -1318,6 +1369,9 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
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);
|
||||
@ -1329,6 +1383,10 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
|
||||
len = sizeof(*fs) * num;
|
||||
fs = malloc(len);
|
||||
if (fs == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
num = getfsstat(fs, len, MNT_NOWAIT);
|
||||
@ -1408,13 +1466,14 @@ error:
|
||||
static PyObject*
|
||||
get_network_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_ifc_info = NULL;
|
||||
|
||||
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
|
||||
@ -1428,8 +1487,11 @@ get_network_io_counters(PyObject* self, PyObject* args)
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
|
||||
PyErr_SetFromErrno(0);
|
||||
@ -1450,6 +1512,12 @@ get_network_io_counters(PyObject* self, PyObject* args)
|
||||
|
||||
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,
|
||||
@ -1489,18 +1557,24 @@ error:
|
||||
static PyObject*
|
||||
get_disk_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_disk_info = NULL;
|
||||
|
||||
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) {
|
||||
@ -1558,6 +1632,9 @@ get_system_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;
|
||||
@ -1692,8 +1769,7 @@ PsutilMethods[] =
|
||||
"Return system per-cpu times as a list of tuples"},
|
||||
#endif
|
||||
{"get_system_boot_time", get_system_boot_time, METH_VARARGS,
|
||||
"Return a float indicating the system boot time expressed in "
|
||||
"seconds since the epoch"},
|
||||
"Return the system boot time expressed in seconds since the epoch."},
|
||||
{"get_disk_partitions", get_disk_partitions, METH_VARARGS,
|
||||
"Return a list of tuples including device, mount point and "
|
||||
"fs type for all partitions mounted on the system."},
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_bsd.h 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_common.c 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -36,4 +34,3 @@ AccessDenied(void) {
|
||||
Py_XDECREF(exc);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_common.h 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_linux.c 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -107,6 +105,9 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
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");
|
||||
@ -153,6 +154,8 @@ get_sysinfo(PyObject* self, PyObject* args)
|
||||
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
|
||||
@ -160,7 +163,6 @@ get_sysinfo(PyObject* self, PyObject* args)
|
||||
(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
|
||||
// TODO: we can also determine BOOT_TIME here
|
||||
}
|
||||
|
||||
|
||||
@ -216,6 +218,9 @@ get_system_users(PyObject* self, PyObject* args)
|
||||
PyObject *user_proc = NULL;
|
||||
struct utmp *ut;
|
||||
|
||||
if (ret_list == NULL)
|
||||
return NULL;
|
||||
|
||||
setutent();
|
||||
while (NULL != (ut = getutent())) {
|
||||
tuple = NULL;
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_linux.h 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_mswindows.c 1525 2012-08-16 16:32:03Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -39,7 +37,7 @@
|
||||
* since the epoch.
|
||||
*/
|
||||
static PyObject*
|
||||
get_system_uptime(PyObject* self, PyObject* args)
|
||||
get_system_boot_time(PyObject* self, PyObject* args)
|
||||
{
|
||||
double uptime;
|
||||
time_t pt;
|
||||
@ -84,9 +82,9 @@ pid_exists(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
status = pid_is_running(pid);
|
||||
status = psutil_pid_is_running(pid);
|
||||
if (-1 == status) {
|
||||
return NULL; // exception raised in pid_is_running()
|
||||
return NULL; // exception raised in psutil_pid_is_running()
|
||||
}
|
||||
return PyBool_FromLong(status);
|
||||
}
|
||||
@ -104,7 +102,10 @@ get_pid_list(PyObject* self, PyObject* args)
|
||||
PyObject* pid = NULL;
|
||||
PyObject* retlist = PyList_New(0);
|
||||
|
||||
proclist = get_pids(&numberOfReturnedPIDs);
|
||||
if (retlist == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
proclist = psutil_get_pids(&numberOfReturnedPIDs);
|
||||
if (NULL == proclist) {
|
||||
goto error;
|
||||
}
|
||||
@ -248,7 +249,7 @@ get_process_cpu_times(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -335,10 +336,10 @@ get_process_create_time(PyObject* self, PyObject* args)
|
||||
|
||||
// special case for PIDs 0 and 4, return BOOT_TIME
|
||||
if (0 == pid || 4 == pid) {
|
||||
return get_system_uptime(NULL, NULL);
|
||||
return get_system_boot_time(NULL, NULL);
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -407,7 +408,7 @@ get_process_create_time_2(PyObject* self, PyObject* args)
|
||||
}
|
||||
// special case for PIDs 0 and 4, return BOOT_TIME
|
||||
if (0 == pid || 4 == pid) {
|
||||
return get_system_uptime(NULL, NULL);
|
||||
return get_system_boot_time(NULL, NULL);
|
||||
}
|
||||
/*
|
||||
Convert the LARGE_INTEGER union to a Unix time.
|
||||
@ -459,7 +460,7 @@ get_process_name(PyObject* self, PyObject* args) {
|
||||
return Py_BuildValue("s", "System");
|
||||
}
|
||||
|
||||
pid_return = pid_is_running(pid);
|
||||
pid_return = psutil_pid_is_running(pid);
|
||||
if (pid_return == 0) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
@ -467,9 +468,9 @@ get_process_name(PyObject* self, PyObject* args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
name = get_name(pid);
|
||||
name = psutil_get_name(pid);
|
||||
if (name == NULL) {
|
||||
return NULL; // exception set in get_name()
|
||||
return NULL; // exception set in psutil_get_name()
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@ -491,7 +492,7 @@ get_process_ppid(PyObject* self, PyObject* args) {
|
||||
return Py_BuildValue("l", 0);
|
||||
}
|
||||
|
||||
pid_return = pid_is_running(pid);
|
||||
pid_return = psutil_pid_is_running(pid);
|
||||
if (pid_return == 0) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
@ -499,9 +500,9 @@ get_process_ppid(PyObject* self, PyObject* args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ppid = get_ppid(pid);
|
||||
ppid = psutil_get_ppid(pid);
|
||||
if (ppid == NULL) {
|
||||
return NULL; // exception set in get_ppid()
|
||||
return NULL; // exception set in psutil_get_ppid()
|
||||
}
|
||||
return ppid;
|
||||
}
|
||||
@ -522,7 +523,7 @@ get_process_cmdline(PyObject* self, PyObject* args) {
|
||||
return Py_BuildValue("[]");
|
||||
}
|
||||
|
||||
pid_return = pid_is_running(pid);
|
||||
pid_return = psutil_pid_is_running(pid);
|
||||
if (pid_return == 0) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
@ -534,7 +535,7 @@ get_process_cmdline(PyObject* self, PyObject* args) {
|
||||
|
||||
// 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 = get_arg_list(pid);
|
||||
arglist = psutil_get_arg_list(pid);
|
||||
if ( NULL == arglist ) {
|
||||
// carry on anyway, clear any exceptions too
|
||||
PyErr_Clear();
|
||||
@ -559,7 +560,7 @@ get_process_exe(PyObject* self, PyObject* args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
|
||||
hProcess = psutil_handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
|
||||
if (NULL == hProcess) {
|
||||
return NULL;
|
||||
}
|
||||
@ -593,7 +594,7 @@ get_process_memory_info(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (NULL == hProcess) {
|
||||
return NULL;
|
||||
}
|
||||
@ -732,6 +733,9 @@ get_system_cpu_times(PyObject* self, PyObject* args)
|
||||
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) {
|
||||
@ -827,12 +831,12 @@ get_process_cwd(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
processHandle = handle_from_pid(pid);
|
||||
processHandle = psutil_handle_from_pid(pid);
|
||||
if (processHandle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pebAddress = GetPebAddress(processHandle);
|
||||
pebAddress = psutil_get_peb_address(processHandle);
|
||||
|
||||
// get the address of ProcessParameters
|
||||
#ifdef _WIN64
|
||||
@ -878,6 +882,11 @@ get_process_cwd(PyObject* self, PyObject* args)
|
||||
|
||||
// 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,
|
||||
@ -1065,16 +1074,19 @@ get_process_num_threads(PyObject* self, PyObject* args)
|
||||
static PyObject*
|
||||
get_process_threads(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* retList = PyList_New(0);
|
||||
PyObject* pyTuple = NULL;
|
||||
HANDLE hThreadSnap = NULL;
|
||||
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;
|
||||
}
|
||||
@ -1085,7 +1097,7 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
goto error;
|
||||
}
|
||||
|
||||
pid_return = pid_is_running(pid);
|
||||
pid_return = psutil_pid_is_running(pid);
|
||||
if (pid_return == 0) {
|
||||
NoSuchProcess();
|
||||
goto error;
|
||||
@ -1183,12 +1195,12 @@ get_process_open_files(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
processHandle = handle_from_pid_waccess(pid, access);
|
||||
processHandle = psutil_handle_from_pid_waccess(pid, access);
|
||||
if (processHandle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
filesList = get_open_files(pid, processHandle);
|
||||
filesList = psutil_get_open_files(pid, processHandle);
|
||||
CloseHandle(processHandle);
|
||||
if (filesList == NULL) {
|
||||
return PyErr_SetFromWindowsErr(0);
|
||||
@ -1252,7 +1264,7 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
processHandle = handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
|
||||
processHandle = psutil_handle_from_pid_waccess(pid, PROCESS_QUERY_INFORMATION);
|
||||
if (processHandle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1268,6 +1280,9 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
|
||||
bufferSize = 0x100;
|
||||
user = malloc(bufferSize);
|
||||
if (user == NULL) {
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
|
||||
if (!GetTokenInformation(tokenHandle,
|
||||
TokenUser,
|
||||
@ -1277,7 +1292,10 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
{
|
||||
free(user);
|
||||
user = malloc(bufferSize);
|
||||
|
||||
if (user == NULL) {
|
||||
CloseHandle(tokenHandle);
|
||||
return PyErr_NoMemory();
|
||||
}
|
||||
if (!GetTokenInformation(tokenHandle,
|
||||
TokenUser,
|
||||
user,
|
||||
@ -1298,7 +1316,11 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
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))
|
||||
@ -1306,8 +1328,11 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
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))
|
||||
{
|
||||
@ -1324,6 +1349,12 @@ get_process_username(PyObject* self, PyObject* args)
|
||||
|
||||
/* 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);
|
||||
@ -1502,7 +1533,7 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pid_is_running(pid) == 0) {
|
||||
if (psutil_pid_is_running(pid) == 0) {
|
||||
ConnDecrefPyObjs();
|
||||
return NoSuchProcess();
|
||||
}
|
||||
@ -1536,6 +1567,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
connectionsList = PyList_New(0);
|
||||
if (connectionsList == NULL) {
|
||||
ConnDecrefPyObjs();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* TCP IPv4 */
|
||||
|
||||
@ -1551,6 +1586,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
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)
|
||||
@ -1635,6 +1674,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
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)
|
||||
@ -1719,6 +1762,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
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)
|
||||
@ -1782,6 +1829,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
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)
|
||||
@ -1859,7 +1910,7 @@ get_process_priority(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1889,7 +1940,7 @@ set_process_priority(PyObject* self, PyObject* args)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hProcess = handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1905,6 +1956,83 @@ set_process_priority(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
|
||||
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
|
||||
/*
|
||||
* Get process IO priority as a Python integer.
|
||||
*/
|
||||
static PyObject*
|
||||
get_process_io_priority(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*
|
||||
set_process_io_priority(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_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Return a Python tuple referencing process I/O counters.
|
||||
*/
|
||||
@ -1918,7 +2046,7 @@ get_process_io_counters(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (NULL == hProcess) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1974,7 +2102,7 @@ get_process_cpu_affinity(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -1984,7 +2112,11 @@ get_process_cpu_affinity(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
CloseHandle(hProcess);
|
||||
#ifdef _WIN64
|
||||
return Py_BuildValue("K", (unsigned long long)proc_mask);
|
||||
#else
|
||||
return Py_BuildValue("k", (unsigned long)proc_mask);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@ -1999,10 +2131,15 @@ set_process_cpu_affinity(PyObject* self, PyObject* args)
|
||||
DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_SET_INFORMATION;
|
||||
DWORD_PTR mask;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "lk", &pid, &mask)) {
|
||||
#ifdef _WIN64
|
||||
if (! PyArg_ParseTuple(args, "lK", &pid, &mask))
|
||||
#else
|
||||
if (! PyArg_ParseTuple(args, "lk", &pid, &mask))
|
||||
#endif
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
hProcess = handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
hProcess = psutil_handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
if (hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
@ -2080,11 +2217,6 @@ get_disk_usage(PyObject* self, PyObject* args)
|
||||
static PyObject*
|
||||
get_network_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_nic_info = NULL;
|
||||
PyObject* py_pre_nic_name = NULL;
|
||||
PyObject* py_nic_name = NULL;
|
||||
|
||||
int attempts = 0;
|
||||
int outBufLen = 15000;
|
||||
DWORD dwRetVal = 0;
|
||||
@ -2094,11 +2226,18 @@ get_network_io_counters(PyObject* self, PyObject* args)
|
||||
PIP_ADAPTER_ADDRESSES pAddresses = NULL;
|
||||
PIP_ADAPTER_ADDRESSES pCurrAddresses = NULL;
|
||||
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_nic_info = NULL;
|
||||
PyObject* py_pre_nic_name = NULL;
|
||||
PyObject* py_nic_name = NULL;
|
||||
|
||||
if (py_retdict == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
do {
|
||||
pAddresses = (IP_ADAPTER_ADDRESSES *) malloc(outBufLen);
|
||||
if (pAddresses == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"memory allocation failed for IP_ADAPTER_ADDRESSES struct.");
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -2128,8 +2267,7 @@ get_network_io_counters(PyObject* self, PyObject* args)
|
||||
pIfRow = (MIB_IFROW *) malloc(sizeof(MIB_IFROW));
|
||||
|
||||
if (pIfRow == NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError,
|
||||
"memory allocation failed for MIB_IFROW struct.");
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
@ -2185,6 +2323,22 @@ error:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// fix for mingw32, see
|
||||
// https://code.google.com/p/psutil/issues/detail?id=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;
|
||||
|
||||
/*
|
||||
* Return a Python dict of tuples for disk I/O information
|
||||
@ -2192,33 +2346,36 @@ error:
|
||||
static PyObject*
|
||||
get_disk_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_disk_info = NULL;
|
||||
|
||||
DISK_PERFORMANCE diskPerformance;
|
||||
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;
|
||||
}
|
||||
|
||||
for (devNum = 0;; devNum++) {
|
||||
// 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 (szDevice, "\\\\.\\PhysicalDrive%d", devNum);
|
||||
hDevice = CreateFile (szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
sprintf(szDevice, "\\\\.\\PhysicalDrive%d", devNum);
|
||||
hDevice = CreateFile(szDevice, 0, FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (hDevice == INVALID_HANDLE_VALUE) {
|
||||
// what happens if we get an invalid handle on the first disk?
|
||||
// we might end up with an empty dict incorrectly in some cases
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (DeviceIoControl(hDevice, IOCTL_DISK_PERFORMANCE, NULL, 0,
|
||||
&diskPerformance, sizeof(DISK_PERFORMANCE),
|
||||
&diskPerformance, sizeof(diskPerformance),
|
||||
&dwSize, NULL))
|
||||
{
|
||||
sprintf (szDeviceDisplay, "PhysicalDrive%d", devNum);
|
||||
sprintf(szDeviceDisplay, "PhysicalDrive%d", devNum);
|
||||
py_disk_info = Py_BuildValue("(IILLLL)",
|
||||
diskPerformance.ReadCount,
|
||||
diskPerformance.WriteCount,
|
||||
@ -2300,6 +2457,14 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
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 http://code.google.com/p/psutil/issues/detail?id=264
|
||||
SetErrorMode(SEM_FAILCRITICALERRORS);
|
||||
|
||||
if (! PyArg_ParseTuple(args, "O", &py_all)) {
|
||||
goto error;
|
||||
}
|
||||
@ -2382,9 +2547,11 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
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;
|
||||
@ -2404,10 +2571,6 @@ error:
|
||||
static PyObject*
|
||||
get_system_users(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retlist = PyList_New(0);
|
||||
PyObject* py_tuple = NULL;
|
||||
PyObject* py_address = NULL;
|
||||
|
||||
HANDLE hServer = NULL;
|
||||
LPTSTR buffer_user = NULL;
|
||||
LPTSTR buffer_addr = NULL;
|
||||
@ -2425,6 +2588,13 @@ get_system_users(PyObject* self, PyObject* args)
|
||||
HINSTANCE hInstWinSta = NULL;
|
||||
ULONG returnLen;
|
||||
|
||||
PyObject* py_retlist = PyList_New(0);
|
||||
PyObject* py_tuple = NULL;
|
||||
PyObject* py_address = NULL;
|
||||
if (py_retlist == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
hInstWinSta = LoadLibraryA("winsta.dll");
|
||||
WinStationQueryInformationW = (PWINSTATIONQUERYINFORMATIONW)
|
||||
GetProcAddress(hInstWinSta, "WinStationQueryInformationW");
|
||||
@ -2557,7 +2727,7 @@ get_process_num_handles(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (NULL == hProcess) {
|
||||
return NULL;
|
||||
}
|
||||
@ -2660,10 +2830,13 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
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 = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if (NULL == hProcess) {
|
||||
goto error;
|
||||
}
|
||||
@ -2756,6 +2929,12 @@ PsutilMethods[] =
|
||||
"Return process priority."},
|
||||
{"set_process_priority", set_process_priority, METH_VARARGS,
|
||||
"Set process priority."},
|
||||
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
|
||||
{"get_process_io_priority", get_process_io_priority, METH_VARARGS,
|
||||
"Return process IO priority."},
|
||||
{"set_process_io_priority", set_process_io_priority, METH_VARARGS,
|
||||
"Set process IO priority."},
|
||||
#endif
|
||||
{"get_process_cpu_affinity", get_process_cpu_affinity, METH_VARARGS,
|
||||
"Return process CPU affinity as a bitmask."},
|
||||
{"set_process_cpu_affinity", set_process_cpu_affinity, METH_VARARGS,
|
||||
@ -2791,8 +2970,8 @@ PsutilMethods[] =
|
||||
"Determine if the process exists in the current process list."},
|
||||
{"get_num_cpus", get_num_cpus, METH_VARARGS,
|
||||
"Returns the number of CPUs on the system"},
|
||||
{"get_system_uptime", get_system_uptime, METH_VARARGS,
|
||||
"Return system uptime"},
|
||||
{"get_system_boot_time", get_system_boot_time, METH_VARARGS,
|
||||
"Return the system boot time expressed in seconds since the epoch."},
|
||||
{"get_virtual_mem", get_virtual_mem, METH_VARARGS,
|
||||
"Return the total amount of physical memory, in bytes"},
|
||||
{"get_system_cpu_times", get_system_cpu_times, METH_VARARGS,
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_mswindows.h 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -28,6 +26,10 @@ static PyObject* get_process_num_threads(PyObject* self, PyObject* args);
|
||||
static PyObject* get_process_threads(PyObject* self, PyObject* args);
|
||||
static PyObject* get_process_priority(PyObject* self, PyObject* args);
|
||||
static PyObject* set_process_priority(PyObject* self, PyObject* args);
|
||||
#if (_WIN32_WINNT >= 0x0600) // Windows Vista
|
||||
static PyObject* get_process_io_priority(PyObject* self, PyObject* args);
|
||||
static PyObject* set_process_io_priority(PyObject* self, PyObject* args);
|
||||
#endif
|
||||
static PyObject* get_process_io_counters(PyObject* self, PyObject* args);
|
||||
static PyObject* get_process_cpu_affinity(PyObject* self, PyObject* args);
|
||||
static PyObject* set_process_cpu_affinity(PyObject* self, PyObject* args);
|
||||
@ -51,7 +53,7 @@ static PyObject* kill_process(PyObject* self, PyObject* args);
|
||||
|
||||
static PyObject* get_pid_list(PyObject* self, PyObject* args);
|
||||
static PyObject* get_num_cpus(PyObject* self, PyObject* args);
|
||||
static PyObject* get_system_uptime(PyObject* self, PyObject* args);
|
||||
static PyObject* get_system_boot_time(PyObject* self, PyObject* args);
|
||||
static PyObject* get_virtual_mem(PyObject* self, PyObject* args);
|
||||
static PyObject* get_system_cpu_times(PyObject* self, PyObject* args);
|
||||
static PyObject* pid_exists(PyObject* self, PyObject* args);
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_osx.c 1501 2012-07-25 12:57:34Z g.rodola@gmail.com $
|
||||
*
|
||||
* 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.
|
||||
@ -31,7 +29,7 @@
|
||||
#include <mach/mach_host.h>
|
||||
#include <mach/mach_traps.h>
|
||||
#include <mach/mach_vm.h>
|
||||
#include <mach/shared_memory_server.h>
|
||||
#include <mach/shared_region.h>
|
||||
|
||||
#include <mach-o/loader.h>
|
||||
|
||||
@ -62,6 +60,7 @@ psutil_sys_vminfo(vm_statistics_data_t *vmstat)
|
||||
"host_statistics() failed: %s", mach_error_string(ret));
|
||||
return 0;
|
||||
}
|
||||
mach_port_deallocate(mach_task_self(), mport);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -79,7 +78,10 @@ get_pid_list(PyObject* self, PyObject* args)
|
||||
PyObject *pid = NULL;
|
||||
PyObject *retlist = PyList_New(0);
|
||||
|
||||
if (get_proc_list(&proclist, &num_processes) != 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;
|
||||
}
|
||||
@ -120,7 +122,7 @@ get_process_name(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("s", kp.kp_proc.p_comm);
|
||||
@ -164,7 +166,7 @@ get_process_exe(PyObject* self, PyObject* args)
|
||||
}
|
||||
ret = proc_pidpath(pid, &buf, sizeof(buf));
|
||||
if (ret == 0) {
|
||||
if (! pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
@ -188,7 +190,7 @@ get_process_cmdline(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
// get the commandline, defined in arch/osx/process_info.c
|
||||
arglist = get_arg_list(pid);
|
||||
arglist = psutil_get_arg_list(pid);
|
||||
return arglist;
|
||||
}
|
||||
|
||||
@ -204,7 +206,7 @@ get_process_ppid(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("l", (long)kp.kp_eproc.e_ppid);
|
||||
@ -222,7 +224,7 @@ get_process_uids(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_ruid,
|
||||
@ -242,7 +244,7 @@ get_process_gids(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("lll", (long)kp.kp_eproc.e_pcred.p_rgid,
|
||||
@ -262,7 +264,7 @@ get_process_tty_nr(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", kp.kp_eproc.e_tdev);
|
||||
@ -290,6 +292,9 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
PyObject* py_tuple = NULL;
|
||||
PyObject* py_list = PyList_New(0);
|
||||
|
||||
if (py_list == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
goto error;
|
||||
}
|
||||
@ -297,7 +302,7 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
err = task_for_pid(mach_task_self(), pid, &task);
|
||||
|
||||
if (err != KERN_SUCCESS) {
|
||||
if (! pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
@ -329,7 +334,7 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
memset(addr_str, 0, sizeof(addr_str));
|
||||
memset(perms, 0, sizeof(perms));
|
||||
|
||||
sprintf(addr_str, "%016x-%016x", address, address + size);
|
||||
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' : '-',
|
||||
@ -397,9 +402,14 @@ get_process_memory_maps(PyObject* self, PyObject* args)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
@ -463,7 +473,7 @@ get_process_create_time(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("d", TV2DOUBLE(kp.kp_proc.p_starttime));
|
||||
@ -623,11 +633,13 @@ get_system_cpu_times(PyObject* self, PyObject* args)
|
||||
kern_return_t error;
|
||||
host_cpu_load_info_data_t r_load;
|
||||
|
||||
error = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&r_load, &count);
|
||||
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,
|
||||
@ -649,17 +661,22 @@ get_system_per_cpu_times(PyObject* self, PyObject* args)
|
||||
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;
|
||||
int i, ret;
|
||||
|
||||
error = host_processor_info(mach_host_self(), PROCESSOR_CPU_LOAD_INFO,
|
||||
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;
|
||||
|
||||
@ -736,6 +753,9 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
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);
|
||||
@ -747,6 +767,10 @@ get_disk_partitions(PyObject* self, PyObject* args)
|
||||
|
||||
len = sizeof(*fs) * num;
|
||||
fs = malloc(len);
|
||||
if (fs == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
Py_BEGIN_ALLOW_THREADS
|
||||
num = getfsstat(fs, len, MNT_NOWAIT);
|
||||
@ -846,7 +870,7 @@ get_process_status(PyObject* self, PyObject* args)
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
return NULL;
|
||||
}
|
||||
if (get_kinfo_proc(pid, &kp) == -1) {
|
||||
if (psutil_get_kinfo_proc(pid, &kp) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
return Py_BuildValue("i", (int)kp.kp_proc.p_stat);
|
||||
@ -873,6 +897,9 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
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;
|
||||
@ -881,7 +908,7 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
// task_for_pid() requires special privileges
|
||||
err = task_for_pid(mach_task_self(), pid, &task);
|
||||
if (err != KERN_SUCCESS) {
|
||||
if (! pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
@ -939,9 +966,13 @@ get_process_threads(PyObject* self, PyObject* args)
|
||||
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) {
|
||||
@ -977,6 +1008,9 @@ get_process_open_files(PyObject* self, PyObject* args)
|
||||
PyObject *retList = PyList_New(0);
|
||||
PyObject *tuple = NULL;
|
||||
|
||||
if (retList == NULL)
|
||||
return NULL;
|
||||
|
||||
if (! PyArg_ParseTuple(args, "l", &pid)) {
|
||||
goto error;
|
||||
}
|
||||
@ -989,6 +1023,10 @@ get_process_open_files(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -1054,7 +1092,7 @@ error:
|
||||
if (errno != 0) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
else if (! pid_exists(pid)) {
|
||||
else if (! psutil_pid_exists(pid)) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
@ -1125,6 +1163,9 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
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;
|
||||
}
|
||||
@ -1144,6 +1185,10 @@ get_process_connections(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
@ -1306,7 +1351,7 @@ error:
|
||||
if (errno != 0) {
|
||||
return PyErr_SetFromErrno(PyExc_OSError);
|
||||
}
|
||||
else if (! pid_exists(pid) ) {
|
||||
else if (! psutil_pid_exists(pid) ) {
|
||||
return NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
@ -1337,6 +1382,9 @@ get_process_num_fds(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -1356,13 +1404,15 @@ get_process_num_fds(PyObject* self, PyObject* args)
|
||||
static PyObject*
|
||||
get_network_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_ifc_info = NULL;
|
||||
|
||||
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
|
||||
@ -1377,6 +1427,10 @@ get_network_io_counters(PyObject* self, PyObject* args)
|
||||
}
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) {
|
||||
PyErr_SetFromErrno(0);
|
||||
@ -1437,15 +1491,17 @@ error:
|
||||
static PyObject*
|
||||
get_disk_io_counters(PyObject* self, PyObject* args)
|
||||
{
|
||||
PyObject* py_retdict = PyDict_New();
|
||||
PyObject* py_disk_info = NULL;
|
||||
|
||||
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,
|
||||
@ -1562,9 +1618,10 @@ get_disk_io_counters(PyObject* self, PyObject* args)
|
||||
// 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, write_time / 1000);
|
||||
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))
|
||||
@ -1595,48 +1652,38 @@ error:
|
||||
static PyObject*
|
||||
get_system_users(PyObject* self, PyObject* args)
|
||||
{
|
||||
struct utmpx *utx;
|
||||
PyObject *ret_list = PyList_New(0);
|
||||
PyObject *tuple = NULL;
|
||||
struct utmpx ut;
|
||||
FILE *fp = NULL;
|
||||
|
||||
fp = fopen(_PATH_UTMPX, "r");
|
||||
if (fp == NULL) {
|
||||
// man fopen says errno is set but it seems it's not (OSX 10.6)
|
||||
PyErr_SetFromErrnoWithFilename(PyExc_OSError, _PATH_UTMPX);
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (fread(&ut, sizeof(ut), 1, fp) == 1) {
|
||||
if (*ut.ut_user == '\0') {
|
||||
if (ret_list == NULL)
|
||||
return NULL;
|
||||
while ((utx = getutxent()) != NULL) {
|
||||
if (utx->ut_type != USER_PROCESS)
|
||||
continue;
|
||||
}
|
||||
#ifdef UTMPX_USER_PROCESS
|
||||
if (ut.ut_type != UTMPX_USER_PROCESS) {
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
tuple = Py_BuildValue("(sssf)",
|
||||
ut.ut_user, // username
|
||||
ut.ut_line, // tty
|
||||
ut.ut_host, // hostname
|
||||
(float)ut.ut_tv.tv_sec // login time
|
||||
utx->ut_user, // username
|
||||
utx->ut_line, // tty
|
||||
utx->ut_host, // hostname
|
||||
(float)utx->ut_tv.tv_sec // start time
|
||||
);
|
||||
if (!tuple)
|
||||
if (!tuple) {
|
||||
endutxent();
|
||||
goto error;
|
||||
if (PyList_Append(ret_list, tuple))
|
||||
}
|
||||
if (PyList_Append(ret_list, tuple)) {
|
||||
endutxent();
|
||||
goto error;
|
||||
}
|
||||
Py_DECREF(tuple);
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
endutxent();
|
||||
return ret_list;
|
||||
|
||||
error:
|
||||
Py_XDECREF(tuple);
|
||||
Py_DECREF(ret_list);
|
||||
if (fp != NULL)
|
||||
fclose(fp);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -1704,8 +1751,7 @@ PsutilMethods[] =
|
||||
{"get_system_per_cpu_times", get_system_per_cpu_times, METH_VARARGS,
|
||||
"Return system per-cpu times as a list of tuples"},
|
||||
{"get_system_boot_time", get_system_boot_time, METH_VARARGS,
|
||||
"Return a float indicating the system boot time expressed in "
|
||||
"seconds since the epoch"},
|
||||
"Return the system boot time expressed in seconds since the epoch."},
|
||||
{"get_disk_partitions", get_disk_partitions, METH_VARARGS,
|
||||
"Return a list of tuples including device, mount point and "
|
||||
"fs type for all partitions mounted on the system."},
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_osx.h 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_posix.c 1223 2011-11-09 23:47:55Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: _psutil_posix.h 1223 2011-11-09 23:47:55Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.c 1462 2012-07-18 03:12:08Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -34,7 +32,7 @@
|
||||
* On error, the function returns a BSD errno value.
|
||||
*/
|
||||
int
|
||||
get_proc_list(struct kinfo_proc **procList, size_t *procCount)
|
||||
psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount)
|
||||
{
|
||||
int err;
|
||||
struct kinfo_proc * result;
|
||||
@ -114,7 +112,7 @@ get_proc_list(struct kinfo_proc **procList, size_t *procCount)
|
||||
|
||||
|
||||
char
|
||||
*getcmdpath(long pid, size_t *pathsize)
|
||||
*psutil_get_cmd_path(long pid, size_t *pathsize)
|
||||
{
|
||||
int mib[4];
|
||||
char *path;
|
||||
@ -135,7 +133,7 @@ char
|
||||
|
||||
path = malloc(size);
|
||||
if (path == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, "couldn't allocate memory");
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -150,6 +148,7 @@ char
|
||||
|
||||
|
||||
/*
|
||||
* XXX no longer used; it probably makese sense to remove it.
|
||||
* Borrowed from psi Python System Information project
|
||||
*
|
||||
* Get command arguments and environment variables.
|
||||
@ -162,10 +161,10 @@ char
|
||||
* 1 for insufficient privileges.
|
||||
*/
|
||||
char
|
||||
*getcmdargs(long pid, size_t *argsize)
|
||||
*psutil_get_cmd_args(long pid, size_t *argsize)
|
||||
{
|
||||
int mib[4];
|
||||
size_t size, argmax;
|
||||
int mib[4], argmax;
|
||||
size_t size = sizeof(argmax);
|
||||
char *procargs = NULL;
|
||||
|
||||
/* Get the maximum process arguments size. */
|
||||
@ -179,7 +178,7 @@ char
|
||||
/* Allocate space for the arguments. */
|
||||
procargs = (char *)malloc(argmax);
|
||||
if (procargs == NULL) {
|
||||
PyErr_SetString(PyExc_MemoryError, "couldn't allocate memory");
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -205,7 +204,7 @@ char
|
||||
|
||||
/* returns the command line as a python list object */
|
||||
PyObject*
|
||||
get_arg_list(long pid)
|
||||
psutil_get_arg_list(long pid)
|
||||
{
|
||||
char *argstr = NULL;
|
||||
int pos = 0;
|
||||
@ -217,7 +216,7 @@ get_arg_list(long pid)
|
||||
return retlist;
|
||||
}
|
||||
|
||||
argstr = getcmdargs(pid, &argsize);
|
||||
argstr = psutil_get_cmd_args(pid, &argsize);
|
||||
if (argstr == NULL) {
|
||||
goto error;
|
||||
}
|
||||
@ -253,7 +252,7 @@ error:
|
||||
* Return 1 if PID exists in the current process list, else 0.
|
||||
*/
|
||||
int
|
||||
pid_exists(long pid)
|
||||
psutil_pid_exists(long pid)
|
||||
{
|
||||
int kill_ret;
|
||||
if (pid < 0) {
|
||||
@ -269,3 +268,17 @@ pid_exists(long pid)
|
||||
// otherwise return 0 for PID not found
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Set exception to AccessDenied if pid exists else NoSuchProcess.
|
||||
*/
|
||||
int
|
||||
psutil_raise_ad_or_nsp(pid) {
|
||||
if (psutil_pid_exists(pid) == 0) {
|
||||
NoSuchProcess();
|
||||
}
|
||||
else {
|
||||
AccessDenied();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.h 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -13,9 +11,8 @@
|
||||
|
||||
typedef struct kinfo_proc kinfo_proc;
|
||||
|
||||
int get_proc_list(struct kinfo_proc **procList, size_t *procCount);
|
||||
char *getcmdargs(long pid, size_t *argsize);
|
||||
char *getcmdpath(long pid, size_t *pathsize);
|
||||
PyObject* get_arg_list(long pid);
|
||||
int pid_exists(long pid);
|
||||
|
||||
int psutil_get_proc_list(struct kinfo_proc **procList, size_t *procCount);
|
||||
char *psutil_get_cmd_args(long pid, size_t *argsize);
|
||||
char *psutil_get_cmd_path(long pid, size_t *pathsize);
|
||||
int psutil_pid_exists(long pid);
|
||||
PyObject* psutil_get_arg_list(long pid);
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: ntextapi.h 1452 2012-07-13 19:02:07Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -230,3 +228,79 @@ WTSCloseServer(
|
||||
IN HANDLE hServer
|
||||
);
|
||||
#endif
|
||||
// end mingw support:
|
||||
|
||||
/*
|
||||
* 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 struct _PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
PVOID Reserved1;
|
||||
PVOID PebBaseAddress;
|
||||
PVOID Reserved2[2];
|
||||
ULONG_PTR UniqueProcessId;
|
||||
PVOID Reserved3;
|
||||
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
|
||||
|
||||
|
||||
typedef enum _PROCESSINFOCLASS {
|
||||
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
|
||||
} PROCESSINFOCLASS;
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_handles.c 1463 2012-07-18 13:06:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -120,7 +118,7 @@ PVOID GetLibraryProcAddress(PSTR LibraryName, PSTR ProcName)
|
||||
|
||||
|
||||
PyObject*
|
||||
get_open_files(long pid, HANDLE processHandle)
|
||||
psutil_get_open_files(long pid, HANDLE processHandle)
|
||||
{
|
||||
_NtQuerySystemInformation NtQuerySystemInformation =
|
||||
GetLibraryProcAddress("ntdll.dll", "NtQuerySystemInformation");
|
||||
@ -139,9 +137,15 @@ get_open_files(long pid, HANDLE processHandle)
|
||||
PyObject *arg = NULL;
|
||||
PyObject *fileFromWchar = NULL;
|
||||
|
||||
|
||||
if (filesList == NULL)
|
||||
return NULL;
|
||||
|
||||
handleInfo = (PSYSTEM_HANDLE_INFORMATION)malloc(handleInfoSize);
|
||||
if (handleInfo == NULL) {
|
||||
Py_DECREF(filesList);
|
||||
PyErr_NoMemory();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* NtQuerySystemInformation won't give us the correct buffer size,
|
||||
so we guess by doubling the buffer size. */
|
||||
|
@ -9,4 +9,4 @@
|
||||
#include <Python.h>
|
||||
#include <windows.h>
|
||||
|
||||
PyObject* get_open_files(long pid, HANDLE processHandle);
|
||||
PyObject* psutil_get_open_files(long pid, HANDLE processHandle);
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.c 1463 2012-07-18 13:06:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -18,29 +16,6 @@
|
||||
#include "process_info.h"
|
||||
#include "ntextapi.h"
|
||||
|
||||
/*
|
||||
* 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 struct _PROCESS_BASIC_INFORMATION
|
||||
{
|
||||
PVOID Reserved1;
|
||||
PVOID PebBaseAddress;
|
||||
PVOID Reserved2[2];
|
||||
ULONG_PTR UniqueProcessId;
|
||||
PVOID Reserved3;
|
||||
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
|
||||
|
||||
|
||||
/*
|
||||
@ -51,7 +26,7 @@ typedef struct _PROCESS_BASIC_INFORMATION
|
||||
* Return a process handle or NULL.
|
||||
*/
|
||||
HANDLE
|
||||
handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
|
||||
psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
DWORD processExitCode = 0;
|
||||
@ -84,20 +59,20 @@ handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess)
|
||||
|
||||
|
||||
/*
|
||||
* Same as handle_from_pid_waccess but implicitly uses
|
||||
* Same as psutil_handle_from_pid_waccess but implicitly uses
|
||||
* PROCESS_QUERY_INFORMATION | PROCESS_VM_READ as dwDesiredAccess
|
||||
* parameter for OpenProcess.
|
||||
*/
|
||||
HANDLE
|
||||
handle_from_pid(DWORD pid) {
|
||||
psutil_handle_from_pid(DWORD pid) {
|
||||
DWORD dwDesiredAccess = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ;
|
||||
return handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
return psutil_handle_from_pid_waccess(pid, dwDesiredAccess);
|
||||
}
|
||||
|
||||
|
||||
// fetch the PEB base address from NtQueryInformationProcess()
|
||||
PVOID
|
||||
GetPebAddress(HANDLE ProcessHandle)
|
||||
psutil_get_peb_address(HANDLE ProcessHandle)
|
||||
{
|
||||
_NtQueryInformationProcess NtQueryInformationProcess =
|
||||
(_NtQueryInformationProcess)GetProcAddress(
|
||||
@ -110,7 +85,7 @@ GetPebAddress(HANDLE ProcessHandle)
|
||||
|
||||
|
||||
DWORD*
|
||||
get_pids(DWORD *numberOfReturnedPIDs) {
|
||||
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.
|
||||
@ -129,7 +104,10 @@ get_pids(DWORD *numberOfReturnedPIDs) {
|
||||
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);
|
||||
@ -145,7 +123,7 @@ get_pids(DWORD *numberOfReturnedPIDs) {
|
||||
|
||||
|
||||
int
|
||||
pid_is_running(DWORD pid)
|
||||
psutil_pid_is_running(DWORD pid)
|
||||
{
|
||||
HANDLE hProcess;
|
||||
DWORD exitCode;
|
||||
@ -197,13 +175,13 @@ pid_is_running(DWORD pid)
|
||||
|
||||
|
||||
int
|
||||
pid_in_proclist(DWORD pid)
|
||||
psutil_pid_in_proclist(DWORD pid)
|
||||
{
|
||||
DWORD *proclist = NULL;
|
||||
DWORD numberOfReturnedPIDs;
|
||||
DWORD i;
|
||||
|
||||
proclist = get_pids(&numberOfReturnedPIDs);
|
||||
proclist = psutil_get_pids(&numberOfReturnedPIDs);
|
||||
if (NULL == proclist) {
|
||||
return -1;
|
||||
}
|
||||
@ -221,25 +199,27 @@ pid_in_proclist(DWORD pid)
|
||||
|
||||
|
||||
// Check exit code from a process handle. Return FALSE on an error also
|
||||
BOOL is_running(HANDLE hProcess)
|
||||
// XXX - not used anymore
|
||||
int
|
||||
handlep_is_running(HANDLE hProcess)
|
||||
{
|
||||
DWORD dwCode;
|
||||
|
||||
if (NULL == hProcess) {
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetExitCodeProcess(hProcess, &dwCode)) {
|
||||
return (dwCode == STILL_ACTIVE);
|
||||
if (dwCode == STILL_ACTIVE) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Return None to represent NoSuchProcess, else return NULL for
|
||||
// other exception or the name as a Python string
|
||||
PyObject*
|
||||
get_name(long pid)
|
||||
psutil_get_name(long pid)
|
||||
{
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe = { 0 };
|
||||
@ -266,7 +246,7 @@ get_name(long pid)
|
||||
|
||||
/* returns parent pid (as a Python int) for given pid or None on failure */
|
||||
PyObject*
|
||||
get_ppid(long pid)
|
||||
psutil_get_ppid(long pid)
|
||||
{
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe = { 0 };
|
||||
@ -296,7 +276,7 @@ get_ppid(long pid)
|
||||
* with given pid or NULL on error.
|
||||
*/
|
||||
PyObject*
|
||||
get_arg_list(long pid)
|
||||
psutil_get_arg_list(long pid)
|
||||
{
|
||||
int nArgs, i;
|
||||
LPWSTR *szArglist = NULL;
|
||||
@ -309,12 +289,12 @@ get_arg_list(long pid)
|
||||
PyObject *arg_from_wchar = NULL;
|
||||
PyObject *argList = NULL;
|
||||
|
||||
hProcess = handle_from_pid(pid);
|
||||
hProcess = psutil_handle_from_pid(pid);
|
||||
if(hProcess == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pebAddress = GetPebAddress(hProcess);
|
||||
pebAddress = psutil_get_peb_address(hProcess);
|
||||
|
||||
/* get the address of ProcessParameters */
|
||||
#ifdef _WIN64
|
||||
@ -347,6 +327,10 @@ get_arg_list(long pid)
|
||||
|
||||
/* 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,
|
||||
@ -386,7 +370,7 @@ get_arg_list(long pid)
|
||||
// arglist parsed as array of UNICODE_STRING, so convert each to Python
|
||||
// string object and add to arg list
|
||||
argList = Py_BuildValue("[]");
|
||||
if (!argList)
|
||||
if (argList == NULL)
|
||||
goto error;
|
||||
for(i=0; i<nArgs; i++) {
|
||||
arg_from_wchar = NULL;
|
||||
@ -468,6 +452,10 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
|
||||
|
||||
bufferSize = initialBufferSize;
|
||||
buffer = malloc(bufferSize);
|
||||
if (buffer == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
|
||||
while (TRUE) {
|
||||
status = NtQuerySystemInformation(SystemProcessInformation, buffer,
|
||||
@ -477,6 +465,10 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
|
||||
{
|
||||
free(buffer);
|
||||
buffer = malloc(bufferSize);
|
||||
if (buffer == NULL) {
|
||||
PyErr_NoMemory();
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else {
|
||||
break;
|
||||
@ -485,9 +477,7 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
|
||||
|
||||
if (status != 0) {
|
||||
PyErr_Format(PyExc_RuntimeError, "NtQuerySystemInformation() failed");
|
||||
FreeLibrary(hNtDll);
|
||||
free(buffer);
|
||||
return 0;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (bufferSize <= 0x20000) {
|
||||
@ -504,7 +494,11 @@ get_process_info(DWORD pid, PSYSTEM_PROCESS_INFORMATION *retProcess, PVOID *retB
|
||||
} while ( (process = PH_NEXT_PROCESS(process)) );
|
||||
|
||||
NoSuchProcess();
|
||||
goto error;
|
||||
|
||||
error:
|
||||
FreeLibrary(hNtDll);
|
||||
free(buffer);
|
||||
if (buffer != NULL)
|
||||
free(buffer);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.h 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
@ -12,14 +10,14 @@
|
||||
#include <Python.h>
|
||||
#include <windows.h>
|
||||
|
||||
HANDLE handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess);
|
||||
HANDLE handle_from_pid(DWORD pid);
|
||||
PVOID GetPebAddress(HANDLE ProcessHandle);
|
||||
HANDLE handle_from_pid(DWORD pid);
|
||||
BOOL is_running(HANDLE hProcess);
|
||||
int pid_in_proclist(DWORD pid);
|
||||
int pid_is_running(DWORD pid);
|
||||
PyObject* get_arg_list(long pid);
|
||||
PyObject* get_ppid(long pid);
|
||||
PyObject* get_name(long pid);
|
||||
DWORD* get_pids(DWORD *numberOfReturnedPIDs);
|
||||
HANDLE psutil_handle_from_pid_waccess(DWORD pid, DWORD dwDesiredAccess);
|
||||
HANDLE psutil_handle_from_pid(DWORD pid);
|
||||
PVOID psutil_get_peb_address(HANDLE ProcessHandle);
|
||||
HANDLE psutil_handle_from_pid(DWORD pid);
|
||||
int psutil_pid_in_proclist(DWORD pid);
|
||||
int psutil_pid_is_running(DWORD pid);
|
||||
int psutil_handlep_is_running(HANDLE hProcess);
|
||||
PyObject* psutil_get_arg_list(long pid);
|
||||
PyObject* psutil_get_ppid(long pid);
|
||||
PyObject* psutil_get_name(long pid);
|
||||
DWORD* psutil_get_pids(DWORD *numberOfReturnedPIDs);
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: security.c 1296 2012-04-25 01:29:43Z david.daeschler@gmail.com $
|
||||
*
|
||||
* 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.
|
||||
@ -68,10 +66,8 @@ int HasSystemPrivilege(HANDLE hProcess) {
|
||||
// allocate buffer and call GetTokenInformation again
|
||||
//tp = (PTOKEN_PRIVILEGES) GlobalAlloc(GPTR, dwSize);
|
||||
pBuffer = (BYTE *) malloc(dwSize);
|
||||
|
||||
if (pBuffer == NULL) {
|
||||
PyErr_SetFromWindowsErr(0);
|
||||
free(pBuffer);
|
||||
PyErr_NoMemory();
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -237,4 +233,3 @@ int UnsetSeDebug()
|
||||
CloseHandle(hToken);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: security.h 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
*
|
||||
* 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.
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.c 1460 2012-07-18 02:49:24Z g.rodola@gmail.com $
|
||||
*
|
||||
* 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.
|
||||
@ -28,7 +26,7 @@
|
||||
* Return 1 if PID exists in the current process list, else 0.
|
||||
*/
|
||||
int
|
||||
pid_exists(long pid)
|
||||
psutil_pid_exists(long pid)
|
||||
{
|
||||
int kill_ret;
|
||||
|
||||
@ -58,7 +56,7 @@ pid_exists(long pid)
|
||||
* On error, the function returns a BSD errno value.
|
||||
*/
|
||||
int
|
||||
get_proc_list(kinfo_proc **procList, size_t *procCount)
|
||||
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. */
|
||||
@ -125,7 +123,7 @@ get_proc_list(kinfo_proc **procList, size_t *procCount)
|
||||
|
||||
/* Read the maximum argument size for processes */
|
||||
int
|
||||
get_argmax()
|
||||
psutil_get_argmax()
|
||||
{
|
||||
int argmax;
|
||||
int mib[] = { CTL_KERN, KERN_ARGMAX };
|
||||
@ -140,7 +138,7 @@ get_argmax()
|
||||
|
||||
/* return process args as a python list */
|
||||
PyObject*
|
||||
get_arg_list(long pid)
|
||||
psutil_get_arg_list(long pid)
|
||||
{
|
||||
int mib[3];
|
||||
int nargs;
|
||||
@ -159,7 +157,7 @@ get_arg_list(long pid)
|
||||
}
|
||||
|
||||
/* read argmax and allocate memory for argument space. */
|
||||
argmax = get_argmax();
|
||||
argmax = psutil_get_argmax();
|
||||
if (! argmax) {
|
||||
PyErr_SetFromErrno(PyExc_OSError);
|
||||
goto error;
|
||||
@ -177,7 +175,7 @@ get_arg_list(long pid)
|
||||
mib[2] = pid;
|
||||
if (sysctl(mib, 3, procargs, &argmax, NULL, 0) < 0) {
|
||||
if (EINVAL == errno) { // invalid == access denied OR nonexistent PID
|
||||
if ( pid_exists(pid) ) {
|
||||
if ( psutil_pid_exists(pid) ) {
|
||||
AccessDenied();
|
||||
} else {
|
||||
NoSuchProcess();
|
||||
@ -238,7 +236,7 @@ error:
|
||||
|
||||
|
||||
int
|
||||
get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
|
||||
psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp)
|
||||
{
|
||||
int mib[4];
|
||||
size_t len;
|
||||
@ -276,7 +274,7 @@ 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 (! pid_exists(pid)) {
|
||||
if (! psutil_pid_exists(pid)) {
|
||||
NoSuchProcess();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
/*
|
||||
* $Id: process_info.h 1407 2012-06-30 17:14:54Z g.rodola@gmail.com $
|
||||
*
|
||||
* 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.
|
||||
@ -14,9 +12,9 @@
|
||||
|
||||
typedef struct kinfo_proc kinfo_proc;
|
||||
|
||||
int get_proc_list(kinfo_proc **procList, size_t *procCount);
|
||||
int get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
|
||||
int get_argmax(void);
|
||||
int pid_exists(long pid);
|
||||
int psutil_get_proc_list(kinfo_proc **procList, size_t *procCount);
|
||||
int psutil_get_kinfo_proc(pid_t pid, struct kinfo_proc *kp);
|
||||
int psutil_get_argmax(void);
|
||||
int psutil_pid_exists(long pid);
|
||||
int psutil_proc_pidinfo(long pid, int flavor, void *pti, int size);
|
||||
PyObject* get_arg_list(long pid);
|
||||
PyObject* psutil_get_arg_list(long pid);
|
||||
|
@ -1,73 +1,19 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: error.py 1142 2011-10-05 18:45:49Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
||||
"""psutil exception classes; do not import this directly"""
|
||||
"""This module is deprecated as exceptions are defined in _error.py
|
||||
and are supposed to be accessed from 'psutil' namespace as in:
|
||||
- psutil.NoSuchProcess
|
||||
- psutil.AccessDenied
|
||||
- psutil.TimeoutExpired
|
||||
"""
|
||||
|
||||
import warnings
|
||||
from psutil._error import *
|
||||
|
||||
class Error(Exception):
|
||||
"""Base exception class. All other psutil exceptions inherit
|
||||
from this one.
|
||||
"""
|
||||
|
||||
class NoSuchProcess(Error):
|
||||
"""Exception raised when a process with a certain PID doesn't
|
||||
or no longer exists (zombie).
|
||||
"""
|
||||
|
||||
def __init__(self, pid, name=None, msg=None):
|
||||
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
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class AccessDenied(Error):
|
||||
"""Exception raised when permission to perform an action is denied."""
|
||||
|
||||
def __init__(self, pid=None, name=None, msg=None):
|
||||
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 = ""
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
|
||||
class TimeoutExpired(Error):
|
||||
"""Raised on Process.wait(timeout) if timeout expires and process
|
||||
is still alive.
|
||||
"""
|
||||
|
||||
def __init__(self, pid=None, name=None):
|
||||
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
|
||||
else:
|
||||
self.msg = ""
|
||||
|
||||
def __str__(self):
|
||||
return self.msg
|
||||
|
||||
warnings.warn("psutil.error module is deprecated and scheduled for removal; " \
|
||||
"use psutil namespace instead", category=DeprecationWarning,
|
||||
stacklevel=2)
|
||||
|
@ -1,5 +0,0 @@
|
||||
[egg_info]
|
||||
tag_build =
|
||||
tag_date = 0
|
||||
tag_svn_revision = 0
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: setup.py 1469 2012-07-18 16:00:39Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -137,6 +135,7 @@ def main():
|
||||
'Programming Language :: Python :: 3.0',
|
||||
'Programming Language :: Python :: 3.1',
|
||||
'Programming Language :: Python :: 3.2',
|
||||
'Programming Language :: Python :: 3.3',
|
||||
'Topic :: System :: Monitoring',
|
||||
'Topic :: System :: Networking',
|
||||
'Topic :: System :: Networking :: Monitoring',
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _bsd.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _linux.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -14,6 +12,7 @@ import subprocess
|
||||
import sys
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
|
||||
from test_psutil import sh, get_test_subprocess
|
||||
from psutil._compat import PY3
|
||||
@ -115,6 +114,26 @@ class LinuxSpecificTestCase(unittest.TestCase):
|
||||
free = int(lines[2].split()[3]) * 1024
|
||||
self.assert_eq_w_tol(free, psutil.swap_memory().free, TOLERANCE)
|
||||
|
||||
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('.')))
|
||||
# steal >= 2.6.11
|
||||
# guest >= 2.6.24
|
||||
# guest_nice >= 3.2.0
|
||||
if kernel_ver_info >= (2, 6, 11):
|
||||
assert 'steal' in fields, fields
|
||||
else:
|
||||
assert 'steal' not in fields, fields
|
||||
if kernel_ver_info >= (2, 6, 24):
|
||||
assert 'guest' in fields, fields
|
||||
else:
|
||||
assert 'guest' not in fields, fields
|
||||
if kernel_ver_info >= (3, 2, 0):
|
||||
assert 'guest_nice' in fields, fields
|
||||
else:
|
||||
assert 'guest_nice' not in fields, fields
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
test_suite = unittest.TestSuite()
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _osx.py 1498 2012-07-24 21:41:28Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -22,7 +20,7 @@ from test_psutil import reap_children, get_test_subprocess, sh
|
||||
|
||||
|
||||
PAGESIZE = os.sysconf("SC_PAGE_SIZE")
|
||||
TOLERANCE = 200 * 1024 # 200 KB
|
||||
TOLERANCE = 500 * 1024 # 500 KB
|
||||
|
||||
|
||||
def sysctl(cmdline):
|
||||
@ -61,7 +59,7 @@ class OSXSpecificTestCase(unittest.TestCase):
|
||||
difference = abs(first - second)
|
||||
if difference <= tolerance:
|
||||
return
|
||||
msg = '%r != %r within %r delta (%r difference)' \
|
||||
msg = '%r != %r (tolerance=%r, difference=%s)' \
|
||||
% (first, second, tolerance, difference)
|
||||
raise AssertionError(msg)
|
||||
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _posix.py 1386 2012-06-27 15:44:36Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -19,7 +17,7 @@ import psutil
|
||||
|
||||
from psutil._compat import PY3
|
||||
from test_psutil import (get_test_subprocess, reap_children, PYTHON, LINUX, OSX,
|
||||
BSD, ignore_access_denied, sh, skipIf)
|
||||
BSD, skip_on_access_denied, sh, skipIf)
|
||||
|
||||
|
||||
def ps(cmd):
|
||||
@ -72,7 +70,7 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
username_psutil = psutil.Process(self.pid).username
|
||||
self.assertEqual(username_ps, username_psutil)
|
||||
|
||||
@ignore_access_denied
|
||||
@skip_on_access_denied()
|
||||
def test_process_rss_memory(self):
|
||||
# give python interpreter some time to properly initialize
|
||||
# so that the results are the same
|
||||
@ -81,7 +79,7 @@ class PosixSpecificTestCase(unittest.TestCase):
|
||||
rss_psutil = psutil.Process(self.pid).get_memory_info()[0] / 1024
|
||||
self.assertEqual(rss_ps, rss_psutil)
|
||||
|
||||
@ignore_access_denied
|
||||
@skip_on_access_denied()
|
||||
def test_process_vsz_memory(self):
|
||||
# give python interpreter some time to properly initialize
|
||||
# so that the results are the same
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: _windows.py 1453 2012-07-13 19:55:11Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: test_memory_leaks.py 1499 2012-07-25 12:42:31Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -149,7 +147,11 @@ class TestProcessObjectLeaks(Base):
|
||||
self.execute('get_ionice')
|
||||
|
||||
def test_set_ionice(self):
|
||||
self.execute('set_ionice', psutil.IOPRIO_CLASS_NONE)
|
||||
if WINDOWS:
|
||||
value = psutil.Process(os.getpid()).get_ionice()
|
||||
self.execute('set_ionice', value)
|
||||
else:
|
||||
self.execute('set_ionice', psutil.IOPRIO_CLASS_NONE)
|
||||
|
||||
def test_username(self):
|
||||
self.execute('username')
|
||||
|
@ -1,7 +1,5 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# $Id: test_psutil.py 1525 2012-08-16 16:32:03Z g.rodola $
|
||||
#
|
||||
|
||||
# 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.
|
||||
@ -33,7 +31,7 @@ import collections
|
||||
import datetime
|
||||
|
||||
import psutil
|
||||
from psutil._compat import PY3, callable, long
|
||||
from psutil._compat import PY3, callable, long, wraps
|
||||
|
||||
|
||||
PYTHON = os.path.realpath(sys.executable)
|
||||
@ -48,7 +46,7 @@ BSD = sys.platform.startswith("freebsd")
|
||||
|
||||
_subprocesses_started = set()
|
||||
|
||||
def get_test_subprocess(cmd=None, stdout=DEVNULL, stderr=DEVNULL, stdin=None,
|
||||
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
|
||||
@ -59,7 +57,7 @@ def get_test_subprocess(cmd=None, stdout=DEVNULL, stderr=DEVNULL, stdin=None,
|
||||
if cmd is None:
|
||||
pyline = ""
|
||||
if wait:
|
||||
pyline += "open('%s', 'w'); " % TESTFN
|
||||
pyline += "open(r'%s', 'w'); " % TESTFN
|
||||
pyline += "import time; time.sleep(3600);"
|
||||
cmd_ = [PYTHON, "-c", pyline]
|
||||
else:
|
||||
@ -68,7 +66,7 @@ def get_test_subprocess(cmd=None, stdout=DEVNULL, stderr=DEVNULL, stdin=None,
|
||||
if wait:
|
||||
if cmd is None:
|
||||
stop_at = time.time() + 3
|
||||
while time.time() > stop_at:
|
||||
while stop_at > time.time():
|
||||
if os.path.exists(TESTFN):
|
||||
break
|
||||
time.sleep(0.001)
|
||||
@ -166,7 +164,9 @@ def safe_remove(fname):
|
||||
try:
|
||||
os.remove(fname)
|
||||
except OSError:
|
||||
pass
|
||||
err = sys.exc_info()[1]
|
||||
if err.args[0] != errno.ENOENT:
|
||||
raise
|
||||
|
||||
def call_until(fun, expr, timeout=1):
|
||||
"""Keep calling function for timeout secs and exit if eval()
|
||||
@ -213,16 +213,22 @@ def skipUnless(condition, reason="", warn=False):
|
||||
return skipIf(True, reason, warn)
|
||||
return skipIf(False)
|
||||
|
||||
def ignore_access_denied(fun):
|
||||
def skip_on_access_denied(only_if=None):
|
||||
"""Decorator to Ignore AccessDenied exceptions."""
|
||||
def outer(fun, *args, **kwargs):
|
||||
def inner(self):
|
||||
def decorator(fun):
|
||||
@wraps(fun)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return fun(self, *args, **kwargs)
|
||||
return fun(*args, **kwargs)
|
||||
except psutil.AccessDenied:
|
||||
pass
|
||||
return inner
|
||||
return outer
|
||||
if only_if is not None:
|
||||
if not only_if:
|
||||
raise
|
||||
atexit.register(warn, "%r was skipped because it raised " \
|
||||
"AccessDenied" % fun.__name__)
|
||||
return wrapper
|
||||
return decorator
|
||||
|
||||
|
||||
def supports_ipv6():
|
||||
"""Return True if IPv6 is supported on this platform."""
|
||||
@ -320,12 +326,21 @@ class TestCase(unittest.TestCase):
|
||||
assert x > 0
|
||||
self.assertEqual(x, psutil.virtual_memory().total)
|
||||
|
||||
def test_BOOT_TIME(self):
|
||||
x = psutil.BOOT_TIME
|
||||
assert isinstance(x, float)
|
||||
assert x > 0
|
||||
def test_BOOT_TIME(self, arg=None):
|
||||
x = arg or psutil.BOOT_TIME
|
||||
assert isinstance(x, float), x
|
||||
assert x > 0, x
|
||||
assert x < time.time(), x
|
||||
|
||||
def test_get_boot_time(self):
|
||||
self.test_BOOT_TIME(psutil.get_boot_time())
|
||||
if WINDOWS:
|
||||
# work around float precision issues; give it 1 secs tolerance
|
||||
diff = abs(psutil.get_boot_time() - psutil.BOOT_TIME)
|
||||
assert diff < 1, diff
|
||||
else:
|
||||
self.assertEqual(psutil.get_boot_time(), psutil.BOOT_TIME)
|
||||
|
||||
def test_NUM_CPUS(self):
|
||||
self.assertEqual(psutil.NUM_CPUS, len(psutil.cpu_times(percpu=True)))
|
||||
assert psutil.NUM_CPUS >= 1, psutil.NUM_CPUS
|
||||
@ -342,6 +357,7 @@ class TestCase(unittest.TestCase):
|
||||
warnings.filterwarnings("error")
|
||||
p = psutil.Process(os.getpid())
|
||||
try:
|
||||
self.assertRaises(DeprecationWarning, __import__, 'psutil.error')
|
||||
self.assertRaises(DeprecationWarning, psutil.virtmem_usage)
|
||||
self.assertRaises(DeprecationWarning, psutil.used_phymem)
|
||||
self.assertRaises(DeprecationWarning, psutil.avail_phymem)
|
||||
@ -468,6 +484,8 @@ class TestCase(unittest.TestCase):
|
||||
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)))
|
||||
|
||||
def test_sys_per_cpu_times2(self):
|
||||
tot1 = psutil.cpu_times(percpu=True)
|
||||
@ -483,24 +501,42 @@ class TestCase(unittest.TestCase):
|
||||
return
|
||||
self.fail()
|
||||
|
||||
def _test_cpu_percent(self, percent):
|
||||
assert isinstance(percent, float), percent
|
||||
assert percent >= 0.0, percent
|
||||
assert percent <= 100.0, percent
|
||||
|
||||
def test_sys_cpu_percent(self):
|
||||
psutil.cpu_percent(interval=0.001)
|
||||
psutil.cpu_percent(interval=0.001)
|
||||
for x in range(1000):
|
||||
percent = psutil.cpu_percent(interval=None)
|
||||
assert isinstance(percent, float)
|
||||
assert percent >= 0.0, percent
|
||||
assert percent <= 100.0, percent
|
||||
self._test_cpu_percent(psutil.cpu_percent(interval=None))
|
||||
|
||||
def test_sys_per_cpu_percent(self):
|
||||
psutil.cpu_percent(interval=0.001, percpu=True)
|
||||
psutil.cpu_percent(interval=0.001, percpu=True)
|
||||
self.assertEqual(len(psutil.cpu_percent(interval=0.001, percpu=True)),
|
||||
psutil.NUM_CPUS)
|
||||
for x in range(1000):
|
||||
percents = psutil.cpu_percent(interval=None, percpu=True)
|
||||
for percent in percents:
|
||||
assert isinstance(percent, float)
|
||||
assert percent >= 0.0, percent
|
||||
assert percent <= 100.0, percent
|
||||
self._test_cpu_percent(percent)
|
||||
|
||||
def test_sys_cpu_times_percent(self):
|
||||
psutil.cpu_times_percent(interval=0.001)
|
||||
for x in range(1000):
|
||||
cpu = psutil.cpu_times_percent(interval=None)
|
||||
for percent in cpu:
|
||||
self._test_cpu_percent(percent)
|
||||
self._test_cpu_percent(sum(cpu))
|
||||
|
||||
def test_sys_per_cpu_times_percent(self):
|
||||
self.assertEqual(len(psutil.cpu_times_percent(interval=0.001,
|
||||
percpu=True)),
|
||||
psutil.NUM_CPUS)
|
||||
for x in range(1000):
|
||||
cpus = psutil.cpu_times_percent(interval=None, percpu=True)
|
||||
for cpu in cpus:
|
||||
for percent in cpu:
|
||||
self._test_cpu_percent(percent)
|
||||
self._test_cpu_percent(sum(cpu))
|
||||
|
||||
def test_disk_usage(self):
|
||||
usage = psutil.disk_usage(os.getcwd())
|
||||
@ -525,6 +561,8 @@ class TestCase(unittest.TestCase):
|
||||
|
||||
def test_disk_partitions(self):
|
||||
for disk in psutil.disk_partitions(all=False):
|
||||
if WINDOWS and 'cdrom' in disk.opts:
|
||||
continue
|
||||
assert os.path.exists(disk.device), disk
|
||||
assert os.path.isdir(disk.mountpoint), disk
|
||||
assert disk.fstype, disk
|
||||
@ -599,9 +637,17 @@ class TestCase(unittest.TestCase):
|
||||
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:
|
||||
# http://code.google.com/p/psutil/issues/detail?id=338
|
||||
while key[-1].isdigit():
|
||||
key = key[:-1]
|
||||
assert key not in ret, (key, ret.keys())
|
||||
|
||||
def test_get_users(self):
|
||||
users = psutil.get_users()
|
||||
@ -828,37 +874,53 @@ class TestCase(unittest.TestCase):
|
||||
assert io2.read_count >= io1.read_count, (io1, io2)
|
||||
assert io2.read_bytes >= io1.read_bytes, (io1, io2)
|
||||
|
||||
@skipUnless(LINUX)
|
||||
# Linux and Windows Vista+
|
||||
@skipUnless(hasattr(psutil.Process, 'get_ionice'))
|
||||
def test_get_set_ionice(self):
|
||||
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(os.getpid())
|
||||
try:
|
||||
p.set_ionice(2)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 4)
|
||||
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(os.getpid())
|
||||
try:
|
||||
p.set_ionice(2)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 4)
|
||||
#
|
||||
p.set_ionice(3)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 3)
|
||||
self.assertEqual(value, 0)
|
||||
#
|
||||
p.set_ionice(2, 0)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 0)
|
||||
p.set_ionice(2, 7)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 7)
|
||||
self.assertRaises(ValueError, p.set_ionice, 2, 10)
|
||||
finally:
|
||||
p.set_ionice(IOPRIO_CLASS_NONE)
|
||||
else:
|
||||
p = psutil.Process(os.getpid())
|
||||
original = p.get_ionice()
|
||||
try:
|
||||
value = 0 # very low
|
||||
if original == value:
|
||||
value = 1 # low
|
||||
p.set_ionice(value)
|
||||
self.assertEqual(p.get_ionice(), value)
|
||||
finally:
|
||||
p.set_ionice(original)
|
||||
#
|
||||
p.set_ionice(3)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 3)
|
||||
self.assertEqual(value, 0)
|
||||
#
|
||||
p.set_ionice(2, 0)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 0)
|
||||
p.set_ionice(2, 7)
|
||||
ioclass, value = p.get_ionice()
|
||||
self.assertEqual(ioclass, 2)
|
||||
self.assertEqual(value, 7)
|
||||
self.assertRaises(ValueError, p.set_ionice, 2, 10)
|
||||
finally:
|
||||
p.set_ionice(IOPRIO_CLASS_NONE)
|
||||
self.assertRaises(ValueError, p.set_ionice, 3)
|
||||
self.assertRaises(TypeError, p.set_ionice, 2, 1)
|
||||
|
||||
def test_get_num_threads(self):
|
||||
# on certain platforms such as Linux we might test for exact
|
||||
@ -983,14 +1045,18 @@ class TestCase(unittest.TestCase):
|
||||
try:
|
||||
self.assertEqual(exe, PYTHON)
|
||||
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.
|
||||
ver = "%s.%s" % (sys.version_info[0], sys.version_info[1])
|
||||
self.assertEqual(exe.replace(ver, ''), PYTHON.replace(ver, ''))
|
||||
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):
|
||||
sproc = get_test_subprocess([PYTHON, "-E"], wait=True)
|
||||
@ -998,8 +1064,9 @@ class TestCase(unittest.TestCase):
|
||||
|
||||
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()
|
||||
self.assertEqual(psutil.Process(sproc.pid).name.lower(), pyexe)
|
||||
assert pyexe.startswith(name), (pyexe, name)
|
||||
|
||||
if os.name == 'posix':
|
||||
|
||||
@ -1367,7 +1434,7 @@ class TestCase(unittest.TestCase):
|
||||
def test_get_num_ctx_switches(self):
|
||||
p = psutil.Process(os.getpid())
|
||||
before = sum(p.get_num_ctx_switches())
|
||||
for x in range(50000):
|
||||
for x in range(500000):
|
||||
after = sum(p.get_num_ctx_switches())
|
||||
if after > before:
|
||||
return
|
||||
@ -1428,7 +1495,7 @@ class TestCase(unittest.TestCase):
|
||||
except psutil.Error:
|
||||
pass
|
||||
# this is the one, now let's make sure there are no duplicates
|
||||
pid = max(sorted(table, key=lambda x: table[x]))
|
||||
pid = sorted(table.items(), key=lambda x: x[1])[-1][0]
|
||||
p = psutil.Process(pid)
|
||||
try:
|
||||
c = p.get_children(recursive=True)
|
||||
@ -1452,8 +1519,7 @@ class TestCase(unittest.TestCase):
|
||||
def test_invalid_pid(self):
|
||||
self.assertRaises(TypeError, psutil.Process, "1")
|
||||
self.assertRaises(TypeError, psutil.Process, None)
|
||||
# Refers to Issue #12
|
||||
self.assertRaises(psutil.NoSuchProcess, psutil.Process, -1)
|
||||
self.assertRaises(ValueError, psutil.Process, -1)
|
||||
|
||||
def test_as_dict(self):
|
||||
sproc = get_test_subprocess()
|
||||
@ -1569,6 +1635,21 @@ class TestCase(unittest.TestCase):
|
||||
self.assertIn(0, psutil.get_pid_list())
|
||||
self.assertTrue(psutil.pid_exists(0))
|
||||
|
||||
def test__all__(self):
|
||||
for name in dir(psutil):
|
||||
if name in ('callable', 'defaultdict', 'error', 'namedtuple'):
|
||||
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 'deprecated' not in fun.__doc__.lower():
|
||||
self.fail('%r not in psutil.__all__' % name)
|
||||
|
||||
def test_Popen(self):
|
||||
# Popen class test
|
||||
# XXX this test causes a ResourceWarning on Python 3 because
|
||||
@ -1620,8 +1701,11 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
continue
|
||||
attrs.append(name)
|
||||
|
||||
for p in psutil.process_iter():
|
||||
for name in attrs:
|
||||
default = object()
|
||||
failures = []
|
||||
for name in attrs:
|
||||
for p in psutil.process_iter():
|
||||
ret = default
|
||||
try:
|
||||
try:
|
||||
attr = getattr(p, name, None)
|
||||
@ -1632,6 +1716,13 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
valid_procs += 1
|
||||
except (psutil.NoSuchProcess, psutil.AccessDenied):
|
||||
err = sys.exc_info()[1]
|
||||
if isinstance(err, psutil.NoSuchProcess):
|
||||
if psutil.pid_exists(p.pid):
|
||||
# XXX race condition; we probably need
|
||||
# to try figuring out the process
|
||||
# identity before failing
|
||||
self.fail("PID still exists but fun raised " \
|
||||
"NoSuchProcess")
|
||||
self.assertEqual(err.pid, p.pid)
|
||||
if err.name:
|
||||
# make sure exception's name attr is set
|
||||
@ -1646,9 +1737,19 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
meth(ret)
|
||||
except Exception:
|
||||
err = sys.exc_info()[1]
|
||||
trace = traceback.format_exc()
|
||||
self.fail('%s\nproc=%s, method=%r, retvalue=%r'
|
||||
% (trace, p, name, ret))
|
||||
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.
|
||||
@ -1668,6 +1769,7 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
if POSIX:
|
||||
assert os.path.isfile(ret), 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):
|
||||
@ -1680,7 +1782,7 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
def create_time(self, ret):
|
||||
self.assertTrue(ret > 0)
|
||||
if not WINDOWS:
|
||||
self.assertTrue(ret >= psutil.BOOT_TIME)
|
||||
assert ret >= psutil.BOOT_TIME, (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))
|
||||
@ -1712,8 +1814,12 @@ class TestFetchAllProcesses(unittest.TestCase):
|
||||
self.assertTrue(field >= 0)
|
||||
|
||||
def get_ionice(self, ret):
|
||||
self.assertTrue(ret.ioclass >= 0)
|
||||
self.assertTrue(ret.value >= 0)
|
||||
if LINUX:
|
||||
self.assertTrue(ret.ioclass >= 0)
|
||||
self.assertTrue(ret.value >= 0)
|
||||
else:
|
||||
self.assertTrue(ret >= 0)
|
||||
self.assertIn(ret, (0, 1, 2))
|
||||
|
||||
def get_num_threads(self, ret):
|
||||
self.assertTrue(ret >= 1)
|
||||
@ -1907,6 +2013,7 @@ def cleanup():
|
||||
safe_remove(TESTFN)
|
||||
|
||||
atexit.register(cleanup)
|
||||
safe_remove(TESTFN)
|
||||
|
||||
def test_main():
|
||||
tests = []
|
||||
|
Loading…
Reference in New Issue
Block a user