From 866ceac9d51e2a9f3434cce55aa478fd455e07f1 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Oct 2020 02:52:02 -0500 Subject: warn when the server stops listening for connections because its in overflow --- src/waitress/server.py | 22 +++++++++++++++++++++- tests/test_server.py | 14 ++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/waitress/server.py b/src/waitress/server.py index b053c69..639b9de 100644 --- a/src/waitress/server.py +++ b/src/waitress/server.py @@ -179,6 +179,7 @@ class BaseWSGIServer(wasyncore.dispatcher): next_channel_cleanup = 0 socketmod = socket # test shim asyncore = wasyncore # test shim + in_connection_overflow = False def __init__( self, @@ -296,7 +297,26 @@ class BaseWSGIServer(wasyncore.dispatcher): if now >= self.next_channel_cleanup: self.next_channel_cleanup = now + self.adj.cleanup_interval self.maintenance(now) - return self.accepting and len(self._map) < self.adj.connection_limit + + if ( + not self.in_connection_overflow + and len(self._map) >= self.adj.connection_limit + ): + self.in_connection_overflow = True + self.logger.warning( + 'server active connections reached the connection limit, ' + 'no longer accepting new connections' + ) + elif ( + self.in_connection_overflow + and len(self._map) < self.adj.connection_limit + ): + self.in_connection_overflow = False + self.logger.info( + 'server active connections dropped below the connection limit, ' + 'listening again' + ) + return self.accepting and not self.in_connection_overflow def writable(self): return False diff --git a/tests/test_server.py b/tests/test_server.py index 05f6b4e..508b382 100644 --- a/tests/test_server.py +++ b/tests/test_server.py @@ -185,6 +185,7 @@ class TestWSGIServer(unittest.TestCase): inst.adj = DummyAdj inst._map = {"a": 1, "b": 2} self.assertFalse(inst.readable()) + self.assertTrue(inst.in_connection_overflow) def test_readable_maplen_lt_connection_limit(self): inst = self._makeOneWithMap() @@ -192,6 +193,19 @@ class TestWSGIServer(unittest.TestCase): inst.adj = DummyAdj inst._map = {} self.assertTrue(inst.readable()) + self.assertFalse(inst.in_connection_overflow) + + def test_readable_maplen_toggles_connection_overflow(self): + inst = self._makeOneWithMap() + inst.accepting = True + inst.adj = DummyAdj + inst._map = {"a": 1, "b": 2} + self.assertFalse(inst.in_connection_overflow) + self.assertFalse(inst.readable()) + self.assertTrue(inst.in_connection_overflow) + inst._map = {} + self.assertTrue(inst.readable()) + self.assertFalse(inst.in_connection_overflow) def test_readable_maintenance_false(self): import time -- cgit v1.2.1 From 734014d34b1139b753457694f7b583c230e5bb14 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Oct 2020 02:55:11 -0500 Subject: add changelog --- CHANGES.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES.txt b/CHANGES.txt index f4d1acc..c62602e 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -3,6 +3,12 @@ - Drop Python 2.7 support +- The server now issues warning output when it there are enough open + connections (controlled by "connection_limit"), that it is no longer + accepting new connections. This situation was previously difficult to + diagnose. + See https://github.com/Pylons/waitress/pull/322 + 1.4.4 (2020-06-01) ------------------ -- cgit v1.2.1 From 78e98a75e527f90d8d8f2a25f5cb3f26527e75b4 Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Oct 2020 02:59:10 -0500 Subject: only change state while accepting --- src/waitress/server.py | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/src/waitress/server.py b/src/waitress/server.py index 639b9de..631780b 100644 --- a/src/waitress/server.py +++ b/src/waitress/server.py @@ -298,25 +298,27 @@ class BaseWSGIServer(wasyncore.dispatcher): self.next_channel_cleanup = now + self.adj.cleanup_interval self.maintenance(now) - if ( - not self.in_connection_overflow - and len(self._map) >= self.adj.connection_limit - ): - self.in_connection_overflow = True - self.logger.warning( - 'server active connections reached the connection limit, ' - 'no longer accepting new connections' - ) - elif ( - self.in_connection_overflow - and len(self._map) < self.adj.connection_limit - ): - self.in_connection_overflow = False - self.logger.info( - 'server active connections dropped below the connection limit, ' - 'listening again' - ) - return self.accepting and not self.in_connection_overflow + if self.accepting: + if ( + not self.in_connection_overflow + and len(self._map) >= self.adj.connection_limit + ): + self.in_connection_overflow = True + self.logger.warning( + 'total open connections reached the connection limit, ' + 'no longer accepting new connections' + ) + elif ( + self.in_connection_overflow + and len(self._map) < self.adj.connection_limit + ): + self.in_connection_overflow = False + self.logger.info( + 'total open connections dropped below the connection limit, ' + 'listening again' + ) + return not self.in_connection_overflow + return False def writable(self): return False -- cgit v1.2.1 From 25e093936d31dba3d5b042f842566729fb01668c Mon Sep 17 00:00:00 2001 From: Michael Merickel Date: Thu, 22 Oct 2020 09:27:11 -0500 Subject: blackify --- src/waitress/server.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/waitress/server.py b/src/waitress/server.py index 631780b..b37980e 100644 --- a/src/waitress/server.py +++ b/src/waitress/server.py @@ -305,8 +305,8 @@ class BaseWSGIServer(wasyncore.dispatcher): ): self.in_connection_overflow = True self.logger.warning( - 'total open connections reached the connection limit, ' - 'no longer accepting new connections' + "total open connections reached the connection limit, " + "no longer accepting new connections" ) elif ( self.in_connection_overflow @@ -314,8 +314,8 @@ class BaseWSGIServer(wasyncore.dispatcher): ): self.in_connection_overflow = False self.logger.info( - 'total open connections dropped below the connection limit, ' - 'listening again' + "total open connections dropped below the connection limit, " + "listening again" ) return not self.in_connection_overflow return False -- cgit v1.2.1