Django

Code

Ticket #11193 (new)

Opened 10 months ago

Last modified 7 months ago

WSGI handler not properly handling lock

Reported by: Phillip Sitbon Assigned to: nobody
Milestone: Component: Core framework
Version: 1.0 Keywords: threads, locks
Cc: Triage Stage: Accepted
Has patch: 0 Needs documentation: 0
Needs tests: 0 Patch needs improvement: 0

Description

For this code in wsgi.py, seen in the latest release and the latest repository revision:

        if self._request_middleware is None:
            self.initLock.acquire()
            # Check that middleware is still uninitialised.
            if self._request_middleware is None:
                self.load_middleware()
            self.initLock.release()

I noticed the issue of thread safety in this handler came up in #10470, but this code is still not thread safe because it it can be put into a deadlock state. It will deadlock after any of the middleware loading fails- for example, when the module pointed to by DJANGO_SETTINGS_MODULE isn't found (which is how I came to notice it). After the failure, initLock is held and so this can deadlock on initLock.acquire().

The fix is very simple, and should absolutely be done anywhere locking is done:

        if self._request_middleware is None:
            self.initLock.acquire()
            try:
                # Check that middleware is still uninitialised.
                if self._request_middleware is None:
                    self.load_middleware()
            finally:
                self.initLock.release()

Of course using with keyword is an option as well. Also, I'm not sure how you would handle an indeterminate state between initialized and not initialized (e.g. some middleware loaded), but it might be a good idea to set self._request_middleware back to None before releasing the lock in case of an exception:

        if self._request_middleware is None:
            self.initLock.acquire()
            try:
                # Check that middleware is still uninitialised.
                if self._request_middleware is None:
                    self.load_middleware()
            except:
                # possibly unload whatever middleware didn't fail here
                self._request_middleware = None
                raise
            finally:
                self.initLock.release()

Attachments

Change History

05/24/09 12:40:15 changed by Phillip Sitbon

  • needs_better_patch changed.
  • needs_tests changed.
  • needs_docs changed.

Sorry, I forgot to point out a few things:

  • I'm using Django with the latest version of PyISAPIe
  • The code I submitted does indeed fix the deadlock issue for me.

05/29/09 14:09:55 changed by anonymous

  • version changed from SVN to 1.0.

08/08/09 15:39:12 changed by Alex

  • stage changed from Unreviewed to Accepted.

Add/Change #11193 (WSGI handler not properly handling lock)




Change Properties
Action