@@ -227,8 +227,6 @@ class BaseConfig(object):
# pid of the actual qemu process
self.qemu_environ = os.environ.copy()
self.qemuprocess = None
- # avoid cleanup twice
- self.cleaned = False
# Files to cleanup after run
self.cleanup_files = []
self.qmp = None
@@ -1658,6 +1656,7 @@ to your build configuration.
process = subprocess.Popen(cmds, stderr=subprocess.PIPE, pass_fds=pass_fds, env=self.qemu_environ)
self.qemuprocess = process
retcode = process.wait()
+ signal.alarm(0)
if retcode:
if retcode == -signal.SIGTERM:
logger.info("Qemu terminated by SIGTERM")
@@ -1672,22 +1671,11 @@ to your build configuration.
raise RunQemuError('Failed to run %s' % str(cmd))
def cleanup(self):
- if self.cleaned:
- return
-
# avoid dealing with SIGTERM when cleanup function is running
signal.signal(signal.SIGTERM, signal.SIG_IGN)
logger.info("Cleaning up")
- if self.qemuprocess:
- try:
- # give it some time to shut down, ignore return values and output
- self.qemuprocess.send_signal(signal.SIGTERM)
- self.qemuprocess.communicate(timeout=5)
- except subprocess.TimeoutExpired:
- self.qemuprocess.kill()
-
with open('/proc/uptime', 'r') as f:
uptime_seconds = f.readline().split()[0]
logger.info('Host uptime: %s\n' % uptime_seconds)
@@ -1718,8 +1706,6 @@ to your build configuration.
# Deliberately ignore the return code of 'tput smam'.
subprocess.call(["tput", "smam"])
- self.cleaned = True
-
def run_bitbake_env(self, mach=None, target=''):
if not mach:
@@ -1806,9 +1792,26 @@ def main():
def sigterm_handler(signum, frame):
logger.info("Received signal: %s" % (signum))
- config.cleanup()
+ # Stop qemu: process.wait() in start_qemu() will reap it. Add an
+ # alarm to send a SIGKILL if QEMU is still alive 5s later.
+ if config.qemuprocess is not None and config.qemuprocess.returncode is None:
+ try:
+ config.qemuprocess.terminate()
+ except OSError:
+ pass
+ signal.alarm(5)
signal.signal(signal.SIGTERM, sigterm_handler)
+ def sigalrm_handler(signum, frame):
+ # Force-kill qemu if it is still running after the grace period.
+ # No-op once qemu has been reaped (returncode set).
+ if config.qemuprocess is not None and config.qemuprocess.returncode is None:
+ try:
+ config.qemuprocess.kill()
+ except OSError:
+ pass
+ signal.signal(signal.SIGALRM, sigalrm_handler)
+
config.check_args()
config.read_qemuboot()
config.check_and_set()
If QEMU is still running while we are in the cleanup() function, this means we are currently handling a SIGTERM on runqemu. So we are still waiting on the process in start_qemu(). Trying to manipulate the process here might result in a deadlock. As an alternative, SIGTERM handler is now limited to transferring this SIGTERM to QEMU. Clean-up will happen in the normal path of the code. An additional SIGALRM timer makes sure to kill the QEMU process if it's still alive 5 seconds later. [YOCTO #16487] Signed-off-by: Mathieu Dubois-Briand <mathieu.dubois-briand@bootlin.com> --- scripts/runqemu | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-)