diff options
Diffstat (limited to 'meta/lib/oeqa/utils/qemurunner.py')
-rw-r--r-- | meta/lib/oeqa/utils/qemurunner.py | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/meta/lib/oeqa/utils/qemurunner.py b/meta/lib/oeqa/utils/qemurunner.py index 77ec939ad7..c84d299a80 100644 --- a/meta/lib/oeqa/utils/qemurunner.py +++ b/meta/lib/oeqa/utils/qemurunner.py | |||
@@ -70,6 +70,8 @@ class QemuRunner: | |||
70 | self.monitorpipe = None | 70 | self.monitorpipe = None |
71 | 71 | ||
72 | self.logger = logger | 72 | self.logger = logger |
73 | # Whether we're expecting an exit and should show related errors | ||
74 | self.canexit = False | ||
73 | 75 | ||
74 | # Enable testing other OS's | 76 | # Enable testing other OS's |
75 | # Set commands for target communication, and default to Linux ALWAYS | 77 | # Set commands for target communication, and default to Linux ALWAYS |
@@ -118,7 +120,10 @@ class QemuRunner: | |||
118 | import fcntl | 120 | import fcntl |
119 | fl = fcntl.fcntl(o, fcntl.F_GETFL) | 121 | fl = fcntl.fcntl(o, fcntl.F_GETFL) |
120 | fcntl.fcntl(o, fcntl.F_SETFL, fl | os.O_NONBLOCK) | 122 | fcntl.fcntl(o, fcntl.F_SETFL, fl | os.O_NONBLOCK) |
121 | return os.read(o.fileno(), 1000000).decode("utf-8") | 123 | try: |
124 | return os.read(o.fileno(), 1000000).decode("utf-8") | ||
125 | except BlockingIOError: | ||
126 | return "" | ||
122 | 127 | ||
123 | 128 | ||
124 | def handleSIGCHLD(self, signum, frame): | 129 | def handleSIGCHLD(self, signum, frame): |
@@ -229,7 +234,7 @@ class QemuRunner: | |||
229 | r = os.fdopen(r) | 234 | r = os.fdopen(r) |
230 | x = r.read() | 235 | x = r.read() |
231 | os.killpg(os.getpgid(self.runqemu.pid), signal.SIGTERM) | 236 | os.killpg(os.getpgid(self.runqemu.pid), signal.SIGTERM) |
232 | sys.exit(0) | 237 | os._exit(0) |
233 | 238 | ||
234 | self.logger.debug("runqemu started, pid is %s" % self.runqemu.pid) | 239 | self.logger.debug("runqemu started, pid is %s" % self.runqemu.pid) |
235 | self.logger.debug("waiting at most %s seconds for qemu pid (%s)" % | 240 | self.logger.debug("waiting at most %s seconds for qemu pid (%s)" % |
@@ -427,12 +432,17 @@ class QemuRunner: | |||
427 | except OSError as e: | 432 | except OSError as e: |
428 | if e.errno != errno.ESRCH: | 433 | if e.errno != errno.ESRCH: |
429 | raise | 434 | raise |
430 | endtime = time.time() + self.runqemutime | 435 | try: |
431 | while self.runqemu.poll() is None and time.time() < endtime: | 436 | outs, errs = self.runqemu.communicate(timeout = self.runqemutime) |
432 | time.sleep(1) | 437 | if outs: |
433 | if self.runqemu.poll() is None: | 438 | self.logger.info("Output from runqemu:\n%s", outs.decode("utf-8")) |
439 | if errs: | ||
440 | self.logger.info("Stderr from runqemu:\n%s", errs.decode("utf-8")) | ||
441 | except TimeoutExpired: | ||
434 | self.logger.debug("Sending SIGKILL to runqemu") | 442 | self.logger.debug("Sending SIGKILL to runqemu") |
435 | os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL) | 443 | os.killpg(os.getpgid(self.runqemu.pid), signal.SIGKILL) |
444 | if not self.runqemu.stdout.closed: | ||
445 | self.logger.info("Output from runqemu:\n%s" % self.getOutput(self.runqemu.stdout)) | ||
436 | self.runqemu.stdin.close() | 446 | self.runqemu.stdin.close() |
437 | self.runqemu.stdout.close() | 447 | self.runqemu.stdout.close() |
438 | self.runqemu_exited = True | 448 | self.runqemu_exited = True |
@@ -467,6 +477,11 @@ class QemuRunner: | |||
467 | self.thread.stop() | 477 | self.thread.stop() |
468 | self.thread.join() | 478 | self.thread.join() |
469 | 479 | ||
480 | def allowexit(self): | ||
481 | self.canexit = True | ||
482 | if self.thread: | ||
483 | self.thread.allowexit() | ||
484 | |||
470 | def restart(self, qemuparams = None): | 485 | def restart(self, qemuparams = None): |
471 | self.logger.warning("Restarting qemu process") | 486 | self.logger.warning("Restarting qemu process") |
472 | if self.runqemu.poll() is None: | 487 | if self.runqemu.poll() is None: |
@@ -522,7 +537,9 @@ class QemuRunner: | |||
522 | if re.search(self.boot_patterns['search_cmd_finished'], data): | 537 | if re.search(self.boot_patterns['search_cmd_finished'], data): |
523 | break | 538 | break |
524 | else: | 539 | else: |
525 | raise Exception("No data on serial console socket") | 540 | if self.canexit: |
541 | return (1, "") | ||
542 | raise Exception("No data on serial console socket, connection closed?") | ||
526 | 543 | ||
527 | if data: | 544 | if data: |
528 | if raw: | 545 | if raw: |
@@ -560,6 +577,7 @@ class LoggingThread(threading.Thread): | |||
560 | self.logger = logger | 577 | self.logger = logger |
561 | self.readsock = None | 578 | self.readsock = None |
562 | self.running = False | 579 | self.running = False |
580 | self.canexit = False | ||
563 | 581 | ||
564 | self.errorevents = select.POLLERR | select.POLLHUP | select.POLLNVAL | 582 | self.errorevents = select.POLLERR | select.POLLHUP | select.POLLNVAL |
565 | self.readevents = select.POLLIN | select.POLLPRI | 583 | self.readevents = select.POLLIN | select.POLLPRI |
@@ -593,6 +611,9 @@ class LoggingThread(threading.Thread): | |||
593 | self.close_ignore_error(self.writepipe) | 611 | self.close_ignore_error(self.writepipe) |
594 | self.running = False | 612 | self.running = False |
595 | 613 | ||
614 | def allowexit(self): | ||
615 | self.canexit = True | ||
616 | |||
596 | def eventloop(self): | 617 | def eventloop(self): |
597 | poll = select.poll() | 618 | poll = select.poll() |
598 | event_read_mask = self.errorevents | self.readevents | 619 | event_read_mask = self.errorevents | self.readevents |
@@ -638,7 +659,7 @@ class LoggingThread(threading.Thread): | |||
638 | data = self.readsock.recv(count) | 659 | data = self.readsock.recv(count) |
639 | except socket.error as e: | 660 | except socket.error as e: |
640 | if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK: | 661 | if e.errno == errno.EAGAIN or e.errno == errno.EWOULDBLOCK: |
641 | return '' | 662 | return b'' |
642 | else: | 663 | else: |
643 | raise | 664 | raise |
644 | 665 | ||
@@ -649,7 +670,9 @@ class LoggingThread(threading.Thread): | |||
649 | # happened. But for this code it counts as an | 670 | # happened. But for this code it counts as an |
650 | # error since the connection shouldn't go away | 671 | # error since the connection shouldn't go away |
651 | # until qemu exits. | 672 | # until qemu exits. |
652 | raise Exception("Console connection closed unexpectedly") | 673 | if not self.canexit: |
674 | raise Exception("Console connection closed unexpectedly") | ||
675 | return b'' | ||
653 | 676 | ||
654 | return data | 677 | return data |
655 | 678 | ||