From 49618bea69625d9e2a8dd962f43dcf376f575425 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Thu, 25 Jul 2024 15:17:48 -0500 Subject: [PATCH 1/4] Close a temporary file acting as a fake socket This resolves a `ResourceWarning` caused by the test suite. --- tests/t.py | 3 +++ tests/test_http.py | 13 ++++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/t.py b/tests/t.py index 9b76e7deb..4551e9444 100644 --- a/tests/t.py +++ b/tests/t.py @@ -65,3 +65,6 @@ def send(self, data): def seek(self, offset, whence=0): self.tmp.seek(offset, whence) + + def close(self): + self.tmp.close() diff --git a/tests/test_http.py b/tests/test_http.py index f0ddc3bb2..658690d25 100644 --- a/tests/test_http.py +++ b/tests/test_http.py @@ -184,11 +184,14 @@ def test_socket_unreader_chunk(): fake_sock = t.FakeSocket(io.BytesIO(b'Lorem ipsum dolor')) sock_unreader = SocketUnreader(fake_sock, max_chunk=5) - assert sock_unreader.chunk() == b'Lorem' - assert sock_unreader.chunk() == b' ipsu' - assert sock_unreader.chunk() == b'm dol' - assert sock_unreader.chunk() == b'or' - assert sock_unreader.chunk() == b'' + try: + assert sock_unreader.chunk() == b'Lorem' + assert sock_unreader.chunk() == b' ipsu' + assert sock_unreader.chunk() == b'm dol' + assert sock_unreader.chunk() == b'or' + assert sock_unreader.chunk() == b'' + finally: + fake_sock.close() def test_length_reader_read(): From 62530ef41bea468ab91ca0cd63d9e40072fb5519 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Thu, 25 Jul 2024 15:22:42 -0500 Subject: [PATCH 2/4] Close open sockets when an exception is encountered --- gunicorn/instrument/statsd.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gunicorn/instrument/statsd.py b/gunicorn/instrument/statsd.py index 2c54b2e72..e993b46da 100644 --- a/gunicorn/instrument/statsd.py +++ b/gunicorn/instrument/statsd.py @@ -32,11 +32,14 @@ def __init__(self, cfg): else: address_family = socket.AF_INET + self.sock = None try: self.sock = socket.socket(address_family, socket.SOCK_DGRAM) self.sock.connect(cfg.statsd_host) except Exception: - self.sock = None + if self.sock is not None: + self.sock.close() + self.sock = None self.dogstatsd_tags = cfg.dogstatsd_tags From dc197ffbf91c8dc1de28388e02e01f371d849d66 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Thu, 25 Jul 2024 16:54:09 -0500 Subject: [PATCH 3/4] Close open files to prevent `ResourceWarning` in the test suite --- tests/test_reload.py | 32 +++++++++++++++++++------------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/tests/test_reload.py b/tests/test_reload.py index f5b182583..5ea0549f1 100644 --- a/tests/test_reload.py +++ b/tests/test_reload.py @@ -39,9 +39,12 @@ def test_reload_on_syntax_error(): log = mock.Mock() worker = MyWorker(age=0, ppid=0, sockets=[], app=app, timeout=0, cfg=cfg, log=log) - worker.init_process() - reloader.start.assert_called_with() - reloader.add_extra_file.assert_called_with('syntax_error_filename') + try: + worker.init_process() + reloader.start.assert_called_with() + reloader.add_extra_file.assert_called_with('syntax_error_filename') + finally: + worker.tmp.close() def test_start_reloader_after_load_wsgi(): @@ -56,13 +59,16 @@ def test_start_reloader_after_load_wsgi(): log = mock.Mock() worker = MyWorker(age=0, ppid=0, sockets=[], app=app, timeout=0, cfg=cfg, log=log) - worker.load_wsgi = mock.Mock() - mock_parent = mock.Mock() - mock_parent.attach_mock(worker.load_wsgi, 'load_wsgi') - mock_parent.attach_mock(reloader.start, 'reloader_start') - - worker.init_process() - mock_parent.assert_has_calls([ - mock.call.load_wsgi(), - mock.call.reloader_start(), - ]) + try: + worker.load_wsgi = mock.Mock() + mock_parent = mock.Mock() + mock_parent.attach_mock(worker.load_wsgi, 'load_wsgi') + mock_parent.attach_mock(reloader.start, 'reloader_start') + + worker.init_process() + mock_parent.assert_has_calls([ + mock.call.load_wsgi(), + mock.call.reloader_start(), + ]) + finally: + worker.tmp.close() From 7756175f54e3d5da52572ad4d0e984e69b246944 Mon Sep 17 00:00:00 2001 From: Kurt McKee Date: Thu, 25 Jul 2024 16:54:53 -0500 Subject: [PATCH 4/4] Escalate warnings to errors during testing This ensures that unclosed resources will be caught in CI --- pyproject.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index eaca1eac0..24fae1d6c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -76,6 +76,9 @@ main = "gunicorn.app.pasterapp:serve" norecursedirs = ["examples", "lib", "local", "src"] testpaths = ["tests/"] addopts = "--assert=plain --cov=gunicorn --cov-report=xml" +filterwarnings = [ + "error", +] [tool.setuptools] zip-safe = false