Exit immediately after cleanup when signal is received
Waiting for clients introduces the risk that we exceed some timeout (e.g. from systemd) and get killed instead.
This commit is contained in:
parent
46c39b28d6
commit
30c9c55358
@ -27,7 +27,6 @@ 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
|
||||||
@ -36,10 +35,22 @@ from radicale.log import logger
|
|||||||
|
|
||||||
def run():
|
def run():
|
||||||
"""Run Radicale as a standalone server."""
|
"""Run Radicale as a standalone server."""
|
||||||
|
|
||||||
|
# Raise SystemExit when signal arrives to run cleanup code
|
||||||
|
# (like destructors, try-finish etc.), otherwise the process exits
|
||||||
|
# without running any of them
|
||||||
|
def signal_handler(signal_number, stack_frame):
|
||||||
|
sys.exit(1)
|
||||||
|
signal.signal(signal.SIGTERM, signal_handler)
|
||||||
|
signal.signal(signal.SIGINT, signal_handler)
|
||||||
|
if os.name == "posix":
|
||||||
|
signal.signal(signal.SIGHUP, signal_handler)
|
||||||
|
|
||||||
log.setup()
|
log.setup()
|
||||||
|
|
||||||
# Get command-line arguments
|
# Get command-line arguments
|
||||||
parser = argparse.ArgumentParser(usage="radicale [OPTIONS]")
|
parser = argparse.ArgumentParser(
|
||||||
|
prog="radicale", usage="%(prog)s [OPTIONS]")
|
||||||
|
|
||||||
parser.add_argument("--version", action="version", version=VERSION)
|
parser.add_argument("--version", action="version", version=VERSION)
|
||||||
parser.add_argument("--verify-storage", action="store_true",
|
parser.add_argument("--verify-storage", action="store_true",
|
||||||
@ -137,17 +148,8 @@ 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()
|
|
||||||
|
|
||||||
# SIGTERM and SIGINT (aka KeyboardInterrupt) shutdown the server
|
|
||||||
def shutdown(signal_number, stack_frame):
|
|
||||||
shutdown_socket.close()
|
|
||||||
signal.signal(signal.SIGTERM, shutdown)
|
|
||||||
signal.signal(signal.SIGINT, shutdown)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
server.serve(configuration, shutdown_socket_out)
|
server.serve(configuration)
|
||||||
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)
|
||||||
|
@ -172,17 +172,14 @@ class TestBaseServerRequests(BaseTest):
|
|||||||
config_args.append(long_name)
|
config_args.append(long_name)
|
||||||
config_args.append(
|
config_args.append(
|
||||||
self.configuration.get_raw(section, option))
|
self.configuration.get_raw(section, option))
|
||||||
env = os.environ.copy()
|
|
||||||
env["PYTHONPATH"] = os.pathsep.join(sys.path)
|
|
||||||
p = subprocess.Popen(
|
p = subprocess.Popen(
|
||||||
[sys.executable, "-m", "radicale"] + config_args, env=env)
|
[sys.executable, "-m", "radicale"] + config_args,
|
||||||
|
env={**os.environ, "PYTHONPATH": os.pathsep.join(sys.path)})
|
||||||
try:
|
try:
|
||||||
self.get("/", is_alive_fn=lambda: p.poll() is None, check=302)
|
self.get("/", is_alive_fn=lambda: p.poll() is None, check=302)
|
||||||
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")
|
||||||
|
Loading…
Reference in New Issue
Block a user