Open curob opened 1 year ago
After looking at this some more, I do not think the proposed fix is enough as it fixes the memory leak but appears to cause another problem: _Process
instances cannot be killed via the calls to terminate()
that are not a result of the greenlets invoke method ending.
E.g. if another process calls simulator.kill(process)
or (while running) a process calls simulator.kill()
(in order to kill itself) then I do not think this will work anymore.
At this time, my code does not rely on killing running processes so this is not an issue for me (at the moment). If I find a full fix then I will post it here.
Problem
_Process
instances created via thesimulator.process()
method are never released and therefore they (and their containedgreenlet
instance are leaked). This can be a big issue for long running simulations that dynamically create processes. This is also means that any local variables in the process methods will also be leaked.Reproducer
Based on the above, I believe that the
greenlet
associated with the_Process
is never fully being cleaned up and therefore its reference to the owning_Process
(via theinvoke
method) is never being released and therefore the garbage collector cannot free the _Process.Cause
After examining the
_Process
code, it appears that the problem is the_Process.terminate()
method is never allowed to return. Instead, it explicitly callsself.main.switch
. This means that the contained greenlet's reference to the_Process.invoke
method will never complete (because the code always switches to another greenlet right before it completes) and therefore the greenlet infrastructure doesn't know that it can cleanup the thread because technically it never finishes.Proposed Solution:
In
_Process.terminate
change:to:
Greenlet will automatically switch to a dead thread's parent ("When a greenlet dies, in which case execution jumps to the parent greenlet." ref: https://greenlet.readthedocs.io/en/latest/switching.html).
Proof
I made the above change locally and reran my reproducer. Now when I examine the
vert
instance of a completed process it is reported as "dead". When I run the garbage collection steps in the reproducer, no instances of_Process
are found.