Title: [204253] trunk/Tools
Revision
204253
Author
commit-qu...@webkit.org
Date
2016-08-08 09:18:33 -0700 (Mon, 08 Aug 2016)

Log Message

run-webkit-tests should trigger a spindump when WebContent process is unresponsive
https://bugs.webkit.org/show_bug.cgi?id=159827

Patch by Jonathan Bedard <jbed...@apple.com> on 2016-08-08
Reviewed by Daniel Bates.

This change was spurred by a process hang which occurred between tests and did
not produce a meaningful crashlog.

* Scripts/webkitpy/port/driver.py:
(Driver._check_for_driver_crash_or_unresponsiveness): Notify test controller when finished through stdin.

 * Scripts/webkitpy/port/ios.py:
(IOSSimulatorPort):
(IOSSimulatorPort.sample_process): Attempt spindump, but use sample if spindump fails.
* Scripts/webkitpy/port/mac.py:
(MacPort):
(MacPort.sample_process): Attempt spindump, but use sample if spindump fails.

* Scripts/webkitpy/port/mac_unittest.py: Changed expected values to match spindump calls, added specific spindump test.
* Scripts/webkitpy/port/driver_unittest.py: Added dummy write function.

* WebKitTestRunner/TestController.h:
(WTR::TestController::usingServerMode): Added accessor for m_usingServerMode.
* WebKitTestRunner/TestInvocation.cpp:
(WTR::TestInvocation::dumpWebProcessUnresponsiveness): Wait for stdin before continuing when in server mode.

Modified Paths

Diff

Modified: trunk/Tools/ChangeLog (204252 => 204253)


--- trunk/Tools/ChangeLog	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/ChangeLog	2016-08-08 16:18:33 UTC (rev 204253)
@@ -1,3 +1,31 @@
+2016-08-08  Jonathan Bedard  <jbed...@apple.com>
+
+        run-webkit-tests should trigger a spindump when WebContent process is unresponsive
+        https://bugs.webkit.org/show_bug.cgi?id=159827
+
+        Reviewed by Daniel Bates.
+
+        This change was spurred by a process hang which occurred between tests and did
+        not produce a meaningful crashlog.
+
+        * Scripts/webkitpy/port/driver.py:
+        (Driver._check_for_driver_crash_or_unresponsiveness): Notify test controller when finished through stdin.
+
+         * Scripts/webkitpy/port/ios.py:
+        (IOSSimulatorPort):
+        (IOSSimulatorPort.sample_process): Attempt spindump, but use sample if spindump fails.
+        * Scripts/webkitpy/port/mac.py:
+        (MacPort):
+        (MacPort.sample_process): Attempt spindump, but use sample if spindump fails.
+
+        * Scripts/webkitpy/port/mac_unittest.py: Changed expected values to match spindump calls, added specific spindump test.
+        * Scripts/webkitpy/port/driver_unittest.py: Added dummy write function.
+
+        * WebKitTestRunner/TestController.h:
+        (WTR::TestController::usingServerMode): Added accessor for m_usingServerMode.
+        * WebKitTestRunner/TestInvocation.cpp:
+        (WTR::TestInvocation::dumpWebProcessUnresponsiveness): Wait for stdin before continuing when in server mode.
+
 2016-08-07  Dan Bernstein  <m...@apple.com>
 
         [Cocoa] Reply block leaks if the remote object doesn’t call it

Modified: trunk/Tools/Scripts/webkitpy/port/driver.py (204252 => 204253)


--- trunk/Tools/Scripts/webkitpy/port/driver.py	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/Scripts/webkitpy/port/driver.py	2016-08-08 16:18:33 UTC (rev 204253)
@@ -444,6 +444,7 @@
             if child_process_pid:
                 self._port.sample_process(child_process_name, child_process_pid)
             self.error_from_test += error_line
+            self._server_process.write('#SAMPLE FINISHED\n')
             return True
         return self.has_crashed()
 

