python-linux-procfs/SOURCES/procfs-Fix-removing-vanishe...

73 lines
2.3 KiB
Diff

From cf4c740974834b7d5c9dc7b12a69c5269b0d7a2d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
Date: Thu, 24 Jan 2019 21:55:16 +0100
Subject: [PATCH] procfs: Fix removing vanished processes in
pidstats.reload_threads()
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
If a process disappears while iterating the loop in
pidstats.reload_threads(), we get a RuntimeError as shown below. This
is because we cannot remove an entry from a dictionary while iterating the
dictionary.
Reproducer:
1. Add the following line to the beginning of pidstats.reload_threads():
import pdb; pdb.set_trace()
2. Start some process
3. Start the python interpreter and proceed as follows:
[~/git/python-linux-procfs]$ python3
Python 3.6.8 (default, Jan 3 2019, 16:11:14)
[GCC 8.2.1 20181215 (Red Hat 8.2.1-6)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import procfs
>>> ps = procfs.pidstats()
>>> ps.reload_threads()
> /home/olysonek/git/python-linux-procfs/procfs/procfs.py(462)reload_threads()
-> for pid in self.processes.keys():
(Pdb) next
> /home/olysonek/git/python-linux-procfs/procfs/procfs.py(463)reload_threads()
-> try:
At this point, terminate the process started in step 2. Return to the
python interpreter:
(Pdb) continue
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/home/olysonek/git/python-linux-procfs/procfs/procfs.py", line 463, in reload_threads
try:
RuntimeError: dictionary changed size during iteration
Signed-off-by: Ondřej Lysoněk <olysonek@redhat.com>
Signed-off-by: John Kacur <jkacur@redhat.com>
---
procfs/procfs.py | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/procfs/procfs.py b/procfs/procfs.py
index c6f65890d0e4..b0ce2514063d 100755
--- a/procfs/procfs.py
+++ b/procfs/procfs.py
@@ -459,12 +459,15 @@ class pidstats:
self.processes[pid] = process(pid, self.basedir)
def reload_threads(self):
+ to_remove = []
for pid in self.processes.keys():
try:
self.processes[pid].load_threads()
except OSError:
# process vanished, remove it
- del self.processes[pid]
+ to_remove.append(pid)
+ for pid in to_remove:
+ del self.processes[pid]
def find_by_name(self, name):
name = name[:15]
--
2.20.1