From e3e892ea4304362a3db3678dcbaf729369ef18c3 Mon Sep 17 00:00:00 2001 From: "Brian C. Lane" Date: Wed, 12 Dec 2018 16:44:05 -0800 Subject: [PATCH] lorax-composer: Cancel running Anaconda process It ends up that this isn't as easy as you'd think. Anaconda sets up some signal handlers to handle cleanly exiting, but they are not being run when sent a TERM after package installation has started. I think DNF resets them causing it to get ignored. When the cancel is sent it can take several minutes for it to have an effect. In my testing it usually takes around 2 minutes for anaconda to notice and exit. This sends a TERM to the process and then waits for it to exit. When it returns it then removed any device-mapper devices that were setup for image installations, removes any hanging loop devices. It then kills off any process with pyanaconda. in the cmdline, and anaconda-bus.conf (because anaconda starts a bunch of helpers and if it doesn't shut down cleanly they remain running). Resolves: rhbz#1656691 --- src/pylorax/installer.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/pylorax/installer.py b/src/pylorax/installer.py index ec9e9d69..d1bd7785 100644 --- a/src/pylorax/installer.py +++ b/src/pylorax/installer.py @@ -21,9 +21,9 @@ import glob import json from math import ceil import os -import subprocess import shutil import socket +import subprocess import tempfile # Use the Lorax treebuilder branch for iso creation @@ -285,7 +285,10 @@ def novirt_cancel_check(cancel_funcs, proc): """ for f in cancel_funcs: if f(): + log.info("Terminating process %d", proc.pid) proc.terminate() + + # NOTE: Have to return and allow execReadlines to call proc.communicate() return True return False @@ -386,6 +389,7 @@ def novirt_install(opts, disk_img, disk_size, cancel_func=None): for line in execReadlines("anaconda", args, reset_lang=False, env_add={"ANACONDA_PRODUCTNAME": opts.project, "ANACONDA_PRODUCTVERSION": opts.releasever}, + reset_handlers=False, callback=lambda p: not novirt_cancel_check(cancel_funcs, p)): log.info(line) @@ -441,6 +445,12 @@ def novirt_install(opts, disk_img, disk_size, cancel_func=None): log.debug("Removing loop device for %s", disk_img) loop_detach("/dev/"+get_loop_name(disk_img)) + # When anaconda crashes or is canceled it leaves pyanaconda.* running + execWithRedirect("pkill", ["-f", "pyanaconda."]) + + # It can also leave dbus running + execWithRedirect("pkill", ["-f", "anaconda-bus.conf"]) + # qemu disk image is used by bare qcow2 images and by Vagrant if opts.image_type: log.info("Converting %s to %s", disk_img, opts.image_type)