Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(73)

Unified Diff: third_party/psutil/psutil/_pslinux.py

Issue 8159001: Update third_party/psutil and fix the licence issue with it. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove the suppression and unnecessary files. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: third_party/psutil/psutil/_pslinux.py
diff --git a/third_party/psutil/psutil/_pslinux.py b/third_party/psutil/psutil/_pslinux.py
old mode 100644
new mode 100755
index 26a8abf55a6be0583b88f7a5dba320633c2168ea..443b6ade9d2a9744778cc30e9ac55cc2d5da6658
--- a/third_party/psutil/psutil/_pslinux.py
+++ b/third_party/psutil/psutil/_pslinux.py
@@ -1,15 +1,12 @@
#!/usr/bin/env python
#
-# $Id: _pslinux.py 800 2010-11-12 21:51:25Z g.rodola $
+# $Id: _pslinux.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.
-__all__ = ["NUM_CPUS", "TOTAL_PHYMEM",
- "PlatformProcess",
- "avail_phymem", "used_phymem", "total_virtmem", "avail_virtmem",
- "used_virtmem", "get_system_cpu_times", "pid_exists", "get_pid_list",
- "phymem_buffers", "cached_phymem"
- ]
-
+"""Linux platform implementation."""
import os
import errno
@@ -17,50 +14,72 @@ import socket
import struct
import sys
import base64
+import re
-try:
- from collections import namedtuple
-except ImportError:
- from psutil.compat import namedtuple # python < 2.6
-
+import _psutil_posix
+import _psutil_linux
from psutil import _psposix
-from psutil.error import AccessDenied, NoSuchProcess
+from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
+from psutil._common import *
+
+__extra__all__ = [
+ "IOPRIO_CLASS_NONE", "IOPRIO_CLASS_RT", "IOPRIO_CLASS_BE",
+ "IOPRIO_CLASS_IDLE",
+ "phymem_buffers", "cached_phymem"]
-def _get_uptime():
+def _get_boot_time():
"""Return system boot time (epoch in seconds)"""
f = open('/proc/stat', 'r')
- for line in f:
- if line.startswith('btime'):
- f.close()
- return float(line.strip().split()[1])
+ try:
+ for line in f:
+ if line.startswith('btime'):
+ return float(line.strip().split()[1])
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
def _get_num_cpus():
"""Return the number of CPUs on the system"""
num = 0
f = open('/proc/cpuinfo', 'r')
- for line in f:
- if line.startswith('processor'):
+ try:
+ lines = f.readlines()
+ finally:
+ f.close()
+ for line in lines:
+ if line.lower().startswith('processor'):
num += 1
- f.close()
- return num
-def _get_total_phymem():
- """Return the total amount of physical memory, in bytes"""
- f = open('/proc/meminfo', 'r')
- for line in f:
- if line.startswith('MemTotal:'):
+ # unknown format (e.g. amrel/sparc architectures), see:
+ # http://code.google.com/p/psutil/issues/detail?id=200
+ if num == 0:
+ f = open('/proc/stat', 'r')
+ try:
+ lines = f.readlines()
+ finally:
f.close()
- return int(line.split()[1]) * 1024
+ search = re.compile('cpu\d')
+ for line in lines:
+ line = line.split(' ')[0]
+ if search.match(line):
+ num += 1
+
+ if num == 0:
+ raise RuntimeError("can't determine number of CPUs")
+ return num
# Number of clock ticks per second
_CLOCK_TICKS = os.sysconf(os.sysconf_names["SC_CLK_TCK"])
-_UPTIME = _get_uptime()
+_TERMINAL_MAP = _psposix._get_terminal_map()
+BOOT_TIME = _get_boot_time()
NUM_CPUS = _get_num_cpus()
-TOTAL_PHYMEM = _get_total_phymem()
-
-del _get_uptime, _get_num_cpus, _get_total_phymem
+# ioprio_* constants http://linux.die.net/man/2/ioprio_get
+IOPRIO_CLASS_NONE = 0
+IOPRIO_CLASS_RT = 1
+IOPRIO_CLASS_BE = 2
+IOPRIO_CLASS_IDLE = 3
# http://students.mimuw.edu.pl/lxr/source/include/net/tcp_states.h
_TCP_STATES_TABLE = {"01" : "ESTABLISHED",
@@ -76,55 +95,20 @@ _TCP_STATES_TABLE = {"01" : "ESTABLISHED",
"0B" : "CLOSING"
}
-def avail_phymem():
- """Return the amount of physical memory available, in bytes."""
- f = open('/proc/meminfo', 'r')
- free = None
- _flag = False
- for line in f:
- if line.startswith('MemFree:'):
- free = int(line.split()[1]) * 1024
- break
- f.close()
- return free
-
-def used_phymem():
- """"Return the amount of physical memory used, in bytes."""
- return (TOTAL_PHYMEM - avail_phymem())
-
-def total_virtmem():
- """"Return the total amount of virtual memory, in bytes."""
- f = open('/proc/meminfo', 'r')
- for line in f:
- if line.startswith('SwapTotal:'):
- f.close()
- return int(line.split()[1]) * 1024
-
-def avail_virtmem():
- """Return the amount of virtual memory currently in use on the
- system, in bytes.
- """
- f = open('/proc/meminfo', 'r')
- for line in f:
- if line.startswith('SwapFree:'):
- f.close()
- return int(line.split()[1]) * 1024
-
-def used_virtmem():
- """Return the amount of used memory currently in use on the system,
- in bytes.
- """
- return total_virtmem() - avail_virtmem()
+# --- system memory functions
def cached_phymem():
"""Return the amount of cached memory on the system, in bytes.
This reflects the "cached" column of free command line utility.
"""
f = open('/proc/meminfo', 'r')
- for line in f:
- if line.startswith('Cached:'):
- f.close()
- return int(line.split()[1]) * 1024
+ try:
+ for line in f:
+ if line.startswith('Cached:'):
+ return int(line.split()[1]) * 1024
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
def phymem_buffers():
"""Return the amount of physical memory buffers used by the
@@ -132,36 +116,207 @@ def phymem_buffers():
This reflects the "buffers" column of free command line utility.
"""
f = open('/proc/meminfo', 'r')
- for line in f:
- if line.startswith('Buffers:'):
- f.close()
- return int(line.split()[1]) * 1024
+ try:
+ for line in f:
+ if line.startswith('Buffers:'):
+ return int(line.split()[1]) * 1024
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
+
+def phymem_usage():
+ # total, used and free values are matched against free cmdline utility
+ # the percentage matches top/htop and gnome-system-monitor
+ f = open('/proc/meminfo', 'r')
+ try:
+ total = free = buffers = cached = None
+ for line in f:
+ if line.startswith('MemTotal:'):
+ total = int(line.split()[1]) * 1024
+ elif line.startswith('MemFree:'):
+ free = int(line.split()[1]) * 1024
+ elif line.startswith('Buffers:'):
+ buffers = int(line.split()[1]) * 1024
+ elif line.startswith('Cached:'):
+ cached = int(line.split()[1]) * 1024
+ break
+ used = total - free
+ percent = usage_percent(total - (free + buffers + cached), total,
+ _round=1)
+ return ntuple_sysmeminfo(total, used, free, percent)
+ finally:
+ f.close()
+
+
+def virtmem_usage():
+ f = open('/proc/meminfo', 'r')
+ try:
+ total = free = None
+ for line in f:
+ if line.startswith('SwapTotal:'):
+ total = int(line.split()[1]) * 1024
+ elif line.startswith('SwapFree:'):
+ free = int(line.split()[1]) * 1024
+ if total is not None and free is not None:
+ break
+ assert total is not None and free is not None
+ used = total - free
+ percent = usage_percent(used, total, _round=1)
+ return ntuple_sysmeminfo(total, used, free, percent)
+ finally:
+ f.close()
+
+
+# --- system CPU functions
def get_system_cpu_times():
- """Return a dict representing the following CPU times:
+ """Return a named tuple representing the following CPU times:
user, nice, system, idle, iowait, irq, softirq.
"""
f = open('/proc/stat', 'r')
- values = f.readline().split()
- f.close()
+ try:
+ values = f.readline().split()
+ finally:
+ f.close()
values = values[1:8]
values = tuple([float(x) / _CLOCK_TICKS for x in values])
+ return ntuple_sys_cputimes(*values[:7])
+
+def get_system_per_cpu_times():
+ """Return a list of namedtuple representing the CPU times
+ for every CPU available on the system.
+ """
+ cpus = []
+ f = open('/proc/stat', 'r')
+ # get rid of the first line who refers to system wide CPU stats
+ try:
+ f.readline()
+ for line in f.readlines():
+ if line.startswith('cpu'):
+ values = line.split()[1:8]
+ values = tuple([float(x) / _CLOCK_TICKS for x in values])
+ entry = ntuple_sys_cputimes(*values[:7])
+ cpus.append(entry)
+ return cpus
+ finally:
+ f.close()
- return dict(user=values[0], nice=values[1], system=values[2], idle=values[3],
- iowait=values[4], irq=values[5], softirq=values[6])
+
+# --- system disk functions
+
+def disk_partitions(all=False):
+ """Return mounted disk partitions as a list of nameduples"""
+ phydevs = []
+ f = open("/proc/filesystems", "r")
+ try:
+ for line in f:
+ if not line.startswith("nodev"):
+ phydevs.append(line.strip())
+ finally:
+ f.close()
+
+ retlist = []
+ partitions = _psutil_linux.get_disk_partitions()
+ for partition in partitions:
+ device, mountpoint, fstype = partition
+ if device == 'none':
+ device = ''
+ if not all:
+ if device == '' or fstype not in phydevs:
+ continue
+ ntuple = ntuple_partition(device, mountpoint, fstype)
+ retlist.append(ntuple)
+ return retlist
+
+get_disk_usage = _psposix.get_disk_usage
+
+# --- process functions
def get_pid_list():
"""Returns a list of PIDs currently running on the system."""
pids = [int(x) for x in os.listdir('/proc') if x.isdigit()]
- # special case for 0 (kernel process) PID
- pids.insert(0, 0)
return pids
def pid_exists(pid):
"""Check For the existence of a unix pid."""
return _psposix.pid_exists(pid)
+def network_io_counters():
+ """Return network I/O statistics for every network interface
+ installed on the system as a dict of raw tuples.
+ """
+ f = open("/proc/net/dev", "r")
+ try:
+ lines = f.readlines()
+ finally:
+ f.close()
+
+ retdict = {}
+ for line in lines[2:]:
+ fields = line.split()
+ name = fields[0][:-1]
+ bytes_recv = int(fields[1])
+ packets_recv = int(fields[2])
+ bytes_sent = int(fields[9])
+ packets_sent = int(fields[10])
+ retdict[name] = (bytes_sent, bytes_recv, packets_sent, packets_recv)
+ return retdict
+
+def disk_io_counters():
+ """Return disk I/O statistics for every disk installed on the
+ system as a dict of raw tuples.
+ """
+ # man iostat states that sectors are equivalent with blocks and
+ # have a size of 512 bytes since 2.4 kernels. This value is
+ # needed to calculate the amount of disk I/O in bytes.
+ SECTOR_SIZE = 512
+
+ # determine partitions we want to look for
+ partitions = []
+ f = open("/proc/partitions", "r")
+ try:
+ lines = f.readlines()[2:]
+ finally:
+ f.close()
+ for line in lines:
+ _, _, _, name = line.split()
+ if name[-1].isdigit():
+ partitions.append(name)
+ #
+ retdict = {}
+ f = open("/proc/diskstats", "r")
+ try:
+ lines = f.readlines()
+ finally:
+ f.close()
+ for line in lines:
+ _, _, name, reads, _, rbytes, rtime, writes, _, wbytes, wtime = \
+ line.split()[:11]
+ if name in partitions:
+ rbytes = int(rbytes) * SECTOR_SIZE
+ 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)
+ return retdict
+
+
+# taken from /fs/proc/array.c
+_status_map = {"R" : STATUS_RUNNING,
+ "S" : STATUS_SLEEPING,
+ "D" : STATUS_DISK_SLEEP,
+ "T" : STATUS_STOPPED,
+ "t" : STATUS_TRACING_STOP,
+ "Z" : STATUS_ZOMBIE,
+ "X" : STATUS_DEAD,
+ "x" : STATUS_DEAD,
+ "K" : STATUS_WAKE_KILL,
+ "W" : STATUS_WAKING}
# --- decorators
@@ -173,7 +328,10 @@ def wrap_exceptions(callable):
try:
return callable(self, *args, **kwargs)
except (OSError, IOError), err:
- if err.errno == errno.ENOENT: # no such file or directory
+ # ENOENT (no such file or directory) gets raised on open().
+ # ESRCH (no such process) can get raised on read() if
+ # process is gone in meantime.
+ if err.errno in (errno.ENOENT, errno.ESRCH):
raise NoSuchProcess(self.pid, self._process_name)
if err.errno in (errno.EPERM, errno.EACCES):
raise AccessDenied(self.pid, self._process_name)
@@ -181,14 +339,9 @@ def wrap_exceptions(callable):
return wrapper
-class LinuxProcess(object):
+class Process(object):
"""Linux process implementation."""
- _meminfo_ntuple = namedtuple('meminfo', 'rss vms')
- _cputimes_ntuple = namedtuple('cputimes', 'user system')
- _openfile_ntuple = namedtuple('openfile', 'path fd')
- _connection_ntuple = namedtuple('connection', 'fd family type local_address '
- 'remote_address status')
__slots__ = ["pid", "_process_name"]
def __init__(self, pid):
@@ -197,8 +350,6 @@ class LinuxProcess(object):
@wrap_exceptions
def get_process_name(self):
- if self.pid == 0:
- return 'sched' # special case for kernel process
f = open("/proc/%s/stat" % self.pid)
try:
name = f.read().split(' ')[1].replace('(', '').replace(')', '')
@@ -209,7 +360,7 @@ class LinuxProcess(object):
def get_process_exe(self):
if self.pid in (0, 2):
- return "" # special case for kernel processes
+ raise AccessDenied(self.pid, self._process_name)
try:
exe = os.readlink("/proc/%s/exe" % self.pid)
except (OSError, IOError), err:
@@ -226,6 +377,10 @@ class LinuxProcess(object):
raise AccessDenied(self.pid, self._process_name)
raise
+ # readlink() might return paths containing null bytes causing
+ # problems when used with other fs-related functions (os.*,
+ # open(), ...)
+ exe = exe.replace('\x00', '')
# It seems symlinks can point to a deleted/invalid location
# (this usually happens with "pulseaudio" process).
# However, if we had permissions to execute readlink() it's
@@ -237,8 +392,6 @@ class LinuxProcess(object):
@wrap_exceptions
def get_process_cmdline(self):
- if self.pid == 0:
- return [] # special case for kernel process
f = open("/proc/%s/cmdline" % self.pid)
try:
# return the args as a list
@@ -247,28 +400,62 @@ class LinuxProcess(object):
f.close()
@wrap_exceptions
+ def get_process_terminal(self):
+ f = open("/proc/%s/stat" % self.pid)
+ try:
+ tty_nr = int(f.read().split(' ')[6])
+ finally:
+ f.close()
+ try:
+ return _TERMINAL_MAP[tty_nr]
+ except KeyError:
+ return None
+
+ @wrap_exceptions
+ def get_process_io_counters(self):
+ f = open("/proc/%s/io" % self.pid)
+ try:
+ for line in f:
+ if line.startswith("rchar"):
+ read_count = int(line.split()[1])
+ elif line.startswith("wchar"):
+ write_count = int(line.split()[1])
+ elif line.startswith("read_bytes"):
+ read_bytes = int(line.split()[1])
+ elif line.startswith("write_bytes"):
+ write_bytes = int(line.split()[1])
+ return ntuple_io(read_count, write_count, read_bytes, write_bytes)
+ finally:
+ f.close()
+
+ @wrap_exceptions
def get_cpu_times(self):
- # special case for 0 (kernel process) PID
- if self.pid == 0:
- return self._cputimes_ntuple(0.0, 0.0)
f = open("/proc/%s/stat" % self.pid)
- st = f.read().strip()
- f.close()
+ try:
+ st = f.read().strip()
+ finally:
+ f.close()
# ignore the first two values ("pid (exe)")
st = st[st.find(')') + 2:]
values = st.split(' ')
utime = float(values[11]) / _CLOCK_TICKS
stime = float(values[12]) / _CLOCK_TICKS
- return self._cputimes_ntuple(utime, stime)
+ return ntuple_cputimes(utime, stime)
+
+ @wrap_exceptions
+ def process_wait(self, timeout=None):
+ try:
+ return _psposix.wait_pid(self.pid, timeout)
+ except TimeoutExpired:
+ raise TimeoutExpired(self.pid, self._process_name)
@wrap_exceptions
def get_process_create_time(self):
- # special case for 0 (kernel processes) PID; return system uptime
- if self.pid == 0:
- return _UPTIME
f = open("/proc/%s/stat" % self.pid)
- st = f.read().strip()
- f.close()
+ try:
+ st = f.read().strip()
+ finally:
+ f.close()
# ignore the first two values ("pid (exe)")
st = st[st.find(')') + 2:]
values = st.split(' ')
@@ -276,43 +463,129 @@ class LinuxProcess(object):
# unit is jiffies (clock ticks).
# We first divide it for clock ticks and then add uptime returning
# seconds since the epoch, in UTC.
- starttime = (float(values[19]) / _CLOCK_TICKS) + _UPTIME
+ starttime = (float(values[19]) / _CLOCK_TICKS) + BOOT_TIME
return starttime
@wrap_exceptions
def get_memory_info(self):
- # special case for 0 (kernel processes) PID
- if self.pid == 0:
- return self._meminfo_ntuple(0, 0)
f = open("/proc/%s/status" % self.pid)
- virtual_size = 0
- resident_size = 0
- _flag = False
- for line in f:
- if (not _flag) and line.startswith("VmSize:"):
- virtual_size = int(line.split()[1]) * 1024
- _flag = True
- elif line.startswith("VmRSS"):
- resident_size = int(line.split()[1]) * 1024
- break
- f.close()
- return self._meminfo_ntuple(resident_size, virtual_size)
+ try:
+ virtual_size = 0
+ resident_size = 0
+ _flag = False
+ for line in f:
+ if (not _flag) and line.startswith("VmSize:"):
+ virtual_size = int(line.split()[1]) * 1024
+ _flag = True
+ elif line.startswith("VmRSS"):
+ resident_size = int(line.split()[1]) * 1024
+ break
+ return ntuple_meminfo(resident_size, virtual_size)
+ finally:
+ f.close()
@wrap_exceptions
def get_process_cwd(self):
- if self.pid == 0:
- return ''
- return os.readlink("/proc/%s/cwd" % self.pid)
+ # readlink() might return paths containing null bytes causing
+ # problems when used with other fs-related functions (os.*,
+ # open(), ...)
+ path = os.readlink("/proc/%s/cwd" % self.pid)
+ return path.replace('\x00', '')
@wrap_exceptions
def get_process_num_threads(self):
- if self.pid == 0:
- return 0
f = open("/proc/%s/status" % self.pid)
- for line in f:
- if line.startswith("Threads:"):
+ try:
+ for line in f:
+ if line.startswith("Threads:"):
+ return int(line.split()[1])
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
+
+ @wrap_exceptions
+ def get_process_threads(self):
+ thread_ids = os.listdir("/proc/%s/task" % self.pid)
+ thread_ids.sort()
+ retlist = []
+ for thread_id in thread_ids:
+ try:
+ f = open("/proc/%s/task/%s/stat" % (self.pid, thread_id))
+ except (OSError, IOError), err:
+ if err.errno == errno.ENOENT:
+ # no such file or directory; it means thread
+ # disappeared on us
+ continue
+ raise
+ try:
+ st = f.read().strip()
+ finally:
f.close()
- return int(line.split()[1])
+ # ignore the first two values ("pid (exe)")
+ st = st[st.find(')') + 2:]
+ values = st.split(' ')
+ utime = float(values[11]) / _CLOCK_TICKS
+ stime = float(values[12]) / _CLOCK_TICKS
+ ntuple = ntuple_thread(int(thread_id), utime, stime)
+ retlist.append(ntuple)
+ return retlist
+
+ @wrap_exceptions
+ def get_process_nice(self):
+ #f = open('/proc/%s/stat' % self.pid, 'r')
+ #try:
+ # data = f.read()
+ # return int(data.split()[18])
+ #finally:
+ # f.close()
+
+ # Use C implementation
+ return _psutil_posix.getpriority(self.pid)
+
+ @wrap_exceptions
+ def set_process_nice(self, value):
+ return _psutil_posix.setpriority(self.pid, value)
+
+ # only starting from kernel 2.6.13
+ if hasattr(_psutil_linux, "ioprio_get"):
+
+ @wrap_exceptions
+ def get_process_ionice(self):
+ ioclass, value = _psutil_linux.ioprio_get(self.pid)
+ return ntuple_ionice(ioclass, value)
+
+ @wrap_exceptions
+ def set_process_ionice(self, ioclass, value):
+ if ioclass in (IOPRIO_CLASS_NONE, None):
+ if value:
+ raise ValueError("can't specify value with IOPRIO_CLASS_NONE")
+ ioclass = IOPRIO_CLASS_NONE
+ value = 0
+ if ioclass in (IOPRIO_CLASS_RT, IOPRIO_CLASS_BE):
+ if value is None:
+ value = 4
+ elif ioclass == IOPRIO_CLASS_IDLE:
+ if value:
+ raise ValueError("can't specify value with IOPRIO_CLASS_IDLE")
+ value = 0
+ else:
+ value = 0
+ if not 0 <= value <= 8:
+ raise ValueError("value argument range expected is between 0 and 8")
+ return _psutil_linux.ioprio_set(self.pid, ioclass, value)
+
+ @wrap_exceptions
+ def get_process_status(self):
+ f = open("/proc/%s/status" % self.pid)
+ try:
+ for line in f:
+ if line.startswith("State:"):
+ letter = line.split()[1]
+ if letter in _status_map:
+ return _status_map[letter]
+ return constant(-1, '?')
+ finally:
+ f.close()
@wrap_exceptions
def get_open_files(self):
@@ -329,20 +602,12 @@ class LinuxProcess(object):
if file == "[]":
continue
if os.path.isfile(file) and not file in retlist:
- ntuple = self._openfile_ntuple(file, int(fd))
+ ntuple = ntuple_openfile(file, int(fd))
retlist.append(ntuple)
return retlist
-# --- lsof implementation
-#
-# def get_open_files(self):
-# lsof = _psposix.LsofParser(self.pid, self._process_name)
-# return lsof.get_process_open_files()
-
@wrap_exceptions
def get_connections(self):
- if self.pid == 0:
- return []
inodes = {}
# os.listdir() is gonna raise a lot of access denied
# exceptions in case of unprivileged user; that's fine:
@@ -364,27 +629,37 @@ class LinuxProcess(object):
def process(file, family, _type):
retlist = []
f = open(file)
- f.readline() # skip the first line
- for line in f:
- _, laddr, raddr, status, _, _, _, _, _, inode = line.split()[:10]
- if inode in inodes:
- laddr = self._decode_address(laddr, family)
- raddr = self._decode_address(raddr, family)
- if _type == socket.SOCK_STREAM:
- status = _TCP_STATES_TABLE[status]
- else:
- status = ""
- fd = int(inodes[inode])
- conn = self._connection_ntuple(fd, family, _type, laddr,
- raddr, status)
- retlist.append(conn)
- f.close()
- return retlist
+ try:
+ f.readline() # skip the first line
+ for line in f:
+ _, laddr, raddr, status, _, _, _, _, _, inode = \
+ line.split()[:10]
+ if inode in inodes:
+ laddr = self._decode_address(laddr, family)
+ raddr = self._decode_address(raddr, family)
+ if _type == socket.SOCK_STREAM:
+ status = _TCP_STATES_TABLE[status]
+ else:
+ status = ""
+ fd = int(inodes[inode])
+ conn = ntuple_connection(fd, family, _type, laddr,
+ raddr, status)
+ retlist.append(conn)
+ return retlist
+ finally:
+ f.close()
tcp4 = process("/proc/net/tcp", socket.AF_INET, socket.SOCK_STREAM)
- tcp6 = process("/proc/net/tcp6", socket.AF_INET6, socket.SOCK_STREAM)
udp4 = process("/proc/net/udp", socket.AF_INET, socket.SOCK_DGRAM)
- udp6 = process("/proc/net/udp6", socket.AF_INET6, socket.SOCK_DGRAM)
+ try:
+ tcp6 = process("/proc/net/tcp6", socket.AF_INET6, socket.SOCK_STREAM)
+ udp6 = process("/proc/net/udp6", socket.AF_INET6, socket.SOCK_DGRAM)
+ except IOError, err:
+ if err.errno == errno.ENOENT:
+ # IPv6 is not supported on this platform
+ tcp6 = udp6 = []
+ else:
+ raise
return tcp4 + tcp6 + udp4 + udp6
# --- lsof implementation
@@ -395,40 +670,39 @@ class LinuxProcess(object):
@wrap_exceptions
def get_process_ppid(self):
- if self.pid == 0:
- return 0
f = open("/proc/%s/status" % self.pid)
- for line in f:
- if line.startswith("PPid:"):
- # PPid: nnnn
- f.close()
- return int(line.split()[1])
+ try:
+ for line in f:
+ if line.startswith("PPid:"):
+ # PPid: nnnn
+ return int(line.split()[1])
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
@wrap_exceptions
- def get_process_uid(self):
- if self.pid == 0:
- return 0
+ def get_process_uids(self):
f = open("/proc/%s/status" % self.pid)
- for line in f:
- if line.startswith('Uid:'):
- # Uid line provides 4 values which stand for real,
- # effective, saved set, and file system UIDs.
- # We want to provide real UID only.
- f.close()
- return int(line.split()[1])
+ try:
+ for line in f:
+ if line.startswith('Uid:'):
+ _, real, effective, saved, fs = line.split()
+ return ntuple_uids(int(real), int(effective), int(saved))
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
@wrap_exceptions
- def get_process_gid(self):
- if self.pid == 0:
- return 0
+ def get_process_gids(self):
f = open("/proc/%s/status" % self.pid)
- for line in f:
- if line.startswith('Gid:'):
- # Uid line provides 4 values which stand for real,
- # effective, saved set, and file system GIDs.
- # We want to provide real GID only.
- f.close()
- return int(line.split()[1])
+ try:
+ for line in f:
+ if line.startswith('Gid:'):
+ _, real, effective, saved, fs = line.split()
+ return ntuple_gids(int(real), int(effective), int(saved))
+ raise RuntimeError("line not found")
+ finally:
+ f.close()
@staticmethod
def _decode_address(addr, family):
@@ -438,9 +712,9 @@ class LinuxProcess(object):
"0500000A:0016" -> ("10.0.0.5", 22)
"0000000000000000FFFF00000100007F:9E49" -> ("::ffff:127.0.0.1", 40521)
- The IPv4 address portion is a little-endian four-byte hexadecimal
- number; that is, the least significant byte is listed first,
- so we need to reverse the order of the bytes to convert it
+ The IP address portion is a little or big endian four-byte
+ hexadecimal number; that is, the least significant byte is listed
+ first, so we need to reverse the order of the bytes to convert it
to an IP address.
The port is represented as a two-byte hexadecimal number.
@@ -456,16 +730,22 @@ class LinuxProcess(object):
if not port:
return ()
if family == socket.AF_INET:
- ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1])
+ # see: http://code.google.com/p/psutil/issues/detail?id=201
+ if sys.byteorder == 'little':
+ ip = socket.inet_ntop(family, base64.b16decode(ip)[::-1])
+ else:
+ ip = socket.inet_ntop(family, base64.b16decode(ip))
else: # IPv6
# old version - let's keep it, just in case...
#ip = ip.decode('hex')
#return socket.inet_ntop(socket.AF_INET6,
# ''.join(ip[i:i+4][::-1] for i in xrange(0, 16, 4)))
ip = base64.b16decode(ip)
- ip = socket.inet_ntop(socket.AF_INET6,
+ # see: http://code.google.com/p/psutil/issues/detail?id=201
+ if sys.byteorder == 'little':
+ ip = socket.inet_ntop(socket.AF_INET6,
struct.pack('>4I', *struct.unpack('<4I', ip)))
+ else:
+ ip = socket.inet_ntop(socket.AF_INET6,
+ struct.pack('<4I', *struct.unpack('<4I', ip)))
return (ip, port)
-
-PlatformProcess = LinuxProcess
-
« no previous file with comments | « third_party/psutil/psutil/_psbsd.py ('k') | third_party/psutil/psutil/_psmswindows.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698