Django

Code

Ticket #8311 (closed: fixed)

Opened 4 months ago

Last modified 3 months ago

Changeset 8342 makes test suite hang if memcached is not running

Reported by: jcrocholl Assigned to: nobody
Milestone: 1.0 Component: django.contrib.sessions
Version: SVN Keywords:
Cc: johann@browsershots.org, trevor Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

Up to changeset [8341] my project works okay. After upgrading to [8342], manage.py test hangs at 100% CPU, with the following Traceback after Ctrl+C:

............^CTraceback (most recent call last):
  ... (beginning of doctest stack trace omitted) ...
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/unittest.py", line 428, in __call__
    return self.run(*args, **kwds)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/unittest.py", line 424, in run
    test(result)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/unittest.py", line 281, in __call__
    return self.run(*args, **kwds)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/unittest.py", line 260, in run
    testMethod()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/test/_doctest.py", line 2174, in runTest
    failures, tries = runner.run(
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/test/_doctest.py", line 1403, in run
    return self.__run(test, compileflags, out)
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/test/_doctest.py", line 1267, in __run
    compileflags, 1) in test.globs
  File "<doctest django.contrib.sessions.tests[56]>", line 1, in ?
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/contrib/sessions/backends/base.py", line 233, in flush
    self.create()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/contrib/sessions/backends/cache.py", line 20, in create
    self.session_key = self._get_new_session_key()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/contrib/sessions/backends/base.py", line 137, in _get_new_session_key
    session_key = md5_constructor("%s%s%s%s"
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/random.py", line 188, in randrange
    return int(istart + self._randbelow(width))
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/random.py", line 235, in _randbelow
    r = getrandbits(k)
KeyboardInterrupt

The hanging test seems to be in django.contrib.sessions.tests line 56 or so.

Attachments

Change History

08/14/08 12:48:50 changed by Alex

  • status changed from new to closed.
  • needs_better_patch changed.
  • resolution set to worksforme.
  • needs_tests changed.
  • needs_docs changed.

I'm not seeing this on r8350, try svn upping(and clearing out all the .pyc files in django) and if it's still an issue reopen.

08/14/08 13:14:41 changed by mtredinnick

This is a real bug, but, as per this thread on django-users, it seems to be very Mac specific in very specific circumstances. In any case, let's call #8314 the tracking ticket for this one and I'll keep that updated with fixes, etc.

(Triagers, close similar tickets as dupes of #8314.)

08/14/08 15:19:50 changed by jcrocholl

  • status changed from closed to reopened.
  • resolution deleted.

This problem is different from the crash in the django-users thread, and also different from #8314.

This problem persists after upgrading to [8351]. I have deleted all .pyc files and wiped the installation folder.

This problem is not a Python crash or a stack overflow (but I've experienced both of these too).

Python just keeps running at 100% CPU forever. If I kill it with Ctrl+C, the stack trace always looks like the one I posted originally, except for the exact position of the KeyboardInterrupt. The infinite loop seems to start here:

  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/contrib/sessions/backends/base.py", line 236, in flush
    self.create()
  File "/opt/local/Library/Frameworks/Python.framework/Versions/2.4/lib/python2.4/site-packages/django/contrib/sessions/backends/cache.py", line 22, in create
    self.save(must_create=True)

I'm working on Mac OS X 10.5.4, with the following packages from MacPorts:

memcached @1.2.5_2 (active)
postgresql83 @8.3.1_0 (active)
postgresql83-server @8.3.1_0 (active)
py-memcached @1.40_0 (active)
py-psycopg @1.1.21_1+postgresql83 (active)
py-psycopg2 @2.0.5.1_0 (active)
python24 @2.4.5_0+darwin_9 (active)

(follow-up: ↓ 6 ) 08/14/08 15:33:15 changed by mtredinnick

  • stage changed from Unreviewed to Accepted.
  • milestone set to 1.0 beta.

@jcrocholl: apologies for not appreciating the difference here.

Would you be able to run the tests with --verbosity=2 and work out which test it is hanging on? That should help narrow down where the problem might be.

Also, is there anything special in the settings file you are using, such as setting a particular cache backend? I can't repeat the issue here, but I might not be exercising the right piece of code (plus I'm not on a Mac). So if you can supply that info, I'll try to do it just with eyeballs.

08/15/08 02:16:48 changed by Alex

  • milestone changed from 1.0 beta to 1.0.

(in reply to: ↑ 4 ) 08/15/08 02:28:21 changed by jcrocholl

  • summary changed from Changeset 8342 makes test suite hang to Changeset 8342 makes test suite hang when using memcached.

This is the last output of /opt/local/bin/python2.4 manage.py test --verbosity=2 before Python hangs at 100% CPU:

Checking absolute path for fixtures...
Trying absolute path for xml fixture 'initial_data'...
No xml fixture 'initial_data' in absolute path.
Trying absolute path for json fixture 'initial_data'...
No json fixture 'initial_data' in absolute path.
Resetting sequences
Installed 120 object(s) from 4 fixture(s)
test_confirm_complete (django.contrib.auth.tests.views.PasswordResetTest) ... ok
test_confirm_different_passwords (django.contrib.auth.tests.views.PasswordResetTest) ... ok
test_confirm_invalid (django.contrib.auth.tests.views.PasswordResetTest) ... ok
test_confirm_invalid_post (django.contrib.auth.tests.views.PasswordResetTest) ... ok
test_confirm_valid (django.contrib.auth.tests.views.PasswordResetTest) ... ok
Email is sent if a valid email address is provided for password reset ... ok
Error is raised if the provided email address isn't currently registered ... ok
Doctest: django.contrib.auth.tests.__test__.BASIC_TESTS ... ok
Doctest: django.contrib.auth.tests.__test__.FORM_TESTS ... ok
Doctest: django.contrib.auth.tests.__test__.TOKEN_GENERATOR_TESTS ... ok
Doctest: django.contrib.sites.tests ... ok
Doctest: django.contrib.contenttypes.tests ... ok
Doctest: django.contrib.sessions.tests ... 

I already pointed out that this was the hanging test, see the bottom of my first post.

The problem goes away if I don't use memcached (by commenting out the following line in settings.py).

CACHE_BACKEND = 'memcached://127.0.0.1:11211/'

(follow-up: ↓ 8 ) 08/15/08 02:31:55 changed by Alex

Does it occur if you use a different cache backend?

(in reply to: ↑ 7 ) 08/15/08 02:37:56 changed by jcrocholl

Replying to Alex:

Does it occur if you use a different cache backend?

The problem only occurs with memcached. The test suite works okay with any of the following alternatives:

  • No CACHE_BACKEND specified
  • CACHE_BACKEND = 'locmem:///'
  • CACHE_BACKEND = 'file://cache'

My guess is that memcached fails to delete session keys from the cache.

08/15/08 09:37:35 changed by jcrocholl

  • cc set to johann@browsershots.org.
  • summary changed from Changeset 8342 makes test suite hang when using memcached to Changeset 8342 makes test suite hang if memcached is not running.

Okay, here's the simple solution: The memcached daemon should be running when manage.py test is started.

The problem was that memcached was not running on my system. The new session cache code will try to create a new session, but the cache backend will return False when it attempts to save the session to the cache. Then the session code assumes that this session key already exists, and raises CreateError. Then it generates a new session key to try again, and again...

The better solution would be to raise an exception if memcached is selected but unavailable, rather than the current infinite loop. Maybe I should write a patch to limit the number of attempts to 10 or 100? Here's the current implementation:

browser://django/trunk/django/contrib/sessions/backends/cache.py (line 18)

def create(self):
    while True:
        self.session_key = self._get_new_session_key()
        try:
            self.save(must_create=True)
        except CreateError:
            continue
        self.modified = True
        return

08/15/08 09:49:10 changed by mtredinnick

  • stage changed from Accepted to Design decision needed.

Need to think about what to do with caching when the cache isn't available. Depending on that, it will decide what to do here. Nice to hear it isn't a fundamental problem with the code, however. Thanks for chasing that down to the end. We'll do something about the error handling, but I'm not sure what the right solution is yet.

08/15/08 09:59:11 changed by mtredinnick

(In [8381]) Made a few small tweaks to reduce persistent storage accesses in the session backend. Refs #8311, although doesn't fix the problem there.

08/22/08 19:40:33 changed by jacob

  • stage changed from Design decision needed to Accepted.

08/24/08 15:12:00 changed by trevor

  • cc changed from johann@browsershots.org to johann@browsershots.org, trevor.

08/27/08 03:58:53 changed by mtredinnick

  • status changed from reopened to closed.
  • resolution set to fixed.

(In [8620]) Fixed #8311 -- Avoid an infinite loop with session key generation when using the cache backend and memcached goes away (or is not running).


Add/Change #8311 (Changeset 8342 makes test suite hang if memcached is not running)




Change Properties
Action