summaryrefslogtreecommitdiff
path: root/psutil/_pslinux.py
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2022-10-19 02:28:14 +0200
committerGiampaolo Rodola <g.rodola@gmail.com>2022-10-19 02:28:14 +0200
commitaa9a4f6f9bfaca1dd1d22034d007bbf5d86b9670 (patch)
tree106256b2c758aa7253c6b23a67b0938f0795acc2 /psutil/_pslinux.py
parent1da9f7928e79ecc127768e7a5bc4eb7f785f4513 (diff)
downloadpsutil-aa9a4f6f9bfaca1dd1d22034d007bbf5d86b9670.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.py28
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)