Title: [90679] trunk/Tools
Revision
90679
Author
[email protected]
Date
2011-07-09 04:21:30 -0700 (Sat, 09 Jul 2011)

Log Message

nrwt: stack traces from worker-side exceptions aren't very useful inside test-webkitpy
https://bugs.webkit.org/show_bug.cgi?id=64218

Reviewed by Eric Seidel.

Exceptions aren't picklable and can't be sent across the
manager/worker message queue without losing information. NRWT
handles this by turning the stack trace into a set of strings,
and logging the strings when we receive an exception from the
worker. However, when you are running tests and something
crashes on the worker side, test-webkitpy prints the
manager-side stack trace, which is just confusing and useless.

This patch changes the logic so that exceptions are passed
through as-is when the worker and manager are in the same
process (the --worker-model=inline option). This increases the
code paths slightly but makes crashes much more useful.

* Scripts/webkitpy/layout_tests/controllers/manager.py:
* Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py:
* Scripts/webkitpy/layout_tests/controllers/message_broker.py:
* Scripts/webkitpy/layout_tests/controllers/worker.py:
* Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (90678 => 90679)


--- trunk/Tools/ChangeLog	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/ChangeLog	2011-07-09 11:21:30 UTC (rev 90679)
@@ -1,3 +1,29 @@
+2011-07-09  Dirk Pranke  <[email protected]>
+
+        nrwt: stack traces from worker-side exceptions aren't very useful inside test-webkitpy
+        https://bugs.webkit.org/show_bug.cgi?id=64218
+
+        Reviewed by Eric Seidel.
+
+        Exceptions aren't picklable and can't be sent across the
+        manager/worker message queue without losing information. NRWT
+        handles this by turning the stack trace into a set of strings,
+        and logging the strings when we receive an exception from the
+        worker. However, when you are running tests and something
+        crashes on the worker side, test-webkitpy prints the
+        manager-side stack trace, which is just confusing and useless.
+
+        This patch changes the logic so that exceptions are passed
+        through as-is when the worker and manager are in the same
+        process (the --worker-model=inline option). This increases the
+        code paths slightly but makes crashes much more useful.
+
+        * Scripts/webkitpy/layout_tests/controllers/manager.py:
+        * Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py:
+        * Scripts/webkitpy/layout_tests/controllers/message_broker.py:
+        * Scripts/webkitpy/layout_tests/controllers/worker.py:
+        * Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py:
+
 2011-07-09  Darin Fisher  <[email protected]>
 
         Eliminate bad dependency on gfx::Point.

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py (90678 => 90679)


--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager.py	2011-07-09 11:21:30 UTC (rev 90679)
@@ -778,7 +778,7 @@
             self.cancel_workers()
             keyboard_interrupted = True
         except TestRunInterruptedException, e:
-            _log.info(e.reason)
+            _log.warning(e.reason)
             self.cancel_workers()
             interrupted = True
         except WorkerException:

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py (90678 => 90679)


--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/manager_worker_broker.py	2011-07-09 11:21:30 UTC (rev 90679)
@@ -235,7 +235,13 @@
     def yield_to_broker(self):
         self._broker.run_all_pending(MANAGER_TOPIC, self._manager_client)
 
+    def raise_exception(self, exc_info):
+        # Since the worker is in the same process as the manager, we can
+        # raise the exception directly, rather than having to send it through
+        # the queue. This allows us to preserve the traceback.
+        raise exc_info[0], exc_info[1], exc_info[2]
 
+
 if multiprocessing:
 
     class _Process(multiprocessing.Process):

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/message_broker.py (90678 => 90679)


--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/message_broker.py	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/message_broker.py	2011-07-09 11:21:30 UTC (rev 90679)
@@ -61,8 +61,11 @@
 import cPickle
 import logging
 import Queue
+import sys
 import time
+import traceback
 
+from webkitpy.common.system import stack_utils
 
 _log = logging.getLogger(__name__)
 
@@ -194,3 +197,10 @@
     def post_message(self, message_name, *message_args):
         self._broker.post_message(self._client, self._post_topic,
                                   message_name, *message_args)
