From c726948f17c948a5307bbb7241f4b4e1f85f1d23 Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Wed, 3 Feb 2016 19:17:29 +0300 Subject: [PATCH] Handle SIGTERM to shut down gracefully Apparently, fuel-agent doesn't handle any signal received except for SIGINT which is automatically converted by python to KeyboardInterrupt() exception. fuel-agent is unable to send signal for spawned processes, just because utils.execute doesn't know PIDs of opened subprocessess. To mitigate that flaw, fuel-agent will use process group to distribute signals. Process groups are used to control the distribution of signals. A signal directed to a process group is delivered individually to all of the processes that are members of the group. That allows fuel-agent to send signals to subprocesses without knowing thier exact PIDs. Change-Id: Ie59c0425f031fa94e517b79df0a0fc3d0c3e7a07 Related-Bug: #1538645 --- fuel_agent/cmd/agent.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/fuel_agent/cmd/agent.py b/fuel_agent/cmd/agent.py index 554121cf..49f3de75 100644 --- a/fuel_agent/cmd/agent.py +++ b/fuel_agent/cmd/agent.py @@ -12,12 +12,15 @@ # License for the specific language governing permissions and limitations # under the License. +import os +import signal import sys from oslo_config import cfg import six import yaml +from fuel_agent import errors from fuel_agent import manager as manager from fuel_agent.openstack.common import log as logging from fuel_agent import version @@ -72,6 +75,16 @@ def print_err(line): sys.stderr.write('\n') +def handle_sigterm(signum, frame): + # NOTE(agordeev): Since group pid of spawned subprocess is unknown, + # fuel-agent needs to ignore SIGTERM sent by itself. + signal.signal(signal.SIGTERM, signal.SIG_IGN) + print_err('SIGTERM RECEIVED. Propagating it to subprocesses') + os.killpg(os.getpid(), signal.SIGTERM) + raise errors.UnexpectedProcessError( + 'Application was shut down gracefully') + + def handle_exception(exc): LOG = logging.getLogger(__name__) LOG.exception(exc) @@ -81,6 +94,10 @@ def handle_exception(exc): def main(actions=None): + # NOTE(agordeev): get its own process group by calling setpgrp. + # Process group is used to distribute signals to subprocesses. + os.setpgrp() + signal.signal(signal.SIGTERM, handle_sigterm) CONF(sys.argv[1:], project='fuel-agent', version=version.version_info.release_string())