diff options
Diffstat (limited to 'django/middleware')
| -rw-r--r-- | django/middleware/transaction.py | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/django/middleware/transaction.py b/django/middleware/transaction.py index 96b1538d9d..4440f377a7 100644 --- a/django/middleware/transaction.py +++ b/django/middleware/transaction.py @@ -15,6 +15,10 @@ class TransactionMiddleware(object): def process_exception(self, request, exception): """Rolls back the database and leaves transaction management""" if transaction.is_dirty(): + # This rollback might fail because of network failure for example. + # If rollback isn't possible it is impossible to clean the + # connection's state. So leave the connection in dirty state and + # let request_finished signal deal with cleaning the connection. transaction.rollback() transaction.leave_transaction_management() @@ -22,6 +26,21 @@ class TransactionMiddleware(object): """Commits and leaves transaction management.""" if transaction.is_managed(): if transaction.is_dirty(): - transaction.commit() + # Note: it is possible that the commit fails. If the reason is + # closed connection or some similar reason, then there is + # little hope to proceed nicely. However, in some cases ( + # deferred foreign key checks for exampl) it is still possible + # to rollback(). + try: + transaction.commit() + except Exception: + # If the rollback fails, the transaction state will be + # messed up. It doesn't matter, the connection will be set + # to clean state after the request finishes. And, we can't + # clean the state here properly even if we wanted to, the + # connection is in transaction but we can't rollback... + transaction.rollback() + transaction.leave_transaction_management() + raise transaction.leave_transaction_management() return response |
