summaryrefslogtreecommitdiffstats
path: root/meta/lib
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib')
-rw-r--r--meta/lib/oe/package_manager.py37
-rw-r--r--meta/lib/oe/prservice.py4
-rw-r--r--meta/lib/oe/sstatesig.py13
-rw-r--r--meta/lib/oe/utils.py2
-rw-r--r--meta/lib/oeqa/core/utils/concurrencytest.py2
-rw-r--r--meta/lib/oeqa/sdkext/testsdk.py7
-rw-r--r--meta/lib/oeqa/selftest/cases/runtime_test.py2
-rw-r--r--meta/lib/oeqa/selftest/cases/signing.py4
-rw-r--r--meta/lib/oeqa/selftest/context.py6
-rw-r--r--meta/lib/oeqa/targetcontrol.py7
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py16
11 files changed, 67 insertions, 33 deletions
diff --git a/meta/lib/oe/package_manager.py b/meta/lib/oe/package_manager.py
index 7c373715ad..e0b15dc9b4 100644
--- a/meta/lib/oe/package_manager.py
+++ b/meta/lib/oe/package_manager.py
@@ -40,8 +40,9 @@ def opkg_query(cmd_output):
40 ver = "" 40 ver = ""
41 filename = "" 41 filename = ""
42 dep = [] 42 dep = []
43 prov = []
43 pkgarch = "" 44 pkgarch = ""
44 for line in cmd_output.splitlines(): 45 for line in cmd_output.splitlines()+['']:
45 line = line.rstrip() 46 line = line.rstrip()
46 if ':' in line: 47 if ':' in line:
47 if line.startswith("Package: "): 48 if line.startswith("Package: "):
@@ -64,6 +65,10 @@ def opkg_query(cmd_output):
64 dep.append("%s [REC]" % recommend) 65 dep.append("%s [REC]" % recommend)
65 elif line.startswith("PackageArch: "): 66 elif line.startswith("PackageArch: "):
66 pkgarch = line.split(": ")[1] 67 pkgarch = line.split(": ")[1]
68 elif line.startswith("Provides: "):
69 provides = verregex.sub('', line.split(": ")[1])
70 for provide in provides.split(", "):
71 prov.append(provide)
67 72
68 # When there is a blank line save the package information 73 # When there is a blank line save the package information
69 elif not line: 74 elif not line:
@@ -72,20 +77,15 @@ def opkg_query(cmd_output):
72 filename = "%s_%s_%s.ipk" % (pkg, ver, arch) 77 filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
73 if pkg: 78 if pkg:
74 output[pkg] = {"arch":arch, "ver":ver, 79 output[pkg] = {"arch":arch, "ver":ver,
75 "filename":filename, "deps": dep, "pkgarch":pkgarch } 80 "filename":filename, "deps": dep, "pkgarch":pkgarch, "provs": prov}
76 pkg = "" 81 pkg = ""
77 arch = "" 82 arch = ""
78 ver = "" 83 ver = ""
79 filename = "" 84 filename = ""
80 dep = [] 85 dep = []
86 prov = []
81 pkgarch = "" 87 pkgarch = ""
82 88
83 if pkg:
84 if not filename:
85 filename = "%s_%s_%s.ipk" % (pkg, ver, arch)
86 output[pkg] = {"arch":arch, "ver":ver,
87 "filename":filename, "deps": dep }
88
89 return output 89 return output
90 90
91def failed_postinsts_abort(pkgs, log_path): 91def failed_postinsts_abort(pkgs, log_path):
@@ -360,7 +360,7 @@ class DpkgPkgsList(PkgsList):
360 "--admindir=%s/var/lib/dpkg" % self.rootfs_dir, 360 "--admindir=%s/var/lib/dpkg" % self.rootfs_dir,
361 "-W"] 361 "-W"]
362 362
363 cmd.append("-f=Package: ${Package}\nArchitecture: ${PackageArch}\nVersion: ${Version}\nFile: ${Package}_${Version}_${Architecture}.deb\nDepends: ${Depends}\nRecommends: ${Recommends}\n\n") 363 cmd.append("-f=Package: ${Package}\nArchitecture: ${PackageArch}\nVersion: ${Version}\nFile: ${Package}_${Version}_${Architecture}.deb\nDepends: ${Depends}\nRecommends: ${Recommends}\nProvides: ${Provides}\n\n")
364 364
365 try: 365 try:
366 cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8") 366 cmd_output = subprocess.check_output(cmd, stderr=subprocess.STDOUT).strip().decode("utf-8")
@@ -578,6 +578,11 @@ class PackageManager(object, metaclass=ABCMeta):
578 # oe-pkgdata-util reads it from a file 578 # oe-pkgdata-util reads it from a file
579 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs: 579 with tempfile.NamedTemporaryFile(mode="w+", prefix="installed-pkgs") as installed_pkgs:
580 pkgs = self.list_installed() 580 pkgs = self.list_installed()
581
582 provided_pkgs = set()
583 for pkg in pkgs.values():
584 provided_pkgs |= set(pkg.get('provs', []))
585
581 output = oe.utils.format_pkg_list(pkgs, "arch") 586 output = oe.utils.format_pkg_list(pkgs, "arch")
582 installed_pkgs.write(output) 587 installed_pkgs.write(output)
583 installed_pkgs.flush() 588 installed_pkgs.flush()
@@ -589,10 +594,15 @@ class PackageManager(object, metaclass=ABCMeta):
589 if exclude: 594 if exclude:
590 cmd.extend(['--exclude=' + '|'.join(exclude.split())]) 595 cmd.extend(['--exclude=' + '|'.join(exclude.split())])
591 try: 596 try:
592 bb.note("Installing complementary packages ...")
593 bb.note('Running %s' % cmd) 597 bb.note('Running %s' % cmd)
594 complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8") 598 complementary_pkgs = subprocess.check_output(cmd, stderr=subprocess.STDOUT).decode("utf-8")
595 self.install(complementary_pkgs.split(), attempt_only=True) 599 complementary_pkgs = set(complementary_pkgs.split())
600 skip_pkgs = sorted(complementary_pkgs & provided_pkgs)
601 install_pkgs = sorted(complementary_pkgs - provided_pkgs)
602 bb.note("Installing complementary packages ... %s (skipped already provided packages %s)" % (
603 ' '.join(install_pkgs),
604 ' '.join(skip_pkgs)))
605 self.install(install_pkgs, attempt_only=True)
596 except subprocess.CalledProcessError as e: 606 except subprocess.CalledProcessError as e:
597 bb.fatal("Could not compute complementary packages list. Command " 607 bb.fatal("Could not compute complementary packages list. Command "
598 "'%s' returned %d:\n%s" % 608 "'%s' returned %d:\n%s" %
@@ -1619,7 +1629,7 @@ class DpkgPM(OpkgDpkgPM):
1619 1629
1620 os.environ['APT_CONFIG'] = self.apt_conf_file 1630 os.environ['APT_CONFIG'] = self.apt_conf_file
1621 1631
1622 cmd = "%s %s install --force-yes --allow-unauthenticated %s" % \ 1632 cmd = "%s %s install --force-yes --allow-unauthenticated --no-remove %s" % \
1623 (self.apt_get_cmd, self.apt_args, ' '.join(pkgs)) 1633 (self.apt_get_cmd, self.apt_args, ' '.join(pkgs))
1624 1634
1625 try: 1635 try:
@@ -1781,8 +1791,7 @@ class DpkgPM(OpkgDpkgPM):
1781 open(os.path.join(target_dpkg_dir, "available"), "w+").close() 1791 open(os.path.join(target_dpkg_dir, "available"), "w+").close()
1782 1792
1783 def remove_packaging_data(self): 1793 def remove_packaging_data(self):
1784 bb.utils.remove(os.path.join(self.target_rootfs, 1794 bb.utils.remove(self.target_rootfs + self.d.getVar('opkglibdir'), True)
1785 self.d.getVar('opkglibdir')), True)
1786 bb.utils.remove(self.target_rootfs + "/var/lib/dpkg/", True) 1795 bb.utils.remove(self.target_rootfs + "/var/lib/dpkg/", True)
1787 1796
1788 def fix_broken_dependencies(self): 1797 def fix_broken_dependencies(self):
diff --git a/meta/lib/oe/prservice.py b/meta/lib/oe/prservice.py
index b1132ccb11..3a5ef8d921 100644
--- a/meta/lib/oe/prservice.py
+++ b/meta/lib/oe/prservice.py
@@ -3,6 +3,10 @@
3# 3#
4 4
5def prserv_make_conn(d, check = False): 5def prserv_make_conn(d, check = False):
6 # Otherwise this fails when called from recipes which e.g. inherit python3native (which sets _PYTHON_SYSCONFIGDATA_NAME) with:
7 # No module named '_sysconfigdata'
8 if '_PYTHON_SYSCONFIGDATA_NAME' in os.environ:
9 del os.environ['_PYTHON_SYSCONFIGDATA_NAME']
6 import prserv.serv 10 import prserv.serv
7 host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f]) 11 host_params = list([_f for _f in (d.getVar("PRSERV_HOST") or '').split(':') if _f])
8 try: 12 try:
diff --git a/meta/lib/oe/sstatesig.py b/meta/lib/oe/sstatesig.py
index b2316b12b8..f1abff0c45 100644
--- a/meta/lib/oe/sstatesig.py
+++ b/meta/lib/oe/sstatesig.py
@@ -151,6 +151,13 @@ class SignatureGeneratorOEBasicHashMixIn(object):
151 151
152 def get_taskhash(self, tid, deps, dataCache): 152 def get_taskhash(self, tid, deps, dataCache):
153 h = super(bb.siggen.SignatureGeneratorBasicHash, self).get_taskhash(tid, deps, dataCache) 153 h = super(bb.siggen.SignatureGeneratorBasicHash, self).get_taskhash(tid, deps, dataCache)
154 if tid in self.lockedhashes:
155 if self.lockedhashes[tid]:
156 return self.lockedhashes[tid]
157 else:
158 return h
159
160 h = super(bb.siggen.SignatureGeneratorBasicHash, self).get_taskhash(tid, deps, dataCache)
154 161
155 (mc, _, task, fn) = bb.runqueue.split_tid_mcfn(tid) 162 (mc, _, task, fn) = bb.runqueue.split_tid_mcfn(tid)
156 163
@@ -187,17 +194,19 @@ class SignatureGeneratorOEBasicHashMixIn(object):
187 % (recipename, task, h, h_locked, var)) 194 % (recipename, task, h, h_locked, var))
188 195
189 return h_locked 196 return h_locked
197
198 self.lockedhashes[tid] = False
190 #bb.warn("%s %s %s" % (recipename, task, h)) 199 #bb.warn("%s %s %s" % (recipename, task, h))
191 return h 200 return h
192 201
193 def get_unihash(self, tid): 202 def get_unihash(self, tid):
194 if tid in self.lockedhashes: 203 if tid in self.lockedhashes and self.lockedhashes[tid]:
195 return self.lockedhashes[tid] 204 return self.lockedhashes[tid]
196 return super().get_unihash(tid) 205 return super().get_unihash(tid)
197 206
198 def dump_sigtask(self, fn, task, stampbase, runtime): 207 def dump_sigtask(self, fn, task, stampbase, runtime):
199 tid = fn + ":" + task 208 tid = fn + ":" + task
200 if tid in self.lockedhashes: 209 if tid in self.lockedhashes and self.lockedhashes[tid]:
201 return 210 return
202 super(bb.siggen.SignatureGeneratorBasicHash, self).dump_sigtask(fn, task, stampbase, runtime) 211 super(bb.siggen.SignatureGeneratorBasicHash, self).dump_sigtask(fn, task, stampbase, runtime)
203 212
diff --git a/meta/lib/oe/utils.py b/meta/lib/oe/utils.py
index 652b2be145..144c123a0e 100644
--- a/meta/lib/oe/utils.py
+++ b/meta/lib/oe/utils.py
@@ -387,7 +387,7 @@ def host_gcc_version(d, taskcontextonly=False):
387 except subprocess.CalledProcessError as e: 387 except subprocess.CalledProcessError as e:
388 bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8"))) 388 bb.fatal("Error running %s --version: %s" % (compiler, e.output.decode("utf-8")))
389 389
390 match = re.match(r".* (\d\.\d)\.\d.*", output.split('\n')[0]) 390 match = re.match(r".* (\d+\.\d+)\.\d+.*", output.split('\n')[0])
391 if not match: 391 if not match:
392 bb.fatal("Can't get compiler version from %s --version output" % compiler) 392 bb.fatal("Can't get compiler version from %s --version output" % compiler)
393 393
diff --git a/meta/lib/oeqa/core/utils/concurrencytest.py b/meta/lib/oeqa/core/utils/concurrencytest.py
index 0f7b3dcc11..e6b14da89d 100644
--- a/meta/lib/oeqa/core/utils/concurrencytest.py
+++ b/meta/lib/oeqa/core/utils/concurrencytest.py
@@ -261,7 +261,7 @@ def fork_for_tests(concurrency_num, suite):
261 oe.path.copytree(selftestdir, newselftestdir) 261 oe.path.copytree(selftestdir, newselftestdir)
262 262
263 for e in os.environ: 263 for e in os.environ:
264 if builddir in os.environ[e]: 264 if builddir + "/" in os.environ[e] or os.environ[e].endswith(builddir):
265 os.environ[e] = os.environ[e].replace(builddir, newbuilddir) 265 os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
266 266
267 subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True) 267 subprocess.check_output("git init; git add *; git commit -a -m 'initial'", cwd=newselftestdir, shell=True)
diff --git a/meta/lib/oeqa/sdkext/testsdk.py b/meta/lib/oeqa/sdkext/testsdk.py
index 785b5dda53..c5c46df6cd 100644
--- a/meta/lib/oeqa/sdkext/testsdk.py
+++ b/meta/lib/oeqa/sdkext/testsdk.py
@@ -25,11 +25,8 @@ class TestSDKExt(TestSDKBase):
25 25
26 subprocesstweak.errors_have_output() 26 subprocesstweak.errors_have_output()
27 27
28 # extensible sdk can be contaminated if native programs are 28 # We need the original PATH for testing the eSDK, not with our manipulations
29 # in PATH, i.e. use perl-native instead of eSDK one. 29 os.environ['PATH'] = d.getVar("BB_ORIGENV", False).getVar("PATH")
30 paths_to_avoid = [d.getVar('STAGING_DIR'),
31 d.getVar('BASE_WORKDIR')]
32 os.environ['PATH'] = avoid_paths_in_environ(paths_to_avoid)
33 30
34 tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.sh") 31 tcname = d.expand("${SDK_DEPLOY}/${TOOLCHAINEXT_OUTPUTNAME}.sh")
35 if not os.path.exists(tcname): 32 if not os.path.exists(tcname):
diff --git a/meta/lib/oeqa/selftest/cases/runtime_test.py b/meta/lib/oeqa/selftest/cases/runtime_test.py
index 7d3922ce44..d4fea91350 100644
--- a/meta/lib/oeqa/selftest/cases/runtime_test.py
+++ b/meta/lib/oeqa/selftest/cases/runtime_test.py
@@ -166,7 +166,7 @@ class TestImage(OESelftestTestCase):
166 bitbake('core-image-full-cmdline socat') 166 bitbake('core-image-full-cmdline socat')
167 bitbake('-c testimage core-image-full-cmdline') 167 bitbake('-c testimage core-image-full-cmdline')
168 168
169 def test_testimage_virgl_gtk(self): 169 def disabled_test_testimage_virgl_gtk(self):
170 """ 170 """
171 Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk frontend 171 Summary: Check host-assisted accelerate OpenGL functionality in qemu with gtk frontend
172 Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled 172 Expected: 1. Check that virgl kernel driver is loaded and 3d acceleration is enabled
diff --git a/meta/lib/oeqa/selftest/cases/signing.py b/meta/lib/oeqa/selftest/cases/signing.py
index 5c4e01b2c3..5b8f9bbd38 100644
--- a/meta/lib/oeqa/selftest/cases/signing.py
+++ b/meta/lib/oeqa/selftest/cases/signing.py
@@ -44,7 +44,9 @@ class Signing(OESelftestTestCase):
44 origenv = os.environ.copy() 44 origenv = os.environ.copy()
45 45
46 for e in os.environ: 46 for e in os.environ:
47 if builddir in os.environ[e]: 47 if builddir + "/" in os.environ[e]:
48 os.environ[e] = os.environ[e].replace(builddir + "/", newbuilddir + "/")
49 if os.environ[e].endswith(builddir):
48 os.environ[e] = os.environ[e].replace(builddir, newbuilddir) 50 os.environ[e] = os.environ[e].replace(builddir, newbuilddir)
49 51
50 os.chdir(newbuilddir) 52 os.chdir(newbuilddir)
diff --git a/meta/lib/oeqa/selftest/context.py b/meta/lib/oeqa/selftest/context.py
index c4eb5d614e..3d3b19c6e8 100644
--- a/meta/lib/oeqa/selftest/context.py
+++ b/meta/lib/oeqa/selftest/context.py
@@ -280,11 +280,15 @@ class OESelftestTestContextExecutor(OETestContextExecutor):
280 return rc 280 return rc
281 281
282 def _signal_clean_handler(self, signum, frame): 282 def _signal_clean_handler(self, signum, frame):
283 sys.exit(1) 283 if self.ourpid == os.getpid():
284 sys.exit(1)
284 285
285 def run(self, logger, args): 286 def run(self, logger, args):
286 self._process_args(logger, args) 287 self._process_args(logger, args)
287 288
289 # Setup a SIGTERM handler to allow restoration of files like local.conf and bblayers.conf
290 # but don't interfer with other processes
291 self.ourpid = os.getpid()
288 signal.signal(signal.SIGTERM, self._signal_clean_handler) 292 signal.signal(signal.SIGTERM, self._signal_clean_handler)
289 293
290 rc = None 294 rc = None
diff --git a/meta/lib/oeqa/targetcontrol.py b/meta/lib/oeqa/targetcontrol.py
index 1445e3ecfb..41557dc224 100644
--- a/meta/lib/oeqa/targetcontrol.py
+++ b/meta/lib/oeqa/targetcontrol.py
@@ -117,9 +117,9 @@ class QemuTarget(BaseTarget):
117 import oe.path 117 import oe.path
118 bb.utils.mkdirhier(self.testdir) 118 bb.utils.mkdirhier(self.testdir)
119 self.qemurunnerlog = os.path.join(self.testdir, 'qemurunner_log.%s' % self.datetime) 119 self.qemurunnerlog = os.path.join(self.testdir, 'qemurunner_log.%s' % self.datetime)
120 loggerhandler = logging.FileHandler(self.qemurunnerlog) 120 self.loggerhandler = logging.FileHandler(self.qemurunnerlog)
121 loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s")) 121 self.loggerhandler.setFormatter(logging.Formatter("%(levelname)s: %(message)s"))
122 self.logger.addHandler(loggerhandler) 122 self.logger.addHandler(self.loggerhandler)
123 oe.path.symlink(os.path.basename(self.qemurunnerlog), os.path.join(self.testdir, 'qemurunner_log'), force=True) 123 oe.path.symlink(os.path.basename(self.qemurunnerlog), os.path.join(self.testdir, 'qemurunner_log'), force=True)
124 124
125 if d.getVar("DISTRO") == "poky-tiny": 125 if d.getVar("DISTRO") == "poky-tiny":
@@ -182,6 +182,7 @@ class QemuTarget(BaseTarget):
182 182
183 def stop(self): 183 def stop(self):
184 self.runner.stop() 184 self.runner.stop()
185 self.logger.removeHandler(self.loggerhandler)
185 self.connection = None 186 self.connection = None
186 self.ip = None 187 self.ip = None
187 self.server_ip = None 188 self.server_ip = None
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py
index fe8b77d97a..3db177b001 100644
--- a/meta/lib/oeqa/utils/qemurunner.py
+++ b/meta/lib/oeqa/utils/qemurunner.py
@@ -35,6 +35,7 @@ class QemuRunner:
35 35
36 # Popen object for runqemu 36 # Popen object for runqemu
37 self.runqemu = None 37 self.runqemu = None
38 self.runqemu_exited = False
38 # pid of the qemu process that runqemu will start 39 # pid of the qemu process that runqemu will start
39 self.qemupid = None 40 self.qemupid = None
40 # target ip - from the command line or runqemu output 41 # target ip - from the command line or runqemu output
@@ -102,7 +103,6 @@ class QemuRunner:
102 self.logger.debug("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout)) 103 self.logger.debug("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout))
103 self.stop() 104 self.stop()
104 self._dump_host() 105 self._dump_host()
105 raise SystemExit
106 106
107 def start(self, qemuparams = None, get_ip = True, extra_bootparams = None, runqemuparams='', launch_cmd=None, discard_writes=True): 107 def start(self, qemuparams = None, get_ip = True, extra_bootparams = None, runqemuparams='', launch_cmd=None, discard_writes=True):
108 env = os.environ.copy() 108 env = os.environ.copy()
@@ -206,6 +206,8 @@ class QemuRunner:
206 endtime = time.time() + self.runqemutime 206 endtime = time.time() + self.runqemutime
207 while not self.is_alive() and time.time() < endtime: 207 while not self.is_alive() and time.time() < endtime:
208 if self.runqemu.poll(): 208 if self.runqemu.poll():
209 if self.runqemu_exited:
210 return False
209 if self.runqemu.returncode: 211 if self.runqemu.returncode:
210 # No point waiting any longer 212 # No point waiting any longer
211 self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode) 213 self.logger.warning('runqemu exited with code %d' % self.runqemu.returncode)
@@ -215,6 +217,9 @@ class QemuRunner:
215 return False 217 return False
216 time.sleep(0.5) 218 time.sleep(0.5)
217 219
220 if self.runqemu_exited:
221 return False
222
218 if not self.is_alive(): 223 if not self.is_alive():
219 self.logger.error("Qemu pid didn't appear in %s seconds (%s)" % 224 self.logger.error("Qemu pid didn't appear in %s seconds (%s)" %
220 (self.runqemutime, time.strftime("%D %H:%M:%S"))) 225 (self.runqemutime, time.strftime("%D %H:%M:%S")))
@@ -385,7 +390,7 @@ class QemuRunner:
385 os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL) 390 os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL)
386 self.runqemu.stdin.close() 391 self.runqemu.stdin.close()
387 self.runqemu.stdout.close() 392 self.runqemu.stdout.close()
388 self.runqemu = None 393 self.runqemu_exited = True
389 394
390 if hasattr(self, 'server_socket') and self.server_socket: 395 if hasattr(self, 'server_socket') and self.server_socket:
391 self.server_socket.close() 396 self.server_socket.close()
@@ -396,7 +401,10 @@ class QemuRunner:
396 self.qemupid = None 401 self.qemupid = None
397 self.ip = None 402 self.ip = None
398 if os.path.exists(self.qemu_pidfile): 403 if os.path.exists(self.qemu_pidfile):
399 os.remove(self.qemu_pidfile) 404 try:
405 os.remove(self.qemu_pidfile)
406 except FileNotFoundError as e:
407 self.logger.warning('qemu pidfile is no longer present')
400 if self.monitorpipe: 408 if self.monitorpipe:
401 self.monitorpipe.close() 409 self.monitorpipe.close()
402 410
@@ -422,7 +430,7 @@ class QemuRunner:
422 return False 430 return False
423 431
424 def is_alive(self): 432 def is_alive(self):
425 if not self.runqemu or self.runqemu.poll() is not None: 433 if not self.runqemu or self.runqemu.poll() is not None or self.runqemu_exited:
426 return False 434 return False
427 if os.path.isfile(self.qemu_pidfile): 435 if os.path.isfile(self.qemu_pidfile):
428 # when handling pidfile, qemu creates the file, stat it, lock it and then write to it 436 # when handling pidfile, qemu creates the file, stat it, lock it and then write to it