mirror of
https://github.com/u-boot/u-boot.git
synced 2025-05-08 19:11:53 +00:00
pytest: Show a message when sandbox crashes
When a test hands on a real board there is no way on the console to obtain any information about why it hung. With sandbox we can actually find out that it died and get a signal or exit code. Add this to make it easier to figure out what happened. So instead of: test/py/u_boot_spawn.py:171: in expect c = os.read(self.fd, 1024).decode(errors='replace') E OSError: [Errno 5] Input/output error We get: test/py/u_boot_spawn.py:171: in expect c = os.read(self.fd, 1024).decode(errors='replace') E ValueError: U-Boot exited with signal 11 (Signals.SIGSEGV) Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
c3aea68705
commit
35839eda8b
2 changed files with 53 additions and 13 deletions
|
@ -103,6 +103,14 @@ will be written to `${build_dir}/test-log.html`. This is best viewed in a web
|
||||||
browser, but may be read directly as plain text, perhaps with the aid of the
|
browser, but may be read directly as plain text, perhaps with the aid of the
|
||||||
`html2text` utility.
|
`html2text` utility.
|
||||||
|
|
||||||
|
If sandbox crashes (e.g. with a segfault) you will see message like this::
|
||||||
|
|
||||||
|
|
||||||
|
test/py/u_boot_spawn.py:171: in expect
|
||||||
|
c = os.read(self.fd, 1024).decode(errors='replace')
|
||||||
|
E ValueError: U-Boot exited with signal 11 (Signals.SIGSEGV)
|
||||||
|
|
||||||
|
|
||||||
Controlling output
|
Controlling output
|
||||||
~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ class Spawn(object):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.waited = False
|
self.waited = False
|
||||||
|
self.exit_code = 0
|
||||||
|
self.exit_info = ''
|
||||||
self.buf = ''
|
self.buf = ''
|
||||||
self.output = ''
|
self.output = ''
|
||||||
self.logfile_read = None
|
self.logfile_read = None
|
||||||
|
@ -80,6 +82,34 @@ class Spawn(object):
|
||||||
|
|
||||||
os.kill(self.pid, sig)
|
os.kill(self.pid, sig)
|
||||||
|
|
||||||
|
def checkalive(self):
|
||||||
|
"""Determine whether the child process is still running.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple:
|
||||||
|
True if process is alive, else False
|
||||||
|
0 if process is alive, else exit code of process
|
||||||
|
string describing what happened ('' or 'status/signal n')
|
||||||
|
"""
|
||||||
|
|
||||||
|
if self.waited:
|
||||||
|
return False, self.exit_code, self.exit_info
|
||||||
|
|
||||||
|
w = os.waitpid(self.pid, os.WNOHANG)
|
||||||
|
if w[0] == 0:
|
||||||
|
return True, 0, 'running'
|
||||||
|
status = w[1]
|
||||||
|
|
||||||
|
if os.WIFEXITED(status):
|
||||||
|
self.exit_code = os.WEXITSTATUS(status)
|
||||||
|
self.exit_info = 'status %d' % self.exit_code
|
||||||
|
elif os.WIFSIGNALED(status):
|
||||||
|
signum = os.WTERMSIG(status)
|
||||||
|
self.exit_code = -signum
|
||||||
|
self.exit_info = 'signal %d (%s)' % (signum, signal.Signals(signum))
|
||||||
|
self.waited = True
|
||||||
|
return False, self.exit_code, self.exit_info
|
||||||
|
|
||||||
def isalive(self):
|
def isalive(self):
|
||||||
"""Determine whether the child process is still running.
|
"""Determine whether the child process is still running.
|
||||||
|
|
||||||
|
@ -89,16 +119,7 @@ class Spawn(object):
|
||||||
Returns:
|
Returns:
|
||||||
Boolean indicating whether process is alive.
|
Boolean indicating whether process is alive.
|
||||||
"""
|
"""
|
||||||
|
return self.checkalive()[0]
|
||||||
if self.waited:
|
|
||||||
return False
|
|
||||||
|
|
||||||
w = os.waitpid(self.pid, os.WNOHANG)
|
|
||||||
if w[0] == 0:
|
|
||||||
return True
|
|
||||||
|
|
||||||
self.waited = True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def send(self, data):
|
def send(self, data):
|
||||||
"""Send data to the sub-process's stdin.
|
"""Send data to the sub-process's stdin.
|
||||||
|
@ -168,9 +189,20 @@ class Spawn(object):
|
||||||
events = self.poll.poll(poll_maxwait)
|
events = self.poll.poll(poll_maxwait)
|
||||||
if not events:
|
if not events:
|
||||||
raise Timeout()
|
raise Timeout()
|
||||||
c = os.read(self.fd, 1024).decode(errors='replace')
|
try:
|
||||||
if not c:
|
c = os.read(self.fd, 1024).decode(errors='replace')
|
||||||
raise EOFError()
|
except OSError as err:
|
||||||
|
# With sandbox, try to detect when U-Boot exits when it
|
||||||
|
# shouldn't and explain why. This is much more friendly than
|
||||||
|
# just dying with an I/O error
|
||||||
|
if err.errno == 5: # Input/output error
|
||||||
|
alive, exit_code, info = self.checkalive()
|
||||||
|
if alive:
|
||||||
|
raise
|
||||||
|
else:
|
||||||
|
raise ValueError('U-Boot exited with %s' % info)
|
||||||
|
else:
|
||||||
|
raise
|
||||||
if self.logfile_read:
|
if self.logfile_read:
|
||||||
self.logfile_read.write(c)
|
self.logfile_read.write(c)
|
||||||
self.buf += c
|
self.buf += c
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue