New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Killing greenlets across threads may leak greenlets and their stacks? #252
Comments
Similarly, there's no cleanup of the main greenlet from a thread unless some other thread calls one of those proper APIs. The main greenlet from a thread is left "dangling" in a suspended state until the user explicitly updates the state from a different thread. For example, this always reports a growth in greenlets: import gc
import threading
import greenlet
def count_objects(kind=list):
# pylint:disable=unidiomatic-typecheck
# Collect the garbage.
for _ in range(3):
gc.collect()
gc.collect()
return sum(
1
for x in gc.get_objects()
if type(x) is kind
)
def target():
print(greenlet.getcurrent())
print("Begin glets", count_objects(greenlet.greenlet))
t = threading.Thread(target=target)
t.start()
t.join()
del t
print("End glets", count_objects(greenlet.greenlet)) $ python foo.py
Begin glets 1
End glets 2 Inserting a call to |
With #251 fixed (when you call |
Sigh. I have a branch that partly fixes this (I can solve the list leak), but there are still cases where it's very difficult to fix completely. If you start a greenlet in a background thread, provide it to another thread, don't let the background greenlet complete, and don't have the background thread call a greenlet API before finishing and after the last reference to the background greenlet has been deleted, then at least the main greenlet from the background thread leaks (or more, depending on the See greenlet/src/greenlet/tests/test_leaks.py Line 89 in 5d76ab4
False for the parameter) by greenlet/src/greenlet/tests/test_leaks.py Line 170 in 5d76ab4
Currently, the frames from the secondary background greenlet also leak. My branch can at least fix that much. It may not be possible to fix the whole thing though, because a leaking reference is in the C stack and inaccessible. I still have a few things to try, though. |
We're now using Py_AddPendingCall to clean up some thread-local things that don't clean themselves up. I'm still working to be sure we break cycles.
I haven't tested this on other platforms or with a more complex app like gevent yet though.
We're now using Py_AddPendingCall to clean up some thread-local things that don't clean themselves up. I'm still working to be sure we break cycles.
I haven't tested this on other platforms or with a more complex app like gevent yet though.
If proper APIs aren't called in the target thread. See #245 (comment)
The analysis there may not actually be correct. There is a reference cycle, but the greenlets contained in the
deleteme
list should be subject to garbage collection (eventually) because none of them should be active after the thread dies.The text was updated successfully, but these errors were encountered: