diff options
author | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-09-04 16:59:38 +0100 |
---|---|---|
committer | Richard Purdie <richard.purdie@linuxfoundation.org> | 2015-09-06 15:26:18 +0100 |
commit | ef0fe3193eb546757f7c98274b88c4f2eafd7ad0 (patch) | |
tree | 4e3222722ee7fa29409fde8e2f614b8d12683a0e /meta/lib/oeqa/utils/qemurunner.py | |
parent | 3d81a56912fb2c6ca1c5aafb93cbc6e2cfea20b3 (diff) | |
download | poky-ef0fe3193eb546757f7c98274b88c4f2eafd7ad0.tar.gz |
oeqa: Test failure/cleanup improvements
Currently, if qemu segfaults, the tests merrily continue trying to execute
which takes time for them to timeout and is a bit silly. Worse, no logs about
the segfault are shown to the user, its silent!
This patch tries to unravel the tangled web of issues and ensures that we:
* install a SIGCHLD handler which tells the user qemu exited
* check if qemu is running, if it isn't fail the test outright
* don't leave processes behind in sshcontrol which would hold
bitbake.lock and block shutdown
(From OE-Core rev: 5c04b1ca1e989f569d5755a646734d01a0c56cae)
Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
Diffstat (limited to 'meta/lib/oeqa/utils/qemurunner.py')
-rw-r--r-- | meta/lib/oeqa/utils/qemurunner.py | 35 |
1 files changed, 25 insertions, 10 deletions
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py index 3ad747a503..2d485379e8 100644 --- a/meta/lib/oeqa/utils/qemurunner.py +++ b/meta/lib/oeqa/utils/qemurunner.py | |||
@@ -64,6 +64,22 @@ class QemuRunner: | |||
64 | with open(self.logfile, "a") as f: | 64 | with open(self.logfile, "a") as f: |
65 | f.write("%s" % msg) | 65 | f.write("%s" % msg) |
66 | 66 | ||
67 | def getOutput(self, o): | ||
68 | import fcntl | ||
69 | fl = fcntl.fcntl(o, fcntl.F_GETFL) | ||
70 | fcntl.fcntl(o, fcntl.F_SETFL, fl | os.O_NONBLOCK) | ||
71 | return os.read(o.fileno(), 1000000) | ||
72 | |||
73 | |||
74 | def handleSIGCHLD(self, signum, frame): | ||
75 | if self.runqemu and self.runqemu.poll(): | ||
76 | if self.runqemu.returncode: | ||
77 | logger.info('runqemu exited with code %d' % self.runqemu.returncode) | ||
78 | logger.info("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout)) | ||
79 | self.stop() | ||
80 | self._dump_host() | ||
81 | raise SystemExit | ||
82 | |||
67 | def start(self, qemuparams = None): | 83 | def start(self, qemuparams = None): |
68 | if self.display: | 84 | if self.display: |
69 | os.environ["DISPLAY"] = self.display | 85 | os.environ["DISPLAY"] = self.display |
@@ -98,11 +114,8 @@ class QemuRunner: | |||
98 | if qemuparams: | 114 | if qemuparams: |
99 | self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + '\"' | 115 | self.qemuparams = self.qemuparams[:-1] + " " + qemuparams + " " + '\"' |
100 | 116 | ||
101 | def getOutput(o): | 117 | self.origchldhandler = signal.getsignal(signal.SIGCHLD) |
102 | import fcntl | 118 | signal.signal(signal.SIGCHLD, self.handleSIGCHLD) |
103 | fl = fcntl.fcntl(o, fcntl.F_GETFL) | ||
104 | fcntl.fcntl(o, fcntl.F_SETFL, fl | os.O_NONBLOCK) | ||
105 | return os.read(o.fileno(), 1000000) | ||
106 | 119 | ||
107 | launch_cmd = 'runqemu tcpserial=%s %s %s %s' % (self.serverport, self.machine, self.rootfs, self.qemuparams) | 120 | launch_cmd = 'runqemu tcpserial=%s %s %s %s' % (self.serverport, self.machine, self.rootfs, self.qemuparams) |
108 | # FIXME: We pass in stdin=subprocess.PIPE here to work around stty | 121 | # FIXME: We pass in stdin=subprocess.PIPE here to work around stty |
@@ -122,7 +135,7 @@ class QemuRunner: | |||
122 | logger.info('runqemu exited with code %d' % self.runqemu.returncode) | 135 | logger.info('runqemu exited with code %d' % self.runqemu.returncode) |
123 | self._dump_host() | 136 | self._dump_host() |
124 | self.stop() | 137 | self.stop() |
125 | logger.info("Output from runqemu:\n%s" % getOutput(output)) | 138 | logger.info("Output from runqemu:\n%s" % self.getOutput(output)) |
126 | return False | 139 | return False |
127 | time.sleep(1) | 140 | time.sleep(1) |
128 | 141 | ||
@@ -139,7 +152,7 @@ class QemuRunner: | |||
139 | self.ip = ips[0] | 152 | self.ip = ips[0] |
140 | self.server_ip = ips[1] | 153 | self.server_ip = ips[1] |
141 | except IndexError, ValueError: | 154 | except IndexError, ValueError: |
142 | logger.info("Couldn't get ip from qemu process arguments! Here is the qemu command line used:\n%s\nand output from runqemu:\n%s" % (cmdline, getOutput(output))) | 155 | logger.info("Couldn't get ip from qemu process arguments! Here is the qemu command line used:\n%s\nand output from runqemu:\n%s" % (cmdline, self.getOutput(output))) |
143 | self._dump_host() | 156 | self._dump_host() |
144 | self.stop() | 157 | self.stop() |
145 | return False | 158 | return False |
@@ -154,7 +167,7 @@ class QemuRunner: | |||
154 | logger.error("Didn't receive a console connection from qemu. " | 167 | logger.error("Didn't receive a console connection from qemu. " |
155 | "Here is the qemu command line used:\n%s\nand " | 168 | "Here is the qemu command line used:\n%s\nand " |
156 | "output from runqemu:\n%s" % (cmdline, | 169 | "output from runqemu:\n%s" % (cmdline, |
157 | getOutput(output))) | 170 | self.getOutput(output))) |
158 | self.stop_thread() | 171 | self.stop_thread() |
159 | return False | 172 | return False |
160 | 173 | ||
@@ -213,15 +226,15 @@ class QemuRunner: | |||
213 | logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime) | 226 | logger.info("Qemu pid didn't appeared in %s seconds" % self.runqemutime) |
214 | self._dump_host() | 227 | self._dump_host() |
215 | self.stop() | 228 | self.stop() |
216 | logger.info("Output from runqemu:\n%s" % getOutput(output)) | 229 | logger.info("Output from runqemu:\n%s" % self.getOutput(output)) |
217 | return False | 230 | return False |
218 | 231 | ||
219 | return self.is_alive() | 232 | return self.is_alive() |
220 | 233 | ||
221 | def stop(self): | 234 | def stop(self): |
222 | |||
223 | self.stop_thread() | 235 | self.stop_thread() |
224 | if self.runqemu: | 236 | if self.runqemu: |
237 | signal.signal(signal.SIGCHLD, self.origchldhandler) | ||
225 | logger.info("Sending SIGTERM to runqemu") | 238 | logger.info("Sending SIGTERM to runqemu") |
226 | try: | 239 | try: |
227 | os.killpg(self.runqemu.pid, signal.SIGTERM) | 240 | os.killpg(self.runqemu.pid, signal.SIGTERM) |
@@ -255,6 +268,8 @@ class QemuRunner: | |||
255 | return False | 268 | return False |
256 | 269 | ||
257 | def is_alive(self): | 270 | def is_alive(self): |
271 | if not self.runqemu: | ||
272 | return False | ||
258 | qemu_child = self.find_child(str(self.runqemu.pid)) | 273 | qemu_child = self.find_child(str(self.runqemu.pid)) |
259 | if qemu_child: | 274 | if qemu_child: |
260 | self.qemupid = qemu_child[0] | 275 | self.qemupid = qemu_child[0] |