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.

Conflicts:

	bareon/cmd/agent.py

Change-Id: Ie59c0425f031fa94e517b79df0a0fc3d0c3e7a07
Related-Bug: #1538645
This commit is contained in:
Alexander Gordeev 2016-02-03 19:17:29 +03:00
parent 7a47142f7a
commit 58f03a5487

View File

@ -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 bareon import errors
from bareon.openstack.common import log as logging
from bareon.utils import utils
from bareon import version
@ -112,6 +115,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)
@ -121,6 +134,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='bareon',
version=version.version_info.release_string())