Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions ext_http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ def __init__(
class MyServer(socketserver.ThreadingMixIn, SecureHTTPServer):
"""A threaded SecureHTTPServer with basic error filtering."""

# Run connection threads as daemons so a lingering HTTP/1.1 keep-alive
# connection cannot block interpreter shutdown on Ctrl-C (see issue #1).
daemon_threads = True

def handle_error(self, request: socket | tuple[bytes, socket], client_address: Any) -> None: # noqa: ANN401
"""Disable tracebacks on connection close errors."""
_, exc_value, _ = sys.exc_info()
Expand Down Expand Up @@ -317,6 +321,8 @@ def main() -> int:
server.serve_forever()
except KeyboardInterrupt:
print("\nGoodbye")
finally:
server.server_close()
return 0


Expand Down
6 changes: 6 additions & 0 deletions tests/test_ext_http_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ def test_server_serves_range_request(secure_server):
assert body == b"56789ABCDEFGHIJ"


def test_server_uses_daemon_threads():
# Daemon connection threads keep lingering keep-alive connections from
# blocking interpreter shutdown on Ctrl-C (see issue #1).
assert MyServer.daemon_threads is True


def test_set_rate_limit_computes_block_size():
RateLimitWriter.set_rate_limit(128)
assert RateLimitWriter.block_size == int(1024 * 128 * RateLimitWriter.INTERVAL_LEN)