summaryrefslogtreecommitdiffstats
path: root/meta/lib/oeqa/utils/qemurunner.py
diff options
context:
space:
mode:
Diffstat (limited to 'meta/lib/oeqa/utils/qemurunner.py')
-rw-r--r--meta/lib/oeqa/utils/qemurunner.py41
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