-
Notifications
You must be signed in to change notification settings - Fork 218
asgiref.local.Local
creates reference cycles that require garbage collection to be freed when executed in a sync context
#487
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
Comments
Which version of |
@andrewgodwin I noticed this in |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
@patrys Thanks for the report. I've finally got some space in the upcoming window to sit down with
The key bit in the flow is the first one there right? (Or not?) — "Disable garbage collection". Python's GC can be a little slow shall we say, but it does work in the end no? Just trying to understand to effect here. (Independently of what to conclude) @SebCorbin: Please do open a fresh one. There are a few related issues around 3.8 that need investigation. I'd rather have a duplicate than it slip through the gaps. (If you could minimise your example, somehow, that might be handy!) Thanks. |
@carltongibson The |
@patrys Makes sense. Thanks.
I see that here: saleor/saleor#17594 Would you like to open a PR here to upstream that? |
@carltongibson, I will handle it. |
We use Django, which uses
asgiref.local.Local
for its connection management. While debugging memory buildup, I've noticed that thread-criticalLocal
s create reference cycles when used in a sync context.Steps to reproduce
DEBUG_LEAK
Local
variable in synchronous contextLocal
Explanation
When Django tries to reference a database connection that is not yet established, it executes something like this (paraphrasing):
Now, internally,
asgiref
's Local does this:Now, putting everything together:
getattr
on theLocal
object_lock_storage
context manager is enteredasyncio.get_running_loop()
, which raises aRuntimeError
self._storage
(at this point, we're still in the exception handler inside the context manager)Local
executesgetattr
onstorage
, which raises anAttributeError
AttributeError
is propagated back to the context manager and since it's in the exception handler, it's linked to the previousRuntimeError
(Python assumes theAttributeError
was raised while attempting to handle theRuntimeError
)Potential solution
Changing the
_lock_storage
implementation to the following fixes the issue:The text was updated successfully, but these errors were encountered: