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:
Gregory Szorc 2013-05-09 15:39:30 -07:00
parent 09d57c5181
commit 04177dc5e6
57 changed files with 2096 additions and 1296 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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
View 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
View 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
View 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
View 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
View 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
View 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
View File

4
python/psutil/examples/pmap.py Normal file → Executable file
View 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
View 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
View 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
View 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.

View 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:

View File

@ -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')

View File

@ -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.

View 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

View File

@ -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
View 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()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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."},

View File

@ -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.

View 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;
}

View File

@ -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.

View 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;

View File

@ -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.

View 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,

View File

@ -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);

View File

@ -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."},

View File

@ -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.

View 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.

View 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.

View 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();
}
}

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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.

View 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;
}

View File

@ -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);

View File

@ -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)

View File

@ -1,5 +0,0 @@
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0

View File

@ -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',

View File

@ -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.

View 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()

View File

@ -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)

View File

@ -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

View File

@ -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.

View 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')

View File

@ -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 = []