2011-02-03 Dirk Pranke <dpranke@chromium.org>
authordpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Feb 2011 03:12:36 +0000 (03:12 +0000)
committerdpranke@chromium.org <dpranke@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 4 Feb 2011 03:12:36 +0000 (03:12 +0000)
        Reviewed by Kenneth Russell.

        Update, resubmit change to bug 51572. I think the race that was
        fixed in r76703 caused the hang that caused us to roll this
        patch out before, so I'd like to try again.

        https://bugs.webkit.org/show_bug.cgi?id=51572

        * Scripts/webkitpy/layout_tests/layout_package/message_broker.py:
        * Scripts/webkitpy/layout_tests/layout_package/message_broker_unittest.py:

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@77586 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Tools/ChangeLog
Tools/Scripts/webkitpy/layout_tests/layout_package/message_broker.py
Tools/Scripts/webkitpy/layout_tests/layout_package/message_broker_unittest.py

index 8559262375c8f0dfb21b5915326f8177f2803aeb..145fd413e773a4a7797cb8984bcf0f4fcadd6b9a 100644 (file)
@@ -1,3 +1,16 @@
+2011-02-03  Dirk Pranke  <dpranke@chromium.org>
+
+        Reviewed by Kenneth Russell.
+
+        Update, resubmit change to bug 51572. I think the race that was
+        fixed in r76703 caused the hang that caused us to roll this
+        patch out before, so I'd like to try again.
+
+        https://bugs.webkit.org/show_bug.cgi?id=51572
+
+        * Scripts/webkitpy/layout_tests/layout_package/message_broker.py:
+        * Scripts/webkitpy/layout_tests/layout_package/message_broker_unittest.py:
+
 2011-02-03  Daniel Cheng  <dcheng@chromium.org>
 
         Unreviewed.
index 481c6170494856add5556eab5572b1e712b500bc..d99fced77c1d15e91b691961ea05b27dddcba5a8 100644 (file)
@@ -137,6 +137,7 @@ class MultiThreadedBroker(WorkerMessageBroker):
 
     def run_message_loop(self):
         threads = self._threads()
+        wedged_threads = set()
 
         # Loop through all the threads waiting for them to finish.
         some_thread_is_alive = True
@@ -145,11 +146,15 @@ class MultiThreadedBroker(WorkerMessageBroker):
             t = time.time()
             for thread in threads:
                 if thread.isAlive():
+                    if thread in wedged_threads:
+                        continue
+
                     some_thread_is_alive = True
                     next_timeout = thread.next_timeout()
                     if next_timeout and t > next_timeout:
                         log_wedged_worker(thread.getName(), thread.id())
                         thread.clear_next_timeout()
+                        wedged_threads.add(thread)
 
                 exception_info = thread.exception_info()
                 if exception_info is not None:
@@ -164,6 +169,9 @@ class MultiThreadedBroker(WorkerMessageBroker):
             if some_thread_is_alive:
                 time.sleep(0.01)
 
+        if wedged_threads:
+            _log.warning("All remaining threads are wedged, bailing out.")
+
     def cancel_workers(self):
         threads = self._threads()
         for thread in threads:
index 6f04fd35518a04ebd6919ff8a97613cf4c5be1f4..75ce40b25cd67da9e135732d0a2514dbb3bf57bf 100644 (file)
@@ -91,6 +91,7 @@ class TestThread(threading.Thread):
     def clear_next_timeout(self):
         self._next_timeout = None
 
+
 class TestHandler(logging.Handler):
     def __init__(self, astream):
         logging.Handler.__init__(self)
@@ -125,7 +126,12 @@ class MultiThreadedBrokerTest(unittest.TestCase):
         child_thread.start()
         started_msg = starting_queue.get()
         stopping_queue.put(msg)
-        return broker.run_message_loop()
+        res = broker.run_message_loop()
+        if msg == 'Timeout':
+            child_thread._timeout_queue.put('done')
+        child_thread.join(1.0)
+        self.assertFalse(child_thread.isAlive())
+        return res
 
     def test_basic(self):
         interrupted = self.run_one_thread('')
@@ -135,17 +141,23 @@ class MultiThreadedBrokerTest(unittest.TestCase):
         self.assertRaises(KeyboardInterrupt, self.run_one_thread, 'KeyboardInterrupt')
 
     def test_timeout(self):
+        # Because the timeout shows up as a wedged thread, this also tests
+        # log_wedged_worker().
         oc = outputcapture.OutputCapture()
-        oc.capture_output()
+        stdout, stderr = oc.capture_output()
+        logger = message_broker._log
+        astream = array_stream.ArrayStream()
+        handler = TestHandler(astream)
+        logger.addHandler(handler)
         interrupted = self.run_one_thread('Timeout')
+        stdout, stderr = oc.restore_output()
         self.assertFalse(interrupted)
-        oc.restore_output()
+        logger.handlers.remove(handler)
+        self.assertTrue('All remaining threads are wedged, bailing out.' in astream.get())
 
     def test_exception(self):
         self.assertRaises(ValueError, self.run_one_thread, 'Exception')
 
-
-class Test(unittest.TestCase):
     def test_find_thread_stack_found(self):
         id, stack = sys._current_frames().items()[0]
         found_stack = message_broker._find_thread_stack(id)
@@ -155,29 +167,6 @@ class Test(unittest.TestCase):
         found_stack = message_broker._find_thread_stack(0)
         self.assertEqual(found_stack, None)
 
-    def test_log_wedged_worker(self):
-        oc = outputcapture.OutputCapture()
-        oc.capture_output()
-        logger = message_broker._log
-        astream = array_stream.ArrayStream()
-        handler = TestHandler(astream)
-        logger.addHandler(handler)
-
-        starting_queue = Queue.Queue()
-        stopping_queue = Queue.Queue()
-        child_thread = TestThread(starting_queue, stopping_queue)
-        child_thread.start()
-        msg = starting_queue.get()
-
-        message_broker.log_wedged_worker(child_thread.getName(),
-                                         child_thread.id())
-        stopping_queue.put('')
-        child_thread.join(timeout=1.0)
-
-        self.assertFalse(astream.empty())
-        self.assertFalse(child_thread.isAlive())
-        oc.restore_output()
-
 
 if __name__ == '__main__':
     unittest.main()