Modified: trunk/Tools/Scripts/webkitpy/port/driver_unittest.py (204252 => 204253)


--- trunk/Tools/Scripts/webkitpy/port/driver_unittest.py	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/Scripts/webkitpy/port/driver_unittest.py	2016-08-08 16:18:33 UTC (rev 204253)
@@ -206,6 +206,9 @@
             def stop(self, timeout):
                 pass
 
+            def write(self, str):
+                pass
+
         def assert_crash(driver, error_line, crashed, name, pid, unresponsive=False):
             self.assertEqual(driver._check_for_driver_crash_or_unresponsiveness(error_line), crashed)
             self.assertEqual(driver._crashed_process_name, name)

Modified: trunk/Tools/Scripts/webkitpy/port/ios.py (204252 => 204253)


--- trunk/Tools/Scripts/webkitpy/port/ios.py	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/Scripts/webkitpy/port/ios.py	2016-08-08 16:18:33 UTC (rev 204253)
@@ -408,18 +408,29 @@
         return sample_files
 
     def sample_process(self, name, pid):
-        try:
-            hang_report = self.sample_file_path(name, pid)
-            self._executive.run_command([
-                "/usr/bin/sample",
-                pid,
-                10,
-                10,
-                "-file",
-                hang_report,
-            ])
-        except ScriptError as e:
-            _log.warning('Unable to sample process:' + str(e))
+        hang_report = self.sample_file_path(name, pid)
+        exit_status = self._executive.run_command([
+            "/usr/bin/sudo",
+            "-n",
+            "/usr/sbin/spindump",
+            pid,
+            10,
+            10,
+            "-file",
+            hang_report,
+        ], return_exit_code=True)
+        if exit_status:
+            try:
+                self._executive.run_command([
+                    "/usr/bin/sample",
+                    pid,
+                    10,
+                    10,
+                    "-file",
+                    hang_report,
+                ])
+            except ScriptError as e:
+                _log.warning('Unable to sample process:' + str(e))
 
     def _path_to_helper(self):
         binary_name = 'LayoutTestHelper'

Modified: trunk/Tools/Scripts/webkitpy/port/mac.py (204252 => 204253)


--- trunk/Tools/Scripts/webkitpy/port/mac.py	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/Scripts/webkitpy/port/mac.py	2016-08-08 16:18:33 UTC (rev 204253)
@@ -290,18 +290,29 @@
         return sample_files
 
     def sample_process(self, name, pid):
-        try:
-            hang_report = self.sample_file_path(name, pid)
-            self._executive.run_command([
-                "/usr/bin/sample",
-                pid,
-                10,
-                10,
-                "-file",
-                hang_report,
-            ])
-        except ScriptError as e:
-            _log.warning('Unable to sample process:' + str(e))
+        hang_report = self.sample_file_path(name, pid)
+        exit_status = self._executive.run_command([
+            "/usr/bin/sudo",
+            "-n",
+            "/usr/sbin/spindump",
+            pid,
+            10,
+            10,
+            "-file",
+            hang_report,
+        ], return_exit_code=True)
+        if exit_status:
+            try:
+                self._executive.run_command([
+                    "/usr/bin/sample",
+                    pid,
+                    10,
+                    10,
+                    "-file",
+                    hang_report,
+                ])
+            except ScriptError as e:
+                _log.warning('Unable to sample process:' + str(e))
 
     def _path_to_helper(self):
         binary_name = 'LayoutTestHelper'

Modified: trunk/Tools/Scripts/webkitpy/port/mac_unittest.py (204252 => 204253)


--- trunk/Tools/Scripts/webkitpy/port/mac_unittest.py	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/Scripts/webkitpy/port/mac_unittest.py	2016-08-08 16:18:33 UTC (rev 204253)
@@ -203,10 +203,23 @@
         port.stop_helper()
         oc.restore_output()
 
