=== modified file 'lava_dispatcher/actions/lava_android_test.py'
@@ -24,7 +24,7 @@
import logging
from lava_dispatcher.actions import BaseAction
from lava_dispatcher.errors import OperationFailed, TimeoutError
-from lava_dispatcher.utils import generate_bundle_file_name
+from lava_dispatcher.utils import generate_bundle_file_name, DrainConsoleOutput
class AndroidTestAction(BaseAction):
@@ -66,8 +66,11 @@
cmds.insert(0, 'timeout')
cmds.insert(1, '%ss' % timeout)
+ t = DrainConsoleOutput(proc=session._connection, timeout=timeout)
+ t.start()
logging.info("Execute command on host: %s" % (' '.join(cmds)))
rc = subprocess.call(cmds)
+ t.join()
if rc == 124:
raise TimeoutError(
"The test case(%s) on device(%s) times out" % (
=== modified file 'lava_dispatcher/device/fastmodel.py'
@@ -50,6 +50,7 @@
extract_targz,
logging_spawn,
logging_system,
+ DrainConsoleOutput,
)
@@ -184,7 +185,7 @@
f = cStringIO.StringIO()
self._sim_proc.logfile = self._create_rtsm_ostream(f)
- _pexpect_drain(self._sim_proc).start()
+ DrainConsoleOutput(proc=self._sim_proc).start()
def power_on(self):
self._fix_perms()
@@ -235,18 +236,4 @@
return "unknown"
-class _pexpect_drain(threading.Thread):
- ''' The simulator process can dump a lot of information to its console. If
- don't actively read from it, the pipe will get full and the process will
- be blocked. This allows us to keep the pipe empty so the process can run
- '''
- def __init__(self, proc):
- threading.Thread.__init__(self)
- self.proc = proc
-
- self.daemon = True # allow thread to die when main main proc exits
-
- def run(self):
- self.proc.drain()
-
target_class = FastModelTarget
=== modified file 'lava_dispatcher/utils.py'
@@ -23,10 +23,10 @@
import errno
import logging
import os
-import select
-import sys
import shutil
import tempfile
+import threading
+import time
import urlparse
from shlex import shlex
@@ -136,6 +136,31 @@
return os.system(cmd)
+class DrainConsoleOutput(threading.Thread):
+
+ def __init__(self, proc=None, timeout=None):
+ threading.Thread.__init__(self)
+ self.proc = proc
+ self.timeout = timeout
+ self._stopevent = threading.Event()
+ self.daemon = True # allow thread to die when main main proc exits
+
+ def run(self):
+ expect_end = None
+ if self.timeout and (self.timeout > -1):
+ expect_end = time.time() + self.timeout
+ while not self._stopevent.isSet():
+ if expect_end and (expect_end <= time.time()):
+ logging.info("DrainConsoleOutput times out:%s" % self.timeout)
+ break
+ self.proc.empty_buffer()
+ time.sleep(5)
+
+ def join(self, timeout=None):
+ self._stopevent.set()
+ threading.Thread.join(self, timeout)
+
+
class logging_spawn(pexpect.spawn):
def sendline(self, *args, **kw):
@@ -169,23 +194,8 @@
index = 0
while index == 0:
index = self.expect(
- ['.+', pexpect.EOF, pexpect.TIMEOUT], timeout=1, lava_no_logging=1)
-
- def drain(self):
- """this is a one-off of the pexect __interact that ignores STDIN and
- handles an error that happens when we call read just after the process
- exits
- """
- try:
- self._spawn__interact_copy(escape_character=chr(29))
- except:
- einfo = sys.exc_info()
- # since we blindly read this from a thread, it will always wind up
- # dying with a select error. we should still make note of other
- # exceptions that might happen
- if not isinstance(einfo[1], select.error):
- logging.warn("error while draining pexpect buffers: %r", einfo)
- pass
+ ['.+', pexpect.EOF, pexpect.TIMEOUT],
+ timeout=1, lava_no_logging=1)
# XXX Duplication: we should reuse lava-test TestArtifacts