Skip to content

Commit

Permalink
revert #1667 process_iter() new_only param
Browse files Browse the repository at this point in the history
On a second thought I realized that process_iter() uses a global
variable, so it's not thread safe.
That means that if the are 2 threads using it, the first thread one calling the function (+ consume the iterator), will "steal" the processes of the second thread.

psutil.cpu_percent() has the same problem. That means we have a problem
can't solve with the current API and requires a lot of thinking on how
to solve it as it's not obvious.
  • Loading branch information
giampaolo committed Feb 18, 2020
1 parent 793148f commit c9fc4fd
Show file tree
Hide file tree
Showing 4 changed files with 2 additions and 34 deletions.
1 change: 0 additions & 1 deletion HISTORY.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ XXXX-XX-XX
directory for additional data. (patch by Javad Karabi)
- 1652_: [Windows] dropped support for Windows XP and Windows Server 2003.
Minimum supported Windows version now is Windows Vista.
- 1667_: added process_iter(new_only=True) parameter.
- 1671_: [FreeBSD] add CI testing/service for FreeBSD (Cirrus CI).
- 1677_: [Windows] process exe() will succeed for all process PIDs (instead of
raising AccessDenied).
Expand Down
13 changes: 1 addition & 12 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -857,7 +857,7 @@ Functions
.. versionchanged::
5.6.0 PIDs are returned in sorted order

.. function:: process_iter(attrs=None, ad_value=None, new_only=False)
.. function:: process_iter(attrs=None, ad_value=None)

Return an iterator yielding a :class:`Process` class instance for all running
processes on the local machine.
Expand All @@ -873,8 +873,6 @@ Functions
``info`` attribute attached to the returned :class:`Process` instances.
If *attrs* is an empty list it will retrieve all process info (slow).

If *new_only* is true this function will take into consideration only
new PIDs which appeared since the last time it was was called.
Sorting order in which processes are returned is based on their PID.

Example::
Expand All @@ -898,18 +896,9 @@ Functions
3: {'name': 'ksoftirqd/0', 'username': 'root'},
...}

Get only new processes since last call::

>>> for proc in psutil.process_iter(['pid', 'name'], new_only=True):
... print(proc.info)
...

.. versionchanged::
5.3.0 added "attrs" and "ad_value" parameters.

.. versionchanged::
5.7.0 added "new_only" parameter.

.. function:: pid_exists(pid)

Check whether the given PID exists in the current process list. This is
Expand Down
6 changes: 1 addition & 5 deletions psutil/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1407,7 +1407,7 @@ def pid_exists(pid):
_lock = threading.Lock()


def process_iter(attrs=None, ad_value=None, new_only=False):
def process_iter(attrs=None, ad_value=None):
"""Return a generator yielding a Process instance for all
running processes.
Expand All @@ -1428,8 +1428,6 @@ def process_iter(attrs=None, ad_value=None, new_only=False):
If *attrs* is an empty list it will retrieve all process info
(slow).
If *new_only* is true this function will take into consideration
only new PIDs which appeared since the last time it was called.
"""
def add(pid):
proc = Process(pid)
Expand All @@ -1452,8 +1450,6 @@ def remove(pid):

with _lock:
ls = list(dict.fromkeys(new_pids).items())
if not new_only:
ls += list(_pmap.items())
ls.sort()

for pid, proc in ls:
Expand Down
16 changes: 0 additions & 16 deletions psutil/tests/test_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,22 +105,6 @@ def test_prcess_iter_w_attrs(self):
self.assertGreaterEqual(p.info['pid'], 0)
assert m.called

def test_process_iter_new_only(self):
ls1 = list(psutil.process_iter(attrs=['pid']))
ls2 = list(psutil.process_iter(attrs=['pid'], new_only=True))
self.assertGreater(len(ls1), len(ls2))
# assume no more than 3 new processes were created in the meantime
self.assertIn(len(ls2), [0, 1, 2, 3, 4, 5])

sproc = get_test_subprocess()
ls = list(psutil.process_iter(attrs=['pid'], new_only=True))
self.assertIn(len(ls2), [0, 1, 2, 3, 4, 5])
for p in ls:
if p.pid == sproc.pid:
break
else:
self.fail("subprocess not found")

@unittest.skipIf(PYPY and WINDOWS,
"get_test_subprocess() unreliable on PYPY + WINDOWS")
def test_wait_procs(self):
Expand Down

0 comments on commit c9fc4fd

Please sign in to comment.