Skip to content

Commit

Permalink
3227: Wait for the keepalive period to end before stopping the accept…
Browse files Browse the repository at this point in the history
…ance of new requests. This will prevent potential disruptions in request handling.
  • Loading branch information
Michal Daniliszyn 1 committed Jul 8, 2024
1 parent 9802e21 commit 34ce875
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 1 deletion.
3 changes: 2 additions & 1 deletion gunicorn/workers/base_async.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def handle(self, listener, client, addr):
parser = http.RequestParser(self.cfg, client, addr)
try:
listener_name = listener.getsockname()
if not self.cfg.keepalive:
# do not allow keepalive if the worker is about to be restarted
if not self.cfg.keepalive or not self.alive:
req = next(parser)
self.handle_request(listener_name, req, client, addr)
else:
Expand Down
17 changes: 17 additions & 0 deletions gunicorn/workers/ggevent.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ def run(self):
self.notify()
gevent.sleep(1.0)

# Wait for pending keepalive connections to complete before stopping the acceptance of new requests
if self.cfg.keepalive:
self._wait_for_keepalive(servers)

try:
# Stop accepting requests
for server in servers:
Expand Down Expand Up @@ -117,6 +121,19 @@ def run(self):
except Exception:
pass

def _wait_for_keepalive(self, servers):
# Retrieve all active greenlets and repeatedly check, until the keepalive period ends,
# if any of those greenlets are still active. If none are active, exit the loop.

greenlets = {id(greenlet) for server in servers for greenlet in server.pool.greenlets}
ts = time.time()

while time.time() - ts <= self.cfg.keepalive:
if not greenlets.intersection({id(greenlet) for server in servers for greenlet in server.pool.greenlets}):
break
self.notify()
gevent.sleep(1.0)

def handle(self, listener, client, addr):
# Connected socket timeout defaults to socket.getdefaulttimeout().
# This forces to blocking mode.
Expand Down

0 comments on commit 34ce875

Please sign in to comment.