avocado.core.runner: Fix problems with exceptions that can't be pickled

I've noticed this when writing tests using the boto3 (Amazon
AWS) API - for some exceptions, not all the arguments of the
exception can be pickled, leading to the following crash:

    (1/2) scylla_longevity.py:LongevityTest.test_20_minutes: -
    Avocado crashed: TypeError: ('__init__() takes exactly 3 arguments (2 given)', <class 'botocore.exceptions.ClientError'>, ("An error occurred (InvalidAMIID.NotFound) when calling the RunInstances operation: The image id 'ami-20776841' does not exist",))
    Traceback (most recent call last):

     File "/home/lmr/Code/avocado.lmr/avocado/core/job.py", line 451, in _run
       timeout=self.timeout)

     File "/home/lmr/Code/avocado.lmr/avocado/core/runner.py", line 368, in run_suite
       deadline)

     File "/home/lmr/Code/avocado.lmr/avocado/core/runner.py", line 284, in run_test
       if test_status.interrupt:

     File "/home/lmr/Code/avocado.lmr/avocado/core/runner.py", line 82, in __getattribute__
       self._tick()

     File "/home/lmr/Code/avocado.lmr/avocado/core/runner.py", line 111, in _tick
       msg = self.queue.get()

     File "/usr/lib/python2.7/multiprocessing/queues.py", line 378, in get
       return recv()

    TypeError: ('__init__() takes exactly 3 arguments (2 given)', <class 'botocore.exceptions.ClientError'>, ("An error occurred (InvalidAMIID.NotFound) when calling the RunInstances operation: The image id 'ami-20776841' does not exist",))

    Please include the traceback info and command line used on your bug report
    Report bugs visiting https://github.com/avocado-framework/avocado/issues/new

Since we can't restore all the arguments of this exception
upon recv, we have to handle any exception that happens
here and break out from the _tick() loop.
Signed-off-by: NLucas Meneghel Rodrigues <lookkas@gmail.com>
上级 98d69535
......@@ -52,6 +52,26 @@ class TestStatus(object):
self.status = {}
self.interrupt = None
def _get_msg_from_queue(self):
"""
Helper method to handle safely getting messages from the queue.
:return: Message, None if exception happened.
:rtype: dict
"""
try:
return self.queue.get()
# Let's catch all exceptions, since errors here mean a
# crash in avocado.
except Exception, details:
e_msg = ("\nError receiving message from test: %s -> %s" %
(details.__class__, details))
self.job.view.notify(event="error",
msg=e_msg)
stacktrace.log_exc_info(sys.exc_info(),
'avocado.app.tracebacks')
return None
@property
def early_status(self):
"""
......@@ -62,7 +82,9 @@ class TestStatus(object):
else:
queue = []
while not self.queue.empty():
msg = self.queue.get()
msg = self._get_msg_from_queue()
if msg is None:
break
if "early_status" in msg:
self._early_status = msg
for _ in queue: # Return all unprocessed messages back
......@@ -108,7 +130,9 @@ class TestStatus(object):
Process the queue and update current status
"""
while not self.queue.empty():
msg = self.queue.get()
msg = self._get_msg_from_queue()
if msg is None:
break
if "func_at_exit" in msg:
self.job.funcatexit.register(msg["func_at_exit"],
msg.get("args", tuple()),
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册