diff options
author | Giampaolo Rodola <g.rodola@gmail.com> | 2019-02-26 02:04:52 +0100 |
---|---|---|
committer | Giampaolo Rodola <g.rodola@gmail.com> | 2019-02-26 02:04:52 +0100 |
commit | 96091c266e9ab09995ad027c069cb8ade771e6c7 (patch) | |
tree | 4377845db66b7e1f3040913f07c9f48ed48cc47e | |
parent | d912cd584f354c2e660c3331ab63fd8e53c1ecf0 (diff) | |
download | psutil-96091c266e9ab09995ad027c069cb8ade771e6c7.tar.gz |
#1353: make process_iter() thread-safe
-rw-r--r-- | HISTORY.rst | 1 | ||||
-rw-r--r-- | psutil/__init__.py | 16 |
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) |