Internal server: Shutdown server via socket

This commit is contained in:
Unrud 2020-10-04 14:11:43 +02:00
parent c8b31637ef
commit 0e8949ff71
3 changed files with 23 additions and 6 deletions

View File

@ -27,6 +27,7 @@ import argparse
import contextlib import contextlib
import os import os
import signal import signal
import socket
import sys import sys
from radicale import VERSION, config, log, server, storage from radicale import VERSION, config, log, server, storage
@ -35,16 +36,20 @@ from radicale.log import logger
def run(): def run():
"""Run Radicale as a standalone server.""" """Run Radicale as a standalone server."""
exit_signal_numbers = [signal.SIGTERM, signal.SIGINT]
if os.name == "posix":
exit_signal_numbers.append(signal.SIGHUP)
exit_signal_numbers.append(signal.SIGQUIT)
elif os.name == "nt":
exit_signal_numbers.append(signal.SIGBREAK)
# Raise SystemExit when signal arrives to run cleanup code # Raise SystemExit when signal arrives to run cleanup code
# (like destructors, try-finish etc.), otherwise the process exits # (like destructors, try-finish etc.), otherwise the process exits
# without running any of them # without running any of them
def signal_handler(signal_number, stack_frame): def exit_signal_handler(signal_number, stack_frame):
sys.exit(1) sys.exit(1)
signal.signal(signal.SIGTERM, signal_handler) for signal_number in exit_signal_numbers:
signal.signal(signal.SIGINT, signal_handler) signal.signal(signal_number, exit_signal_handler)
if os.name == "posix":
signal.signal(signal.SIGHUP, signal_handler)
log.setup() log.setup()
@ -148,8 +153,17 @@ def run():
sys.exit(1) sys.exit(1)
return return
# Create a socket pair to notify the server of program shutdown
shutdown_socket, shutdown_socket_out = socket.socketpair()
# Shutdown server when signal arrives
def shutdown_signal_handler(signal_number, stack_frame):
shutdown_socket.close()
for signal_number in exit_signal_numbers:
signal.signal(signal_number, shutdown_signal_handler)
try: try:
server.serve(configuration) server.serve(configuration, shutdown_socket_out)
except Exception as e: except Exception as e:
logger.fatal("An exception occurred during server startup: %s", e, logger.fatal("An exception occurred during server startup: %s", e,
exc_info=True) exc_info=True)

View File

@ -61,6 +61,7 @@ class ParallelHTTPServer(socketserver.ThreadingMixIn,
# We wait for child threads ourself # We wait for child threads ourself
block_on_close = False block_on_close = False
daemon_threads = True
def __init__(self, configuration, family, address, RequestHandlerClass): def __init__(self, configuration, family, address, RequestHandlerClass):
self.configuration = configuration self.configuration = configuration

View File

@ -180,6 +180,8 @@ class TestBaseServerRequests(BaseTest):
finally: finally:
p.terminate() p.terminate()
p.wait() p.wait()
if os.name == "posix":
assert p.returncode == 0
def test_wsgi_server(self): def test_wsgi_server(self):
config_path = os.path.join(self.colpath, "config") config_path = os.path.join(self.colpath, "config")