Skip to content

Commit

Permalink
fall back gracefully when psutil is not available
Browse files Browse the repository at this point in the history
  • Loading branch information
msarahan committed Feb 21, 2018
1 parent 48e1a27 commit f784a84
Showing 1 changed file with 21 additions and 18 deletions.
39 changes: 21 additions & 18 deletions conda_build/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import zipfile

import filelock
import psutil

from .conda_interface import hashsum_file, md5_file, unix_path_to_win, win_path_to_unix
from .conda_interface import PY3, iteritems
Expand Down Expand Up @@ -57,7 +56,6 @@
PermissionError = OSError
from scandir import scandir


on_win = (sys.platform == 'win32')

codec = getpreferredencoding() or 'utf-8'
Expand Down Expand Up @@ -108,6 +106,11 @@ def directory_size(path):
return total_size # size in bytes


class DummyPsutilProcess(object):
def children(*args, **kwargs):
return []


class PopenWrapper(object):
# Small wrapper around subprocess.Popen to allow memory usage monitoring
# copied from ProtoCI, https://github.com/ContinuumIO/ProtoCI/blob/59159bc2c9f991fbfa5e398b6bb066d7417583ec/protoci/build2.py#L20 # NOQA
Expand All @@ -116,31 +119,39 @@ def __init__(self, *args, **kwargs):
self.elapsed = None
self.rss = 0
self.vms = 0
# set returncode to a bad one
# in case it is never defined
# after here.
self.returncode = 173
self.returncode = None
self.disk = 0
self.processes = 1

self.out, self.err = self._execute(*args, **kwargs)

def _execute(self, *args, **kwargs):
try:
import psutil
psutil_exceptions = psutil.NoSuchProcess, psutil.AccessDenied, psutil.NoSuchProcess
except ImportError as e:
psutil = None
psutil_exceptions = (OSError, ValueError)
log = get_logger(__name__)
log.warn("psutil import failed. Error was {}".format(e))
log.warn("only disk usage and time statistics will be available. Install psutil to "
"get CPU time and memory usage statistics.")

# The polling interval (in seconds)
time_int = kwargs.pop('time_int', 1)

disk_usage_dir = kwargs.get('cwd', sys.prefix)

# Create a process of this (the parent) process
parent = psutil.Process(os.getpid())
parent = psutil.Process(os.getpid()) if psutil else DummyPsutilProcess()

cpu_usage = defaultdict(dict)

# Using the convenience Popen class provided by psutil
start_time = time.time()
_popen = psutil.Popen(*args, **kwargs)
_popen = psutil.Popen(*args, **kwargs) if psutil else subprocess.Popen(*args, **kwargs)
try:
while _popen.is_running():
while self.returncode is None:
# We need to get all of the children of our process since our
# process spawns other processes. Collect all of the child
# processes
Expand All @@ -162,7 +173,7 @@ def _execute(self, *args, **kwargs):
child_cpu_usage['sys'] = cpu_stats.system
child_cpu_usage['user'] = cpu_stats.user
cpu_usage[child.pid] = child_cpu_usage
except (psutil.ZombieProcess, psutil.AccessDenied, psutil.NoSuchProcess):
except psutil_exceptions:
# process already died. Just ignore it.
continue
processes += 1
Expand All @@ -180,14 +191,6 @@ def _execute(self, *args, **kwargs):
time.sleep(time_int)
self.elapsed = time.time() - start_time
self.returncode = _popen.poll()
if _popen.returncode is not None:
# without this if block
# builds hang
try:
_popen.kill()
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.NoSuchProcess):
pass
break
except KeyboardInterrupt:
_popen.kill()
raise
Expand Down

0 comments on commit f784a84

Please sign in to comment.