From a752e7995bfdabb08b5bb6bcd437b9a5d2e53a7a Mon Sep 17 00:00:00 2001 From: John Kacur Date: Thu, 9 Dec 2021 10:11:07 -0500 Subject: [PATCH 2/2] python-linux-procfs: Fix UnicodeDecodeError Commit 7570fc0d6082 meant to solve the UnicodeDecodeError Instead it actually increased the problem by reading lines as bytes and decoding them. The original problem is hard to trigger and doesn't trigger consistently with reproducers. In addition there seems to be a difference in how this is handled between python-3.6 to python-3.9 For now, we should return the code to reading as utf-8 (the default) since that handles more cases than the current code. We can catch the UnicodeDecodeError and ignore it for now. It is not ideal because we are not handling some pids that trigger the error. This patch also includes a fix for a FileNotFoundError which can occur if a pid exits and disappears before we try to read it in the /proc file system. Signed-off-by: John Kacur --- procfs/procfs.py | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/procfs/procfs.py b/procfs/procfs.py index a78bac5376e3..de55dfc1aef4 100755 --- a/procfs/procfs.py +++ b/procfs/procfs.py @@ -44,7 +44,11 @@ def process_cmdline(pid_info): if pid_info["cmdline"]: return reduce(lambda a, b: a + " %s" % b, pid_info["cmdline"]).strip() - return pid_info["stat"]["comm"] + try: + """ If a pid disappears before we query it, return None """ + return pid_info["stat"]["comm"] + except: + return None class pidstat: @@ -374,9 +378,15 @@ class process: return hasattr(self, attr) def load_cmdline(self): - with open("/proc/%d/cmdline" % self.pid, mode='rb') as f: - cmdline = f.readline().decode(encoding='unicode_escape') - self.cmdline = cmdline.strip().split('\0')[:-1] + try: + with open("/proc/%d/cmdline" % self.pid) as f: + self.cmdline = f.readline().strip().split('\0')[:-1] + except FileNotFoundError: + """ This can happen when a pid disappears """ + self.cmdline = None + except UnicodeDecodeError: + """ TODO - this shouldn't happen, needs to be investigated """ + self.cmdline = None def load_threads(self): self.threads = pidstats("/proc/%d/task/" % self.pid) -- 2.31.1