summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGiampaolo Rodola <g.rodola@gmail.com>2019-02-26 02:04:52 +0100
committerGiampaolo Rodola <g.rodola@gmail.com>2019-02-26 02:04:52 +0100
commit96091c266e9ab09995ad027c069cb8ade771e6c7 (patch)
tree4377845db66b7e1f3040913f07c9f48ed48cc47e
parentd912cd584f354c2e660c3331ab63fd8e53c1ecf0 (diff)
downloadpsutil-96091c266e9ab09995ad027c069cb8ade771e6c7.tar.gz
#1353: make process_iter() thread-safe
-rw-r--r--HISTORY.rst1
-rw-r--r--psutil/__init__.py16
2 files changed, 12 insertions, 5 deletions
diff --git a/HISTORY.rst b/HISTORY.rst
index 3addc027..c553086b 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 0aa13c75..70efc5af 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 process_iter(attrs=None, ad_value=None):
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)