Kaydet (Commit) 81761508 authored tarafından Aymeric Augustin's avatar Aymeric Augustin

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.
üst 25860096
...@@ -2,7 +2,7 @@ from functools import wraps ...@@ -2,7 +2,7 @@ from functools import wraps
from django.db import ( from django.db import (
connections, DEFAULT_DB_ALIAS, connections, DEFAULT_DB_ALIAS,
DatabaseError, ProgrammingError) DatabaseError, Error, ProgrammingError)
from django.utils.decorators import available_attrs from django.utils.decorators import available_attrs
...@@ -224,7 +224,12 @@ class Atomic(object): ...@@ -224,7 +224,12 @@ class Atomic(object):
try: try:
connection.commit() connection.commit()
except DatabaseError: except DatabaseError:
try:
connection.rollback() connection.rollback()
except Error:
# Error during rollback means the connection was
# closed. Clean up in case the server dropped it.
connection.close()
raise raise
else: else:
# This flag will be set to True again if there isn't a savepoint # This flag will be set to True again if there isn't a savepoint
...@@ -245,7 +250,12 @@ class Atomic(object): ...@@ -245,7 +250,12 @@ class Atomic(object):
connection.needs_rollback = True connection.needs_rollback = True
else: else:
# Roll back transaction # Roll back transaction
try:
connection.rollback() connection.rollback()
except Error:
# Error during rollback means the connection was
# closed. Clean up in case the server dropped it.
connection.close()
finally: finally:
# Outermost block exit when autocommit was enabled. # Outermost block exit when autocommit was enabled.
......
...@@ -664,13 +664,6 @@ class BackendTestCase(TestCase): ...@@ -664,13 +664,6 @@ class BackendTestCase(TestCase):
self.assertIsInstance(cursor, CursorWrapper) self.assertIsInstance(cursor, CursorWrapper)
self.assertTrue(cursor.closed) 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. # Unfortunately with sqlite3 the in-memory test database cannot be closed.
@skipUnlessDBFeature('test_db_allows_multiple_connections') @skipUnlessDBFeature('test_db_allows_multiple_connections')
def test_is_usable_after_database_disconnects(self): def test_is_usable_after_database_disconnects(self):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment