#35757 closed Uncategorized (invalid)
memcached.PyMemcacheCache reentrancy problem with ASGI-based runserver
Reported by: | Harm Verhagen | Owned by: | |
---|---|---|---|
Component: | Uncategorized | Version: | 5.1 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I found that using memcached.PyMemcacheCache
with runserver has reentrancy problems.
I implemented a json api in django, when issuing multiple request simultaneously from javascript, the requests sometimes crash.
I have urls that do something like this.
from django.core.cache import cache def example_url(request): cache.incr("some key", 1) # count requests return JsonResponse(data=data, status=201)
When issuing 5-10 requests simultaneously on a runserver, it often (not always) get this crash
File "..../views/api.py", line 2512, in example_url cache.incr("some key", 1) File "./venv/lib/python3.12/site-packages/django/core/cache/backends/memcached.py", line 110, in incr val = self._cache.incr(key, delta) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/hash.py", line 350, in incr return self._run_cmd("incr", key, False, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/hash.py", line 322, in _run_cmd return self._safely_run_func(client, func, default_val, *args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/hash.py", line 211, in _safely_run_func result = func(*args, **kwargs) ^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/base.py", line 827, in incr results = self._misc_cmd([cmd], b"incr", noreply) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/base.py", line 1291, in _misc_cmd buf, line = _reader(self.sock, buf) ^^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/base.py", line 1658, in _readline buf = _recv(sock, RECV_SIZE) ^^^^^^^^^^^^^^^^^^^^^^ File "./venv/lib/python3.12/site-packages/pymemcache/client/base.py", line 1750, in _recv return sock.recv(size) OSError: [Errno 9] Bad file descriptor
The following code looked a bit suspicious.
cache.backends.memcached.py:99 BaseMemcachedCache
def close(self, **kwargs): # Many clients don't clean up connections properly. self._cache.disconnect_all()
Doesn't this race? closing a all connections, might close a connection of a parallel request that was just opened but not yet finished.
Notes
I'm not putting a heavy load on runserver, its a simple javascript app, that happens to do 10 requests on a single page. Django should be able to handle that, also in a dev environment
Workaround
Adding the --noasgi
option seems to help.
./manage.py runserver --noasgi
Weird enough the (to me) more obvious, --nothreading
option does _not_ help. That crashes in the same way.
NB: this workaround breaks django channels, so if you have websockets in your app, then this "workaround" is not usable.
Version info
Django==5.1.1 pymemcache==4.0.0 python 3.12.6 channels==3.0.5 <--- related? channels-redis==3.4.1
Change History (11)
comment:1 by , 11 days ago
Description: | modified (diff) |
---|
comment:2 by , 11 days ago
Description: | modified (diff) |
---|
comment:3 by , 11 days ago
Description: | modified (diff) |
---|
comment:4 by , 11 days ago
Summary: | memcached.PyMemcacheCache reentrancy problem (OSError: [Errno 9] Bad file descriptor) → memcached.PyMemcacheCache reentrancy problem with ASGI-based runserver |
---|
comment:5 by , 11 days ago
Description: | modified (diff) |
---|
comment:6 by , 11 days ago
Description: | modified (diff) |
---|
comment:7 by , 11 days ago
Description: | modified (diff) |
---|
comment:8 by , 10 days ago
comment:9 by , 10 days ago
Description: | modified (diff) |
---|
comment:10 by , 10 days ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
This report seems better suited to be a support request. The best place to get answers to your issue is using any of the user support channels from this link.
Trac is for issues that are confirmed to be in Django. If, after debugging, you find out that this is indeed a bug in Django, please re-open with the specific details and please be sure to include a small Django project to reproduce or a failing test case.
Thank you!
comment:11 by , 9 days ago
Sarah Boyce wrote:
This report seems better suited to be a support request. The best place to get answers...
I actually intended to submit a bug report, not a support request or to get answers or help.
I'll try to cook up a small(er) test that demonstrates the problem.
Its not just a reentrancy problem. Wrapping the calls to
cache.incr()
in a global mutex (threading.Lock()
, just for testing purposes) does not seem to make any difference.