| Index: third_party/psutil/psutil/_psposix.py
|
| diff --git a/third_party/psutil/psutil/_psposix.py b/third_party/psutil/psutil/_psposix.py
|
| deleted file mode 100644
|
| index 08cc268f659f90f811989ea4ce69da0fd2493d09..0000000000000000000000000000000000000000
|
| --- a/third_party/psutil/psutil/_psposix.py
|
| +++ /dev/null
|
| @@ -1,318 +0,0 @@
|
| -#!/usr/bin/env python
|
| -#
|
| -# $Id: _psposix.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.
|
| -
|
| -"""Routines common to all posix systems."""
|
| -
|
| -import os
|
| -import errno
|
| -import subprocess
|
| -import psutil
|
| -import socket
|
| -import re
|
| -import sys
|
| -import warnings
|
| -import time
|
| -import glob
|
| -
|
| -from psutil.error import AccessDenied, NoSuchProcess, TimeoutExpired
|
| -from psutil._compat import namedtuple
|
| -from psutil._common import ntuple_diskinfo, usage_percent
|
| -
|
| -
|
| -def pid_exists(pid):
|
| - """Check whether pid exists in the current process table."""
|
| - if pid < 0:
|
| - return False
|
| - try:
|
| - os.kill(pid, 0)
|
| - except OSError, e:
|
| - return e.errno == errno.EPERM
|
| - else:
|
| - return True
|
| -
|
| -def wait_pid(pid, timeout=None):
|
| - """Wait for process with pid 'pid' to terminate and return its
|
| - exit status code as an integer.
|
| -
|
| - If pid is not a children of os.getpid() (current process) just
|
| - waits until the process disappears and return None.
|
| -
|
| - If pid does not exist at all return None immediately.
|
| -
|
| - Raise TimeoutExpired on timeout expired.
|
| - """
|
| - def check_timeout():
|
| - if timeout is not None:
|
| - if time.time() >= stop_at:
|
| - raise TimeoutExpired
|
| - time.sleep(0.001)
|
| -
|
| - if timeout is not None:
|
| - waitcall = lambda: os.waitpid(pid, os.WNOHANG)
|
| - stop_at = time.time() + timeout
|
| - else:
|
| - waitcall = lambda: os.waitpid(pid, 0)
|
| -
|
| - while 1:
|
| - try:
|
| - retpid, status = waitcall()
|
| - except OSError, err:
|
| - if err.errno == errno.EINTR:
|
| - check_timeout()
|
| - continue
|
| - elif err.errno == errno.ECHILD:
|
| - # not a child of os.getpid(): poll until pid has
|
| - # disappeared and return None instead
|
| - while 1:
|
| - if pid_exists(pid):
|
| - check_timeout()
|
| - else:
|
| - return
|
| - else:
|
| - raise
|
| - else:
|
| - if retpid == 0:
|
| - check_timeout()
|
| - continue
|
| - # process exited due to a signal; return the integer of
|
| - # that signal
|
| - if os.WIFSIGNALED(status):
|
| - return os.WTERMSIG(status)
|
| - # process exited using exit(2) system call; return the
|
| - # integer exit(2) system call has been called with
|
| - elif os.WIFEXITED(status):
|
| - return os.WEXITSTATUS(status)
|
| - else:
|
| - # should never happen
|
| - raise RuntimeError("unknown process exit status")
|
| -
|
| -def get_disk_usage(path):
|
| - """Return disk usage associated with path."""
|
| - st = os.statvfs(path)
|
| - free = (st.f_bavail * st.f_frsize)
|
| - total = (st.f_blocks * st.f_frsize)
|
| - used = (st.f_blocks - st.f_bfree) * st.f_frsize
|
| - percent = usage_percent(used, total, _round=1)
|
| - # NB: the percentage is -5% than what shown by df due to
|
| - # reserved blocks that we are currently not considering:
|
| - # http://goo.gl/sWGbH
|
| - return ntuple_diskinfo(total, used, free, percent)
|
| -
|
| -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
|
| - return ret
|
| -
|
| -
|
| -class LsofParser:
|
| - """A wrapper for lsof command line utility.
|
| - Executes lsof in subprocess and parses its output.
|
| - """
|
| - socket_table = {'TCP' : socket.SOCK_STREAM,
|
| - 'UDP' : socket.SOCK_DGRAM,
|
| - 'IPv4' : socket.AF_INET,
|
| - 'IPv6' : socket.AF_INET6}
|
| - _openfile_ntuple = namedtuple('openfile', 'path fd')
|
| - _connection_ntuple = namedtuple('connection', 'fd family type local_address '
|
| - 'remote_address status')
|
| -
|
| - def __init__(self, pid, name):
|
| - self.pid = pid
|
| - self.process_name = name
|
| -
|
| - def get_process_open_files(self):
|
| - """Return files opened by process by parsing lsof output."""
|
| - # Options:
|
| - # -i == network files only
|
| - # -a == ANDing of all options
|
| - # -p == process with given PID only
|
| - # -n == do not resolve IP addresses
|
| - # -P == do not resolve port numbers
|
| - # -w == suppresses warnings
|
| - # -F0nPt == (0) separate lines with "\x00"
|
| - # (n) file name
|
| - # (t) file type
|
| - # (f) file descriptr
|
| - cmd = "lsof -a -p %s -n -P -F0ftn" % self.pid
|
| - stdout = self.runcmd(cmd)
|
| - if not stdout:
|
| - return []
|
| - files = []
|
| - lines = stdout.split("\n")
|
| - del lines[0] # first line contains the PID
|
| - for line in lines:
|
| - if not line:
|
| - continue
|
| - line = line.strip("\x00")
|
| - fields = {}
|
| - for field in line.split("\x00"):
|
| - key, value = field[0], field[1:]
|
| - fields[key] = value
|
| - if not 't' in fields:
|
| - continue
|
| - _type = fields['t']
|
| - fd = fields['f']
|
| - name = fields['n']
|
| - if 'REG' in _type and fd.isdigit():
|
| - if not os.path.isfile(os.path.realpath(name)):
|
| - continue
|
| - ntuple = self._openfile_ntuple(name, int(fd))
|
| - files.append(ntuple)
|
| - return files
|
| -
|
| - def get_process_connections(self):
|
| - """Return connections opened by a process by parsing lsof output."""
|
| - # Options:
|
| - # -i == network files only
|
| - # -a == ANDing of all options
|
| - # -p == process with given PID only
|
| - # -n == do not resolve IP addresses
|
| - # -P == do not resolve port numbers
|
| - # -w == suppresses warnings
|
| - # -F0nPt == (0) separate lines with "\x00"
|
| - # (n) and show internet addresses only
|
| - # (P) protocol type (TCP, UPD, Unix)
|
| - # (t) socket family (IPv4, IPv6)
|
| - # (T) connection status
|
| - # (f) file descriptors
|
| - cmd = "lsof -p %s -i -a -F0nPtTf -n -P" % self.pid
|
| - stdout = self.runcmd(cmd)
|
| - if not stdout:
|
| - return []
|
| - connections = []
|
| - lines = stdout.split()
|
| - del lines[0] # first line contains the PID
|
| - for line in lines:
|
| - line = line.strip("\x00")
|
| - fields = {}
|
| - for field in line.split("\x00"):
|
| - if field.startswith('T'):
|
| - key, value = field.split('=')
|
| - else:
|
| - key, value = field[0], field[1:]
|
| - fields[key] = value
|
| -
|
| - # XXX - might trow execption; needs "continue on unsupported
|
| - # family or type" (e.g. unix sockets)
|
| - # we consider TCP and UDP sockets only
|
| - stype = fields['P']
|
| - if stype not in self.socket_table:
|
| - continue
|
| - else:
|
| - _type = self.socket_table[fields['P']]
|
| - family = self.socket_table[fields['t']]
|
| - peers = fields['n']
|
| - fd = int(fields['f'])
|
| - if _type == socket.SOCK_STREAM:
|
| - status = fields['TST']
|
| - # OS X shows "CLOSED" instead of "CLOSE" so translate them
|
| - if status == "CLOSED":
|
| - status = "CLOSE"
|
| - else:
|
| - status = ""
|
| - if not '->' in peers:
|
| - local_addr = self._normaddress(peers, family)
|
| - remote_addr = ()
|
| - # OS X processes e.g. SystemUIServer can return *:* for local
|
| - # address, so we return 0 and move on
|
| - if local_addr == 0:
|
| - continue
|
| - else:
|
| - local_addr, remote_addr = peers.split("->")
|
| - local_addr = self._normaddress(local_addr, family)
|
| - remote_addr = self._normaddress(remote_addr, family)
|
| -
|
| - conn = self._connection_ntuple(fd, family, _type, local_addr,
|
| - remote_addr, status)
|
| - connections.append(conn)
|
| -
|
| - return connections
|
| -
|
| - def runcmd(self, cmd):
|
| - """Expects an lsof-related command line, execute it in a
|
| - subprocess and return its output.
|
| - If something goes bad stderr is parsed and proper exceptions
|
| - raised as necessary.
|
| - """
|
| - p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE,
|
| - stderr=subprocess.PIPE)
|
| - stdout, stderr = p.communicate()
|
| - if sys.version_info >= (3,):
|
| - stdout, stderr = map(lambda x: x.decode(sys.stdout.encoding),
|
| - (stdout, stderr))
|
| - if stderr:
|
| - utility = cmd.split(' ')[0]
|
| - if self._which(utility) is None:
|
| - msg = "this functionnality requires %s command line utility " \
|
| - "to be installed on the system" % utility
|
| - raise NotImplementedError(msg)
|
| - elif "permission denied" in stderr.lower():
|
| - # "permission denied" can be found also in case of zombie
|
| - # processes;
|
| - p = psutil.Process(self.pid)
|
| - if not p.is_running():
|
| - raise NoSuchProcess(self.pid, self.process_name)
|
| - raise AccessDenied(self.pid, self.process_name)
|
| - elif "lsof: warning:" in stderr.lower():
|
| - # usually appears when lsof is run for the first time and
|
| - # complains about missing cache file in user home
|
| - warnings.warn(stderr, RuntimeWarning)
|
| - else:
|
| - # this must be considered an application bug
|
| - raise RuntimeError(stderr)
|
| - if not stdout:
|
| - p = psutil.Process(self.pid)
|
| - if not p.is_running():
|
| - raise NoSuchProcess(self.pid, self.process_name)
|
| - return ""
|
| - return stdout
|
| -
|
| - @staticmethod
|
| - def _which(program):
|
| - """Same as UNIX which command. Return None on command not found."""
|
| - def is_exe(fpath):
|
| - return os.path.isfile(fpath) and os.access(fpath, os.X_OK)
|
| -
|
| - fpath, fname = os.path.split(program)
|
| - if fpath:
|
| - if is_exe(program):
|
| - return program
|
| - else:
|
| - for path in os.environ["PATH"].split(os.pathsep):
|
| - exe_file = os.path.join(path, program)
|
| - if is_exe(exe_file):
|
| - return exe_file
|
| - return None
|
| -
|
| - @staticmethod
|
| - def _normaddress(addr, family):
|
| - """Normalize an IP address."""
|
| - assert family in (socket.AF_INET, socket.AF_INET6), "unsupported family"
|
| - if family == socket.AF_INET:
|
| - ip, port = addr.split(':')
|
| - else:
|
| - if "]" in addr:
|
| - ip, port = re.findall('\[([^]]+)\]:([0-9]+)', addr)[0]
|
| - else:
|
| - ip, port = addr.split(':')
|
| - if ip == '*':
|
| - if family == socket.AF_INET:
|
| - ip = "0.0.0.0"
|
| - elif family == socket.AF_INET6:
|
| - ip = "::"
|
| - # OS X can have some procs e.g. SystemUIServer listening on *:*
|
| - else:
|
| - raise ValueError("invalid IP %s" %addr)
|
| - if port == "*":
|
| - return 0
|
| - return (ip, int(port))
|
| -
|
| -
|
|
|