From f1eb6554d40a2ec4c71731dd1f880964230f2df0 Mon Sep 17 00:00:00 2001 From: Per Myren Date: Mon, 21 Oct 2024 10:08:36 +0200 Subject: [PATCH 1/3] Make sure SlicedFile is closed properly Fixes #556 --- src/whitenoise/responders.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/whitenoise/responders.py b/src/whitenoise/responders.py index 9501ea65..f85fe0e7 100644 --- a/src/whitenoise/responders.py +++ b/src/whitenoise/responders.py @@ -64,6 +64,7 @@ def read(self, size=-1): return data def close(self): + super().close() self.fileobj.close() From 6c561d7f169e7741a87a03b87aa32653251dafbd Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 28 Oct 2024 10:29:39 +0000 Subject: [PATCH 2/3] Add regression test --- tests/test_responders.py | 42 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 tests/test_responders.py diff --git a/tests/test_responders.py b/tests/test_responders.py new file mode 100644 index 00000000..8bc7b70e --- /dev/null +++ b/tests/test_responders.py @@ -0,0 +1,42 @@ +from __future__ import annotations + +from io import BytesIO + +from django.test import SimpleTestCase + +from whitenoise.responders import SlicedFile + + +class SlicedFileTests(SimpleTestCase): + def test_close_does_not_rerun_on_del(self): + """ + Regression test for the subtle close() behaviour of SlicedFile that + could lead to database connection errors. + + https://github.com/evansd/whitenoise/pull/612 + """ + file = BytesIO(b"1234567890") + sliced_file = SlicedFile(file, 1, 2) + + # Emulate how Django patches the file object's close() method to be + # response.close() and count the calls. + # https://github.com/django/django/blob/345a6652e6a15febbf4f68351dcea5dd674ea324/django/core/handlers/wsgi.py#L137-L140 + calls = 0 + + file_close = sliced_file.close + + def closer(): + nonlocal calls, file_close + calls += 1 + if file_close is not None: + file_close() + file_close = None + + sliced_file.close = closer + + sliced_file.close() + assert calls == 1 + + # Deleting the sliced file should not call close again. + del sliced_file + assert calls == 1 From 87200769844ee008c8d5d4792969811c24ffa0a0 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Mon, 28 Oct 2024 10:32:16 +0000 Subject: [PATCH 3/3] changelog note --- docs/changelog.rst | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/docs/changelog.rst b/docs/changelog.rst index b29ef4cf..8f065377 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -11,6 +11,10 @@ Unreleased * Support Python 3.13. +* Fix a bug introduced in version 6.0.0 where ``Range`` requests could lead to database connection errors in other requests. + + Thanks to Per Myren for the detailed investigation and fix in `PR #612 `__. + 6.7.0 (2024-06-19) ------------------