Bug 1320380 - Rethrow exception in case of socket failures and no application instance available. r=automatedtester
authorHenrik Skupin <mail@hskupin.info>
Tue, 29 Nov 2016 12:18:18 +0100
changeset 324864 7a1bee2d23ac31bc03ed9742abf881a50cbbf580
parent 324863 f707a43789429c4bae74eb50ead0272d7b36da95
child 324865 9953c71eb9ba58bbfe818e2fae47ac44f9e868e2
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
Bug 1320380 - Rethrow exception in case of socket failures and no application instance available. r=automatedtester MozReview-Commit-ID: D0sQXTuZoPI
--- 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):
     def _(*args, **kwargs):
             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'
                         message = 'Process crashed (Exit code: {returncode})'
                     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
     def convert_keys(*string):
         typing = []
         for val in string:
             if isinstance(val, Keys):