diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2022-10-19 02:28:14 +0200 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2022-10-19 02:28:14 +0200 |
commit | aa9a4f6f9bfaca1dd1d22034d007bbf5d86b9670 (patch) | |
tree | 106256b2c758aa7253c6b23a67b0938f0795acc2 /psutil/_pslinux.py | |
parent | 1da9f7928e79ecc127768e7a5bc4eb7f785f4513 (diff) | |
download | psutil-linux-zombie-proc.tar.gz |
raise ZombieProcess instead of AccessDenied if process is a zombielinux-zombie-proc
Diffstat (limited to 'psutil/_pslinux.py')
-rw-r--r-- | psutil/_pslinux.py | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/psutil/_pslinux.py b/psutil/_pslinux.py index 9dc9643a..c16db892 100644 --- a/psutil/_pslinux.py +++ b/psutil/_pslinux.py @@ -1635,6 +1635,20 @@ def ppid_map(): return ret +def is_zombie(pid): + try: + data = bcat("%s/%s/stat" % (get_procfs_path(), pid)) + except EnvironmentError: + return False + else: + # Process name is between parentheses. It can contain spaces and + # other parentheses. This is taken into account by looking for + # the first occurrence of "(" and the last occurrence of ")". + rpar = data.rfind(b')') + fields = data[rpar + 2:].split() + return fields[0] == "Z" + + def wrap_exceptions(fun): """Decorator which translates bare OSError and IOError exceptions into NoSuchProcess and AccessDenied. @@ -1644,9 +1658,19 @@ def wrap_exceptions(fun): try: return fun(self, *args, **kwargs) except PermissionError: - raise AccessDenied(self.pid, self._name) + # Linux is peculiar in that accessing certain pseudo files + # like /proc/pid/fd/*, /proc/pid/environ and /proc/pid/io + # results in EPERM if process is a zombie. In such cases it + # appears more correct to raise ZP instead of AD. + if is_zombie(self.pid): + raise ZombieProcess(self.pid, self._name, self._ppid) + else: + raise AccessDenied(self.pid, self._name) 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 FileNotFoundError: if not os.path.exists("%s/%s" % (self._procfs_path, self.pid)): raise NoSuchProcess(self.pid, self._name) |