Skip to content

Process.__eq__ method causes problems if Process instances are stored in a list #211

Closed
@giampaolo

Description

From g.rodola on September 23, 2011 16:37:43

What steps will reproduce the problem?  
run the following script:

import psutil, time

while 1:
    procs = [p for p in psutil.process_iter()]
    for p in procs:
        try:
            p.get_memory_info()
        except psutil.Error:
            procs.remove(p)
    time.sleep(1)
    for p in procs:
        try:
            p.get_memory_info()
        except psutil.Error:
            procs.remove(p)
    time.sleep(1)

...then try to open and kill a new process within the time.sleep() window (1 second). 

What is the expected output?  


What do you see instead?  
The script will fail with:

Traceback (most recent call last):
  File "foo.py", line 43, in <module>
    procs.remove(p)
  File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 132, in __eq__
    h2 = (other.pid, other.create_time)
  File "/home/giampaolo/svn/psutil/psutil/__init__.py", line 254, in create_time
    return self._platform_impl.get_process_create_time()
  File "/home/giampaolo/svn/psutil/psutil/_pslinux.py", line 332, in wrapper
    raise NoSuchProcess(self.pid, self._process_name)
psutil.error.NoSuchProcess: process no longer exists (pid=5442) 

Please use labels and text to provide additional information.  
What happens is procs.remove(p) call iterates over the list to figure out what 
the right list element to remove is.
In doing so it calls Process.__eq__ method (which we overridden) against the 
list elements until the right element is found.

We originally overridden __eq__ to implement is_running() method.
The logic behind is_running() is to test for equality with another Process 
object based on pid and creation time.
That is correct but at the time we did that we didn't consider that __eq__ 
method can be used in other cirumstances such as [].remove() which for no 
reason should raise a psutil-related exception.

The proposed fix is to move that logic from __eq__ to is_running() and leave 
__eq__ alone.

Original issue: http://code.google.com/p/psutil/issues/detail?id=211

Metadata

Assignees

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions