summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/waitress/server.py22
-rw-r--r--tests/test_server.py14
2 files changed, 35 insertions, 1 deletions
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