From 96091c266e9ab09995ad027c069cb8ade771e6c7 Mon Sep 17 00:00:00 2001 From: Giampaolo Rodola Date: Tue, 26 Feb 2019 02:04:52 +0100 Subject: [PATCH] #1353: make process_iter() thread-safe --- HISTORY.rst | 1 + psutil/__init__.py | 16 +++++++++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/HISTORY.rst b/HISTORY.rst index 3addc0270..c553086b1 100644 --- a/HISTORY.rst +++ b/HISTORY.rst @@ -21,6 +21,7 @@ XXXX-XX-XX **Bug fixes** +- 1353_: process_iter() is now thread safe (it rarely raised TypeError). - 1394_: [Windows] Process name() and exe() may erronously return "Registry". QueryFullProcessImageNameW is now used instead of GetProcessImageFileNameW in order to prevent that. diff --git a/psutil/__init__.py b/psutil/__init__.py index 0aa13c755..70efc5af0 100644 --- a/psutil/__init__.py +++ b/psutil/__init__.py @@ -1503,6 +1503,7 @@ def pid_exists(pid): _pmap = {} +_lock = threading.Lock() def process_iter(attrs=None, ad_value=None): @@ -1530,21 +1531,26 @@ def add(pid): proc = Process(pid) if attrs is not None: proc.info = proc.as_dict(attrs=attrs, ad_value=ad_value) - _pmap[proc.pid] = proc + with _lock: + _pmap[proc.pid] = proc return proc def remove(pid): - _pmap.pop(pid, None) + with _lock: + _pmap.pop(pid, None) a = set(pids()) b = set(_pmap.keys()) new_pids = a - b gone_pids = b - a - for pid in gone_pids: remove(pid) - for pid, proc in sorted(list(_pmap.items()) + - list(dict.fromkeys(new_pids).items())): + + with _lock: + ls = sorted(list(_pmap.items()) + + list(dict.fromkeys(new_pids).items())) + + for pid, proc in ls: try: if proc is None: # new process yield add(pid)