+    def test_spindump(self):
+
+        def logging_run_command(args):
+            print args
+
+        port = self.make_port()
+        port._executive = MockExecutive2(run_command_fn=logging_run_command)
+        expected_stdout = "['/usr/bin/sudo', '-n', '/usr/sbin/spindump', 42, 10, 10, '-file', '/mock-build/layout-test-results/test-42-sample.txt']\n"
+        OutputCapture().assert_outputs(self, port.sample_process, args=['test', 42], expected_stdout=expected_stdout)
+
     def test_sample_process(self):
 
         def logging_run_command(args):
+            if args[0] == '/usr/bin/sudo':
+                return 1
             print args
+            return 0
 
         port = self.make_port()
         port._executive = MockExecutive2(run_command_fn=logging_run_command)
@@ -213,9 +226,10 @@
         expected_stdout = "['/usr/bin/sample', 42, 10, 10, '-file', '/mock-build/layout-test-results/test-42-sample.txt']\n"
         OutputCapture().assert_outputs(self, port.sample_process, args=['test', 42], expected_stdout=expected_stdout)
 
-    def test_sample_process_throws_exception(self):
-
+    def test_sample_process_exception(self):
         def throwing_run_command(args):
+            if args[0] == '/usr/bin/sudo':
+                return 1
             raise ScriptError("MOCK script error")
 
         port = self.make_port()

Modified: trunk/Tools/WebKitTestRunner/TestController.h (204252 => 204253)


--- trunk/Tools/WebKitTestRunner/TestController.h	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/WebKitTestRunner/TestController.h	2016-08-08 16:18:33 UTC (rev 204253)
@@ -81,7 +81,7 @@
     void notifyDone();
 
     bool shouldShowWebView() const { return m_shouldShowWebView; }
-
+    bool usingServerMode() const { return m_usingServerMode; }
     void configureViewForTest(const TestInvocation&);
     
     bool beforeUnloadReturnValue() const { return m_beforeUnloadReturnValue; }

Modified: trunk/Tools/WebKitTestRunner/TestInvocation.cpp (204252 => 204253)


--- trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2016-08-08 06:05:47 UTC (rev 204252)
+++ trunk/Tools/WebKitTestRunner/TestInvocation.cpp	2016-08-08 16:18:33 UTC (rev 204253)
@@ -41,6 +41,7 @@
 #include <WebKit/WKWebsiteDataStoreRef.h>
 #include <climits>
 #include <cstdio>
+#include <unistd.h>
 #include <wtf/StdLibExtras.h>
 #include <wtf/text/CString.h>
 
@@ -189,15 +190,24 @@
 void TestInvocation::dumpWebProcessUnresponsiveness(const char* errorMessage)
 {
     fprintf(stderr, "%s", errorMessage);
-    char errorMessageToStderr[1024];
+    char buffer[1024] = { };
 #if PLATFORM(COCOA)
     pid_t pid = WKPageGetProcessIdentifier(TestController::singleton().mainWebView()->page());
-    sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast<long>(pid));
+    snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s (pid %ld)\n", TestController::webProcessName(), static_cast<long>(pid));
 #else
-    sprintf(errorMessageToStderr, "#PROCESS UNRESPONSIVE - %s\n", TestController::webProcessName());
+    snprintf(buffer, sizeof(buffer), "#PROCESS UNRESPONSIVE - %s\n", TestController::webProcessName());
 #endif
 
-    dump(errorMessage, errorMessageToStderr, true);
+    dump(errorMessage, buffer, true);
+    
+    if (!TestController::singleton().usingServerMode())
+        return;
+    
+    if (isatty(fileno(stdin)) || isatty(fileno(stderr)))
+        fputs("Grab an image of the stack, then hit enter...\n", stderr);
+    
+    if (!fgets(buffer, sizeof(buffer), stdin) || strcmp(buffer, "#SAMPLE FINISHED\n"))
+        fprintf(stderr, "Failed receive expected sample response, got:\n\t\"%s\"\nContinuing...\n", buffer);
 }
 
 void TestInvocation::dump(const char* textToStdout, const char* textToStderr, bool seenError)
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to