| | 92 | }}} |
| | 93 | |
| | 94 | == Lock handling == |
| | 95 | |
| | 96 | Locks should always be acquired in exception-safe manner, otherwise the system will deadlock when an exception is raised while a lock is held. |
| | 97 | |
| | 98 | Consider the following example (#11193): |
| | 99 | |
| | 100 | '''WRONG''' |
| | 101 | {{{ |
| | 102 | if self._request_middleware is None: |
| | 103 | self.initLock.acquire() |
| | 104 | # Check that middleware is still uninitialised. |
| | 105 | if self._request_middleware is None: |
| | 106 | self.load_middleware() |
| | 107 | self.initLock.release() |
| | 108 | }}} |
| | 109 | |
| | 110 | This will deadlock when `self.load_middleware()` raises an exception (the lock will never be released). |
| | 111 | |
| | 112 | '''RIGHT''' |
| | 113 | {{{ |
| | 114 | if self._request_middleware is None: |
| | 115 | self.initLock.acquire() |
| | 116 | try: |
| | 117 | # Check that middleware is still uninitialised. |
| | 118 | if self._request_middleware is None: |
| | 119 | self.load_middleware() |
| | 120 | except: |
| | 121 | # possibly unload whatever middleware didn't fail here |
| | 122 | # set the guard back to uninitialized state |
| | 123 | self._request_middleware = None |
| | 124 | raise |
| | 125 | finally: |
| | 126 | self.initLock.release() |