+
+    def raise_exception(self, exc_info):
+        # Since tracebacks aren't picklable, send the extracted stack instead.
+        exception_type, exception_value, exception_traceback = sys.exc_info()
+        stack_utils.log_traceback(_log.debug, exception_traceback)
+        stack = traceback.extract_tb(exception_traceback)
+        self._broker.post_message(self._client, self._post_topic, 'exception', exception_type, exception_value, stack)

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py (90678 => 90679)


--- trunk/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/controllers/worker.py	2011-07-09 11:21:30 UTC (rev 90679)
@@ -32,9 +32,7 @@
 import sys
 import threading
 import time
-import traceback
 
-from webkitpy.common.system import stack_utils
 from webkitpy.layout_tests.controllers import manager_worker_broker
 from webkitpy.layout_tests.controllers import single_test_runner
 from webkitpy.layout_tests.models import test_expectations
@@ -95,23 +93,16 @@
                                      % self._name)
         except KeyboardInterrupt:
             exception_msg = ", interrupted"
-            self.post_exception()
+            self._worker_connection.raise_exception(sys.exc_info())
         except:
             exception_msg = ", exception raised"
-            self.post_exception()
+            self._worker_connection.raise_exception(sys.exc_info())
         finally:
             _log.debug("%s done with message loop%s" % (self._name, exception_msg))
             self._worker_connection.post_message('done')
             self.cleanup()
             _log.debug("%s exiting" % self._name)
 
-    def post_exception(self):
-        # Since tracebacks aren't picklable, send the extracted stack instead.
-        exception_type, exception_value, exception_traceback = sys.exc_info()
-        stack_utils.log_traceback(_log.debug, exception_traceback)
-        stack = traceback.extract_tb(exception_traceback)
-        self._worker_connection.post_message('exception', exception_type, exception_value, stack)
-
     def handle_test_list(self, src, list_name, test_list):
         start_time = time.time()
         num_tests = 0

Modified: trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py (90678 => 90679)


--- trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py	2011-07-09 10:55:19 UTC (rev 90678)
+++ trunk/Tools/Scripts/webkitpy/layout_tests/run_webkit_tests_integrationtest.py	2011-07-09 11:21:30 UTC (rev 90679)
@@ -236,9 +236,22 @@
         self.assertEqual(batch_tests_run, [])
 
     def test_exception_raised(self):
-        self.assertRaises(run_webkit_tests.WorkerException, logging_run,
+        # Exceptions raised by a worker are treated differently depending on
+        # whether they are in-process or out. inline exceptions work as normal,
+        # which allows us to get the full stack trace and traceback from the
+        # worker. The downside to this is that it could be any error, but this
+        # is actually useful in testing, which is what --worker-model=inline is
+        # usually used for.
+        #
+        # Exceptions raised in a separate process are re-packaged into
+        # WorkerExceptions, which have a string capture of the stack which can
+        # be printed, but don't display properly in the unit test exception handlers.
+        self.assertRaises(ValueError, logging_run,
             ['failures/expected/exception.html'], tests_included=True)
 
+        self.assertRaises(run_webkit_tests.WorkerException, logging_run,
+            ['--worker-model', 'processes', 'failures/expected/exception.html'], tests_included=True)
+
     def test_full_results_html(self):
         # FIXME: verify html?
         res, out, err, user = logging_run(['--full-results-html'])
@@ -325,8 +338,10 @@
     def test_run_force(self):
         # This raises an exception because we run
         # failures/expected/exception.html, which is normally SKIPped.
-        self.assertRaises(run_webkit_tests.WorkerException, logging_run, ['--force'])
 
+        # See also the comments in test_exception_raised() about ValueError vs. WorkerException.
+        self.assertRaises(ValueError, logging_run, ['--force'])
+
     def test_run_part(self):
         # Test that we actually select the right part
         tests_to_run = ['passes/error.html', 'passes/image.html', 'passes/platform_image.html', 'passes/text.html']
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to