From c0dc1f462bccf720ee8c8a2246b2d7263e7b8eaf Mon Sep 17 00:00:00 2001 From: Luke Jones Date: Sat, 16 Mar 2019 12:31:44 -0700 Subject: [PATCH 1/3] Move socket handling to an atexit handler --- bjoern.py | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/bjoern.py b/bjoern.py index 9d6fc4d6..f71d6358 100644 --- a/bjoern.py +++ b/bjoern.py @@ -1,3 +1,4 @@ +import atexit import os import socket import _bjoern @@ -38,6 +39,18 @@ def server_run(sock, wsgi_app): _bjoern.server_run(sock, wsgi_app) +def _close_server_socket(): + # Handler for cleaning up the server socket when the process terminates + global _default_instance + + if sock.family == socket.AF_UNIX: + filename = sock.getsockname() + if filename[0] != '\0': + os.unlink(sock.getsockname()) + sock.close() + _default_instance = None + + # Backwards compatibility API def listen(wsgi_app, host, port=None, reuse_port=False): """ @@ -73,12 +86,6 @@ def run(*args, **kwargs): "before calling bjoern.run() without arguments.") sock, wsgi_app = _default_instance - try: - server_run(sock, wsgi_app) - finally: - if sock.family == socket.AF_UNIX: - filename = sock.getsockname() - if filename[0] != '\0': - os.unlink(sock.getsockname()) - sock.close() - _default_instance = None + atexit.register(_close_server_socket) + + server_run(sock, wsgi_app) From 5f38de0d950aac91db7b39efbb01bb116eef83a7 Mon Sep 17 00:00:00 2001 From: Luke Pflibsen-Jones Date: Sat, 18 May 2019 14:15:27 -0700 Subject: [PATCH 2/3] Add missing sock declaration --- bjoern.py | 1 + 1 file changed, 1 insertion(+) diff --git a/bjoern.py b/bjoern.py index f71d6358..e236d65d 100644 --- a/bjoern.py +++ b/bjoern.py @@ -43,6 +43,7 @@ def _close_server_socket(): # Handler for cleaning up the server socket when the process terminates global _default_instance + sock = _default_instance[0] if sock.family == socket.AF_UNIX: filename = sock.getsockname() if filename[0] != '\0': From eb20e3ecfe538d112de41458ec0d2efa0b5f07e1 Mon Sep 17 00:00:00 2001 From: Luke Pflibsen-Jones Date: Sat, 18 May 2019 15:29:11 -0700 Subject: [PATCH 3/3] Handle socket closure in all cases - Handlers registered via `atexit` do not run when an exception is thrown, so a try/finally block has been added - Add some comments to clarify behavior so readers don't have to reference the dense documentation for `socket`. --- bjoern.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/bjoern.py b/bjoern.py index e236d65d..09b3a663 100644 --- a/bjoern.py +++ b/bjoern.py @@ -39,16 +39,21 @@ def server_run(sock, wsgi_app): _bjoern.server_run(sock, wsgi_app) -def _close_server_socket(): - # Handler for cleaning up the server socket when the process terminates +def _close_server_socket(sock): + # Clean up the given socket global _default_instance - - sock = _default_instance[0] + + # This fix is only needed on *NIX-like systems if sock.family == socket.AF_UNIX: filename = sock.getsockname() if filename[0] != '\0': os.unlink(sock.getsockname()) + + # Close the socket, but wait for current connections to close first. + # Calling sock.shutdown({reason}) would force it to close, but that may not + # be wiae in al circumstances. sock.close() + _default_instance = None @@ -66,6 +71,7 @@ def listen(wsgi_app, host, port=None, reuse_port=False): sock = bind_and_listen(host, port, reuse_port) _default_instance = (sock, wsgi_app) + def run(*args, **kwargs): """ run(*args, **kwargs): @@ -87,6 +93,10 @@ def run(*args, **kwargs): "before calling bjoern.run() without arguments.") sock, wsgi_app = _default_instance - atexit.register(_close_server_socket) + atexit.register(_close_server_socket, sock) - server_run(sock, wsgi_app) + try: + server_run(sock, wsgi_app) + finally: + _close_server_socket(sock) + atexit.unregister(sock) # Make sure we don't try to close the aocket twice