#36318: Bad stack trace during rollback after bulk create
-------------------------------------+-------------------------------------
Reporter: Gordon Wrigley | Owner: (none)
Type: Bug | Status: new
Component: Database layer | Version: 4.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage: Accepted
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Comment (by Simon Charette):
I think the following might address the issue (for the usage of
`atomic(savepoint=False)` that `bulk_create` makes)
{{{#!diff
diff --git a/django/db/transaction.py b/django/db/transaction.py
index 0c2eee8e73..31363e686b 100644
--- a/django/db/transaction.py
+++ b/django/db/transaction.py
@@ -195,6 +195,7 @@ def __enter__(self):
# Reset state when entering an outermost atomic block.
connection.commit_on_exit = True
connection.needs_rollback = False
+ connection.rollback_exc = None
if not connection.get_autocommit():
# Pretend we're already in an atomic block to bypass the
code
# that disables autocommit to enter a transaction, and
make a
@@ -278,6 +279,9 @@ def __exit__(self, exc_type, exc_value, traceback):
# otherwise.
if sid is None:
connection.needs_rollback = True
+ # Avoid shadowing an already assigned rollback
exc.
+ if connection.rollback_exc is None:
+ connection.rollback_exc = exc_value
else:
try:
connection.savepoint_rollback(sid)
diff --git a/tests/transactions/tests.py b/tests/transactions/tests.py
index 9fe8c58593..329f2e74c2 100644
--- a/tests/transactions/tests.py
+++ b/tests/transactions/tests.py
@@ -504,6 +504,27 @@ def
test_mark_for_rollback_on_error_in_autocommit(self):
# … and further queries work nicely.
Reporter.objects.create()
+ def test_transaction_management_cause_leak(self):
+ with self.assertRaises(Exception), transaction.atomic():
+ raise Exception("First failure")
+
+ with (
+ self.assertRaises(transaction.TransactionManagementError) as
ctx,
+ transaction.atomic(),
+ ):
+ try:
+ with transaction.atomic(savepoint=False):
+ raise Exception("Second failure")
+ except Exception:
+ pass
+ try:
+ with transaction.atomic(savepoint=False):
+ raise Exception("Third failure")
+ except Exception:
+ pass
+ Reporter.objects.count()
+ self.assertEqual(str(ctx.exception.__cause__), "Second failure")
+
class NonAutocommitTests(TransactionTestCase):
available_apps = []
}}}
--
Ticket URL: <
https://code.djangoproject.com/ticket/36318#comment:6>