Bug 1320380 - Rethrow exception in case of socket failures and no application instance available. r=automatedtester, a=test-only
authorHenrik Skupin <mail@hskupin.info>
Tue, 29 Nov 2016 12:18:18 +0100
changeset 352788 96cc481a52a30464c10924cd3949fc10a1de4efe
parent 352787 d8d91cc4391691278e219ee8308c2e25040eac32
child 352789 5805d86370c214e853c6ab297ad3f1b98128b514
push id6795
push userjlund@mozilla.com
push dateMon, 23 Jan 2017 14:19:46 +0000
treeherdermozilla-esr52@76101b503191 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersautomatedtester, test-only
bugs1320380
milestone52.0a2
Bug 1320380 - Rethrow exception in case of socket failures and no application instance available. r=automatedtester, a=test-only MozReview-Commit-ID: D0sQXTuZoPI
testing/marionette/client/marionette_driver/decorators.py
testing/marionette/client/marionette_driver/marionette.py
--- a/testing/marionette/client/marionette_driver/decorators.py
+++ b/testing/marionette/client/marionette_driver/decorators.py
@@ -20,17 +20,17 @@ def do_process_check(func):
     @wraps(func)
     def _(*args, **kwargs):
         try:
             return func(*args, **kwargs)
         except (socket.error, socket.timeout):
             # In case of socket failures which will also include crashes of the
             # application, make sure to handle those correctly.
             m = _find_marionette_in_args(*args, **kwargs)
-            m.handle_socket_failure()
+            m._handle_socket_failure()
 
     return _
 
 
 def uses_marionette(func):
     """Decorator which creates a marionette session and deletes it
     afterwards if one doesn't already exist.
     """
--- a/testing/marionette/client/marionette_driver/marionette.py
+++ b/testing/marionette/client/marionette_driver/marionette.py
@@ -756,27 +756,35 @@ class Marionette(object):
 
         if self.instance:
             name = self.test_name or 'marionette.py'
             crash_count = self.instance.runner.check_for_crashes(test_name=name)
             self.crashed = self.crashed + crash_count
 
         return crash_count > 0
 
-    def handle_socket_failure(self):
-        """Handle socket failures for the currently running application instance.
+    def _handle_socket_failure(self):
+        """Handle socket failures for the currently connected application.
 
         If the application crashed then clean-up internal states, or in case of a content
         crash also kill the process. If there are other reasons for a socket failure,
         wait for the process to shutdown itself, or force kill it.
 
+        Please note that the method expects an exception to be handled on the current stack
+        frame, and is only called via the `@do_process_check` decorator.
+
         """
-        if self.instance:
-            exc, val, tb = sys.exc_info()
+        exc, val, tb = sys.exc_info()
 
+        # If the application hasn't been launched by Marionette no further action can be done.
+        # In such cases we simply re-throw the exception.
+        if not self.instance:
+            raise exc, val, tb
+
+        else:
             # Somehow the socket disconnected. Give the application some time to shutdown
             # itself before killing the process.
             returncode = self.instance.runner.wait(timeout=self.DEFAULT_SHUTDOWN_TIMEOUT)
 
             if returncode is None:
                 message = ('Process killed because the connection to Marionette server is '
                            'lost. Check gecko.log for errors')
                 # This will force-close the application without sending any other message.
@@ -790,18 +798,17 @@ class Marionette(object):
                         message = 'Content process crashed'
                     else:
                         message = 'Process crashed (Exit code: {returncode})'
                 else:
                     message = 'Process has been unexpectedly closed (Exit code: {returncode})'
 
                 self.delete_session(send_request=False, reset_session_id=True)
 
-            if exc:
-                message += ' (Reason: {reason})'
+            message += ' (Reason: {reason})'
 
             raise IOError, message.format(returncode=returncode, reason=val), tb
 
     @staticmethod
     def convert_keys(*string):
         typing = []
         for val in string:
             if isinstance(val, Keys):