﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
35757	memcached.PyMemcacheCache reentrancy problem  with ASGI-based runserver	Harm Verhagen		"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
}}}




"	Bug	closed	Core (Cache system)	5.1	Normal	needsinfo	asgi, async		Unreviewed	0	0	0	0	0	0
