qemurunner.py: refactor searching for QEMU PID

Ask QEMU to store the QEMU process PID in a file, this way we don't
have to parse running processes and analyze descendents.
This is done via QEMU command line argument "-pidfile".

[YOCTO #12001]

(From OE-Core rev: 67612dcd2a8a1aa1d683dddb0bd2f592886ff020)

(From OE-Core rev: 9fe7aa1824666d3f7ceb085bef59026e245cb752)

Signed-off-by: Juro Bystricky <juro.bystricky@intel.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
This commit is contained in:
Juro Bystricky 2017-09-06 17:33:58 -07:00 committed by Richard Purdie
parent 50750e1572
commit 8100e7c44e
1 changed files with 136 additions and 167 deletions

View File

@ -53,6 +53,7 @@ class QemuRunner:
self.use_kvm = use_kvm
self.runqemutime = 120
self.qemu_pidfile = 'pidfile_'+str(os.getpid())
self.host_dumper = HostDumper(dump_host_cmds, dump_dir)
self.logger = logging.getLogger("BitBake.QemuRunner")
@ -142,7 +143,11 @@ class QemuRunner:
if extra_bootparams:
bootparams = bootparams + ' ' + extra_bootparams
self.qemuparams = 'bootparams="{0}" qemuparams="-serial tcp:127.0.0.1:{1}"'.format(bootparams, threadport)
# Ask QEMU to store the QEMU process PID in file, this way we don't have to parse running processes
# and analyze descendents in order to determine it.
if os.path.exists(self.qemu_pidfile):
os.remove(self.qemu_pidfile)
self.qemuparams = 'bootparams="{0}" qemuparams="-serial tcp:127.0.0.1:{1} -pidfile {2}"'.format(bootparams, threadport, self.qemu_pidfile)
if qemuparams:
self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + '\"'
@ -198,11 +203,26 @@ class QemuRunner:
self.stop()
self.logger.info("Output from runqemu:\n%s" % self.getOutput(output))
return False
time.sleep(1)
time.sleep(0.5)
if not self.is_alive():
self.logger.error("Qemu pid didn't appear in %s seconds" % self.runqemutime)
# Dump all processes to help us to figure out what is going on...
ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,command '], stdout=subprocess.PIPE).communicate()[0]
processes = ps.decode("utf-8")
self.logger.info("Running processes:\n%s" % processes)
self._dump_host()
self.stop()
op = self.getOutput(output)
if op:
self.logger.error("Output from runqemu:\n%s" % op)
else:
self.logger.error("No output from runqemu.\n")
return False
# We are alive: qemu is running
out = self.getOutput(output)
netconf = False # network configuration is not required by default
if self.is_alive():
self.logger.info("qemu started in %s seconds - qemu procces pid is %s" % (time.time() - (endtime - self.runqemutime), self.qemupid))
if get_ip:
cmdline = ''
@ -314,19 +334,7 @@ class QemuRunner:
" as root using blank password")
except:
self.logger.info("Serial console failed while trying to login")
else:
self.logger.error("Qemu pid didn't appear in %s seconds" % self.runqemutime)
self._dump_host()
self.stop()
op = self.getOutput(output)
if op:
self.logger.error("Output from runqemu:\n%s" % op)
else:
self.logger.error("No output from runqemu.\n")
return False
return self.is_alive()
return True
def stop(self):
self.stop_thread()
@ -354,6 +362,8 @@ class QemuRunner:
self.server_socket = None
self.qemupid = None
self.ip = None
if os.path.exists(self.qemu_pidfile):
os.remove(self.qemu_pidfile)
def stop_qemu_system(self):
if self.qemupid:
@ -379,56 +389,15 @@ class QemuRunner:
def is_alive(self):
if not self.runqemu:
return False
qemu_child = self.find_child(str(self.runqemu.pid))
if qemu_child:
self.qemupid = qemu_child[0]
if os.path.exists("/proc/" + str(self.qemupid)):
if os.path.isfile(self.qemu_pidfile):
f = open(self.qemu_pidfile, 'r')
qemu_pid = f.read()
f.close()
#logger.info("qemu_pid: %s" % qemu_pid)
self.qemupid = int(qemu_pid)
return True
return False
def find_child(self,parent_pid):
#
# Walk the process tree from the process specified looking for a qemu-system. Return its [pid'cmd]
#
ps = subprocess.Popen(['ps', 'axww', '-o', 'pid,ppid,command'], stdout=subprocess.PIPE).communicate()[0]
processes = ps.decode("utf-8").split('\n')
nfields = len(processes[0].split()) - 1
pids = {}
commands = {}
for row in processes[1:]:
data = row.split(None, nfields)
if len(data) != 3:
continue
if data[1] not in pids:
pids[data[1]] = []
pids[data[1]].append(data[0])
commands[data[0]] = data[2]
if parent_pid not in pids:
return []
parents = []
newparents = pids[parent_pid]
while newparents:
next = []
for p in newparents:
if p in pids:
for n in pids[p]:
if n not in parents and n not in next:
next.append(n)
if p not in parents:
parents.append(p)
newparents = next
#print("Children matching %s:" % str(parents))
for p in parents:
# Need to be careful here since runqemu runs "ldd qemu-system-xxxx"
# Also, old versions of ldd (2.11) run "LD_XXXX qemu-system-xxxx"
basecmd = commands[p].split()[0]
basecmd = os.path.basename(basecmd)
if "qemu-system" in basecmd and "-serial tcp" in commands[p]:
return [int(p),commands[p]]
def run_serial(self, command, raw=False, timeout=5):
# We assume target system have echo to get command status
if not raw: