Skip to content

Commit

Permalink
A developer encountered an AccessDenied exception today on a Mac
Browse files Browse the repository at this point in the history
Catch AccessDenied error in two other places in process_manager.py

Testing Done:
A developer encountered an AccessDenied exception today on a Mac

```
 File "/Users/pantsman/.pex/install/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl.d5493d74c62f5a977c5119c97760061ccd69069a/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl/pants/java/nailgun_executor.py", line 180, in _get_nailgun_client
    running, updated = self._check_nailgun_state(new_fingerprint)
  File "/Users/pantsman/.pex/install/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl.d5493d74c62f5a977c5119c97760061ccd69069a/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl/pants/java/nailgun_executor.py", line 169, in _check_nailgun_state
    old_fp=self.fingerprint, new_fp=new_fingerprint,
  File "/Users/toby/.pex/install/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl.d5493d74c62f5a977c5119c97760061ccd69069a/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl/pants/java/nailgun_executor.py", line 111, in fingerprint
    if self.cmdline:
  File "/Users/pantsman/.pex/install/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl.d5493d74c62f5a977c5119c97760061ccd69069a/pantsbuild.pants-0.0.49_square_20150924_01-py2-none-any.whl/pants/pantsd/process_manager.py", line 97, in cmdline
    return process.cmdline()
  File "/Users/pantsman/.pex/install/psutil-3.1.1-py2.7-macosx-10.4-x86_64.egg.35468d99e847e571301799156d9472c88ad8b757/psutil-3.1.1-py2.7-macosx-10.4-x86_64.egg/psutil/__init__.py", line 584, in cmdline
    return self._proc.cmdline()
  File "/Users/pantsman/.pex/install/psutil-3.1.1-py2.7-macosx-10.4-x86_64.egg.35468d99e847e571301799156d9472c88ad8b757/psutil-3.1.1-py2.7-macosx-10.4-x86_64.egg/psutil/_psosx.py", line 210, in wrapper
    raise AccessDenied(self.pid, self._name)
Exception message: psutil.AccessDenied (pid=19752, name='hdiejectd')
```

A simpler patch (adding an extra catch of AccessDenied exception) solved the problem for the user.

Bugs closed: 2343

Reviewed at https://rbcommons.com/s/twitter/r/2951/
  • Loading branch information
ericzundel committed Oct 9, 2015
1 parent 8511efb commit c01a668
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 19 deletions.
30 changes: 14 additions & 16 deletions src/python/pants/pantsd/process_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,29 +22,30 @@
logger = logging.getLogger(__name__)


@contextmanager
def swallow_psutil_exceptions():
"""A contextmanager that swallows standard psutil access exceptions."""
try:
yield
except (psutil.AccessDenied, psutil.NoSuchProcess):
# This masks common, but usually benign psutil process access exceptions that might be seen
# when accessing attributes/methods on psutil.Process objects.
pass


class ProcessGroup(object):
"""Wraps a logical group of processes and provides convenient access to ProcessManager objects."""

def __init__(self, name):
self._name = name

@contextmanager
def _swallow_psutil_exceptions(self):
"""A contextmanager that swallows standard psutil access exceptions."""
try:
yield
except (psutil.AccessDenied, psutil.NoSuchProcess):
# This masks common, but usually benign psutil process access exceptions that might be seen
# when accessing attributes/methods on psutil.Process objects.
pass

def _instance_from_process(self, process):
"""Default converter from psutil.Process to process instance classes for subclassing."""
return ProcessManager(name=process.name(), pid=process.pid, process_name=process.name())

def iter_processes(self, proc_filter=None):
proc_filter = proc_filter or (lambda x: True)
with self._swallow_psutil_exceptions():
with swallow_psutil_exceptions():
for proc in (x for x in psutil.process_iter() if proc_filter(x)):
yield proc

Expand Down Expand Up @@ -91,13 +92,10 @@ def cmdline(self):
:returns: The command line or else `None` if the underlying process has died.
"""
try:
with swallow_psutil_exceptions():
process = self._as_process()
if process:
return process.cmdline()
except psutil.NoSuchProcess:
# On some platforms, accessing attributes of a zombie'd Process results in NoSuchProcess.
pass
return None

@property
Expand Down Expand Up @@ -258,7 +256,7 @@ def is_alive(self):
if (process.status() == psutil.STATUS_ZOMBIE or # Check for walkers.
(self.process_name and self.process_name != process.name())): # Check for stale pids.
return False
except psutil.NoSuchProcess:
except (psutil.NoSuchProcess, psutil.AccessDenied):
# On some platforms, accessing attributes of a zombie'd Process results in NoSuchProcess.
return False

Expand Down
5 changes: 2 additions & 3 deletions tests/python/pants_test/pantsd/test_process_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@
unicode_literals, with_statement)

import os
import subprocess
import unittest
from contextlib import contextmanager

import mock
import psutil

from pants.pantsd.process_manager import ProcessGroup, ProcessManager
from pants.pantsd.process_manager import ProcessGroup, ProcessManager, swallow_psutil_exceptions
from pants.util.contextutil import temporary_dir


Expand All @@ -31,7 +30,7 @@ def setUp(self):
self.pg = ProcessGroup('test')

def test_swallow_psutil_exceptions(self):
with self.pg._swallow_psutil_exceptions():
with swallow_psutil_exceptions():
raise psutil.NoSuchProcess('test')

def test_iter_processes(self):
Expand Down

0 comments on commit c01a668

Please sign in to comment.