diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2020-05-25 00:15:41 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-25 00:15:41 +0200 |
commit | c74ece234cf810796aa096e0880646879c758ae9 (patch) | |
tree | 353922c72bd13d5966c65a90b4aced627597b586 | |
parent | bd4d2bf420e1dfa3298143daebd485b97335b256 (diff) | |
download | psutil-c74ece234cf810796aa096e0880646879c758ae9.tar.gz |
[macOS] Fix zombie leak detection on (#1766)
-rwxr-xr-x | .ci/travis/install.sh | 12 | ||||
-rw-r--r-- | HISTORY.rst | 1 | ||||
-rw-r--r-- | psutil/_psbsd.py | 12 | ||||
-rw-r--r-- | psutil/_psosx.py | 13 | ||||
-rw-r--r-- | psutil/tests/__init__.py | 3 | ||||
-rwxr-xr-x | psutil/tests/test_connections.py | 3 | ||||
-rwxr-xr-x | psutil/tests/test_contracts.py | 3 |
7 files changed, 38 insertions, 9 deletions
diff --git a/.ci/travis/install.sh b/.ci/travis/install.sh index f06e43d5..16bd5c0c 100755 --- a/.ci/travis/install.sh +++ b/.ci/travis/install.sh @@ -24,13 +24,21 @@ if [[ "$(uname -s)" == 'Darwin' ]]; then pyenv install 3.6.6 pyenv virtualenv 3.6.6 psutil ;; + py37) + pyenv install 3.7.6 + pyenv virtualenv 3.7.6 psutil + ;; + py38) + pyenv install 3.8.2 + pyenv virtualenv 3.8.2 psutil + ;; esac pyenv rehash pyenv activate psutil fi if [[ $TRAVIS_PYTHON_VERSION == '2.7' ]] || [[ $PYVER == 'py27' ]]; then - pip install -U ipaddress mock + pip install -U ipaddress mock unittest2 fi -pip install -U coverage coveralls flake8 setuptools concurrencytest +pip install -U coverage coveralls flake8 setuptools diff --git a/HISTORY.rst b/HISTORY.rst index 3bae76b4..3cb021a1 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -31,6 +31,7 @@ XXXX-XX-XX - 1726_: [Linux] cpu_freq() parsing should use spaces instead of tabs on ia64. (patch by Michał Górny) - 1760_: [Linux] Process.rlimit() does not handle long long type properly. +- 1766_: [macOS] NoSuchProcess may be raised instead of ZombieProcess. 5.7.0 ===== diff --git a/psutil/_psbsd.py b/psutil/_psbsd.py index 49ad1e99..d53eb042 100644 --- a/psutil/_psbsd.py +++ b/psutil/_psbsd.py @@ -551,10 +551,10 @@ def wrap_exceptions(fun): try: return fun(self, *args, **kwargs) except ProcessLookupError: - if not pid_exists(self.pid): - raise NoSuchProcess(self.pid, self._name) - else: + if is_zombie(self.pid): raise ZombieProcess(self.pid, self._name, self._ppid) + else: + raise NoSuchProcess(self.pid, self._name) except PermissionError: raise AccessDenied(self.pid, self._name) except OSError: @@ -576,10 +576,10 @@ def wrap_exceptions_procfs(inst): # 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 not pid_exists(inst.pid): - raise NoSuchProcess(inst.pid, inst._name) - else: + if is_zombie(inst.pid): raise ZombieProcess(inst.pid, inst._name, inst._ppid) + else: + raise NoSuchProcess(inst.pid, inst._name) except PermissionError: raise AccessDenied(inst.pid, inst._name) diff --git a/psutil/_psosx.py b/psutil/_psosx.py index e4296495..2feff932 100644 --- a/psutil/_psosx.py +++ b/psutil/_psosx.py @@ -324,6 +324,14 @@ def pids(): pid_exists = _psposix.pid_exists +def is_zombie(pid): + try: + st = cext.proc_kinfo_oneshot(pid)[kinfo_proc_map['status']] + return st == cext.SZOMB + except Exception: + return False + + def wrap_exceptions(fun): """Decorator which translates bare OSError exceptions into NoSuchProcess and AccessDenied. @@ -333,7 +341,10 @@ def wrap_exceptions(fun): try: return fun(self, *args, **kwargs) except ProcessLookupError: - raise NoSuchProcess(self.pid, self._name) + if is_zombie(self.pid): + raise ZombieProcess(self.pid, self._name, self._ppid) + else: + raise NoSuchProcess(self.pid, self._name) except PermissionError: raise AccessDenied(self.pid, self._name) except cext.ZombieProcessError: diff --git a/psutil/tests/__init__.py b/psutil/tests/__init__.py index 6a119bf5..aac7614f 100644 --- a/psutil/tests/__init__.py +++ b/psutil/tests/__init__.py @@ -499,6 +499,9 @@ def terminate(proc_or_pid, sig=signal.SIGTERM, wait_timeout=GLOBAL_TIMEOUT): pass def sendsig(proc, sig): + # XXX: otherwise the build hangs for some reason. + if MACOS and GITHUB_WHEELS: + sig = signal.SIGKILL # If the process received SIGSTOP, SIGCONT is necessary first, # otherwise SIGTERM won't work. if POSIX and sig != signal.SIGKILL: diff --git a/psutil/tests/test_connections.py b/psutil/tests/test_connections.py index 8a9a6eb4..1a9b32f7 100755 --- a/psutil/tests/test_connections.py +++ b/psutil/tests/test_connections.py @@ -38,6 +38,7 @@ from psutil.tests import enum from psutil.tests import get_free_port from psutil.tests import HAS_CONNECTIONS_UNIX from psutil.tests import PsutilTestCase +from psutil.tests import reap_children from psutil.tests import serialrun from psutil.tests import skip_on_access_denied from psutil.tests import SKIP_SYSCONS @@ -392,6 +393,8 @@ class TestFilters(_ConnTestCase): @skip_on_access_denied(only_if=MACOS) def test_combos(self): + reap_children() + def check_conn(proc, conn, family, type, laddr, raddr, status, kinds): all_kinds = ("all", "inet", "inet4", "inet6", "tcp", "tcp4", "tcp6", "udp", "udp4", "udp6") diff --git a/psutil/tests/test_contracts.py b/psutil/tests/test_contracts.py index 35ab61e0..51bbb9f0 100755 --- a/psutil/tests/test_contracts.py +++ b/psutil/tests/test_contracts.py @@ -34,6 +34,7 @@ from psutil._compat import long from psutil._compat import range from psutil.tests import create_sockets from psutil.tests import enum +from psutil.tests import GITHUB_WHEELS from psutil.tests import HAS_CPU_FREQ from psutil.tests import HAS_NET_IO_COUNTERS from psutil.tests import HAS_SENSORS_FANS @@ -85,6 +86,7 @@ class TestAvailConstantsAPIs(PsutilTestCase): ae(hasattr(psutil, "IOPRIO_LOW"), WINDOWS) ae(hasattr(psutil, "IOPRIO_VERYLOW"), WINDOWS) + @unittest.skipIf(GITHUB_WHEELS, "not exposed via GITHUB_WHEELS") def test_linux_rlimit(self): ae = self.assertEqual ae(hasattr(psutil, "RLIM_INFINITY"), LINUX) @@ -149,6 +151,7 @@ class TestAvailProcessAPIs(PsutilTestCase): def test_ionice(self): self.assertEqual(hasattr(psutil.Process, "ionice"), LINUX or WINDOWS) + @unittest.skipIf(GITHUB_WHEELS, "not exposed via GITHUB_WHEELS") def test_rlimit(self): # requires Linux 2.6.36 self.assertEqual(hasattr(psutil.Process, "rlimit"), LINUX) |