From f87acbea567f90c307a64ff80b8b03f777edf946 Mon Sep 17 00:00:00 2001 From: Pacman Ghost Date: Sat, 30 Mar 2024 21:07:47 +0700 Subject: [PATCH] Handle SIGTERM and shutdown gracefully. --- docker/run.sh | 6 +++++- vasl_templates/webapp/__init__.py | 9 ++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/docker/run.sh b/docker/run.sh index 05af6cd..ab1e0c5 100755 --- a/docker/run.sh +++ b/docker/run.sh @@ -6,6 +6,10 @@ export DISPLAY=:10.0 Xvfb :10 -ac 1>/tmp/xvfb.log 2>/tmp/xvfb.err & # run the webapp server -python3 /app/vasl_templates/webapp/run_server.py \ +# IMPORTANT! This script runs as PID 1, which is the only process that will receive signals, +# so we must replace it with the Python webserver process if it is to receive e.g. SIGTERM, +# which we must handle if "docker stop" and scaling down in Kubernetes is to work (otherwise +# things timeout and we get SIGKILL'ed). +exec python3 /app/vasl_templates/webapp/run_server.py \ --addr 0.0.0.0 \ --force-init-delay 30 diff --git a/vasl_templates/webapp/__init__.py b/vasl_templates/webapp/__init__.py index 88d17fd..e2f48ff 100644 --- a/vasl_templates/webapp/__init__.py +++ b/vasl_templates/webapp/__init__.py @@ -129,8 +129,8 @@ def _is_flask_child_process(): # --------------------------------------------------------------------- -def _on_sigint( signum, stack ): #pylint: disable=unused-argument - """Clean up after a SIGINT.""" +def _on_sig( signum, stack ): #pylint: disable=unused-argument + """Clean up after a SIGINT/SIGTERM.""" # FUDGE! Since we added gRPC test control, we want to shutdown properly and clean things up (e.g. temp files # created by the gRPC service), but the Flask reloader complicates what we have to do here horribly :-( @@ -258,7 +258,10 @@ import vasl_templates.webapp.downloads #pylint: disable=cyclic-import import vasl_templates.webapp.lfa #pylint: disable=cyclic-import # install our signal handler (must be done in the main thread) -signal.signal( signal.SIGINT, _on_sigint ) +signal.signal( signal.SIGINT, _on_sig ) +# NOTE: We must handle SIGTERM, so that "docker stop" and scaling down in Kubernetes +# work properly (otherwise it times out and we get SIGKILL'ed :-/). +signal.signal( signal.SIGTERM, _on_sig ) # register startup initialization app.before_request( _on_request )