From 8176150850b2e34b2afe1dc107e184eb4c6cd668 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sun, 23 Mar 2014 23:34:14 +0100 Subject: [PATCH] Fixed #21202 -- Maintained atomicity when the server disconnects. Thanks intgr for the report. This commit doesn't include a test because I don't know how to emulate a database disconnection in a cross-database compatible way. Also simplified a 'backends' test that was constrained by this problem. --- django/db/transaction.py | 16 +++++++++++++--- tests/backends/tests.py | 7 ------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/django/db/transaction.py b/django/db/transaction.py index 159e2e2257..1f64a689bd 100644 --- a/django/db/transaction.py +++ b/django/db/transaction.py @@ -2,7 +2,7 @@ from functools import wraps from django.db import ( connections, DEFAULT_DB_ALIAS, - DatabaseError, ProgrammingError) + DatabaseError, Error, ProgrammingError) from django.utils.decorators import available_attrs @@ -224,7 +224,12 @@ class Atomic(object): try: connection.commit() except DatabaseError: - connection.rollback() + try: + connection.rollback() + except Error: + # Error during rollback means the connection was + # closed. Clean up in case the server dropped it. + connection.close() raise else: # This flag will be set to True again if there isn't a savepoint @@ -245,7 +250,12 @@ class Atomic(object): connection.needs_rollback = True else: # Roll back transaction - connection.rollback() + try: + connection.rollback() + except Error: + # Error during rollback means the connection was + # closed. Clean up in case the server dropped it. + connection.close() finally: # Outermost block exit when autocommit was enabled. diff --git a/tests/backends/tests.py b/tests/backends/tests.py index da851da166..79eaf84636 100644 --- a/tests/backends/tests.py +++ b/tests/backends/tests.py @@ -664,13 +664,6 @@ class BackendTestCase(TestCase): self.assertIsInstance(cursor, CursorWrapper) self.assertTrue(cursor.closed) - -class IsUsableTests(TransactionTestCase): - # Avoid using a regular TestCase because Django really dislikes closing - # the database connection inside a transaction at this point (#21202). - - available_apps = [] - # Unfortunately with sqlite3 the in-memory test database cannot be closed. @skipUnlessDBFeature('test_db_allows_multiple_connections') def test_is_usable_after_database_disconnects(self):