Bug 1355800 - Improve test web server shutdown to avoid delays. r=jmaher, a=test-only
authorGeoff Brown <gbrown@mozilla.com>
Thu, 13 Apr 2017 14:33:42 -0600
changeset 396129 8feba0be5de64ba016f30815c9026ee7d81711ed
parent 396128 29e9a1d26de8b83494ef55f63a9cfc47d8204199
child 396130 d358eac1d410c46313124b77af3a31c04eb18405
push id1468
push userasasaki@mozilla.com
push dateMon, 05 Jun 2017 19:31:07 +0000
treeherdermozilla-release@0641fc6ee9d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjmaher, test-only
bugs1355800
milestone54.0
Bug 1355800 - Improve test web server shutdown to avoid delays. r=jmaher, a=test-only This eliminates a 2 minute timeout seen at the end of Android mochitests and reftests. Attempts to shutdown the web server were failing because they were directed at IP 10.0.2.2 -- the loopback address for the Android emulator.
layout/tools/reftest/remotereftest.py
testing/mochitest/runtests.py
--- a/layout/tools/reftest/remotereftest.py
+++ b/layout/tools/reftest/remotereftest.py
@@ -1,12 +1,13 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
+from contextlib import closing
 import sys
 import os
 import time
 import tempfile
 import traceback
 import urllib2
 
 import mozdevice
@@ -53,18 +54,24 @@ class ReftestServer:
         self._utilityPath = options.utilityPath
         self._xrePath = options.xrePath
         self._profileDir = options.serverProfilePath
         self.webServer = options.remoteWebServer
         self.httpPort = options.httpPort
         self.scriptDir = scriptDir
         self.pidFile = options.pidFile
         self._httpdPath = os.path.abspath(options.httpdPath)
+        if options.remoteWebServer == "10.0.2.2":
+            # probably running an Android emulator and 10.0.2.2 will
+            # not be visible from host
+            shutdownServer = "127.0.0.1"
+        else:
+            shutdownServer = self.webServer
         self.shutdownURL = "http://%(server)s:%(port)s/server/shutdown" % {
-                           "server": self.webServer, "port": self.httpPort}
+                           "server": shutdownServer, "port": self.httpPort}
 
     def start(self):
         "Run the Refest server, returning the process ID of the server."
 
         env = self.automation.environment(xrePath=self._xrePath)
         env["XPCOM_DEBUG_BREAK"] = "warn"
         if self.automation.IS_WIN32:
             env["PATH"] = env["PATH"] + ";" + self._xrePath
@@ -114,24 +121,26 @@ class ReftestServer:
             print ("TEST-UNEXPECTED-FAIL | remotereftests.py | "
                    "Timed out while waiting for server startup.")
             self.stop()
             return 1
 
     def stop(self):
         if hasattr(self, '_process'):
             try:
-                c = urllib2.urlopen(self.shutdownURL)
-                c.read()
-                c.close()
+                with closing(urllib2.urlopen(self.shutdownURL)) as c:
+                    c.read()
 
                 rtncode = self._process.poll()
                 if (rtncode is None):
                     self._process.terminate()
             except:
+                self.automation.log.info("Failed to shutdown server at %s" %
+                                         self.shutdownURL)
+                traceback.print_exc()
                 self._process.kill()
 
 
 class RemoteReftest(RefTest):
     use_marionette = False
     remoteApp = ''
     resolver_cls = RemoteReftestResolver
 
--- a/testing/mochitest/runtests.py
+++ b/testing/mochitest/runtests.py
@@ -9,16 +9,17 @@ Runs the Mochitest test harness.
 from __future__ import with_statement
 import os
 import sys
 SCRIPT_DIR = os.path.abspath(os.path.realpath(os.path.dirname(__file__)))
 sys.path.insert(0, SCRIPT_DIR)
 
 from argparse import Namespace
 from collections import defaultdict
+from contextlib import closing
 import ctypes
 import glob
 import json
 import mozcrash
 import mozdebug
 import mozinfo
 import mozprocess
 import mozrunner
@@ -388,18 +389,24 @@ class MochitestServer(object):
             options = vars(options)
         self._log = logger
         self._keep_open = bool(options['keep_open'])
         self._utilityPath = options['utilityPath']
         self._xrePath = options['xrePath']
         self._profileDir = options['profilePath']
         self.webServer = options['webServer']
         self.httpPort = options['httpPort']
+        if options.get('remoteWebServer') == "10.0.2.2":
+            # probably running an Android emulator and 10.0.2.2 will
+            # not be visible from host
+            shutdownServer = "127.0.0.1"
+        else:
+            shutdownServer = self.webServer
         self.shutdownURL = "http://%(server)s:%(port)s/server/shutdown" % {
-            "server": self.webServer,
+            "server": shutdownServer,
             "port": self.httpPort}
         self.testPrefix = "undefined"
 
         if options.get('httpdPath'):
             self._httpdPath = options['httpdPath']
         else:
             self._httpdPath = SCRIPT_DIR
         self._httpdPath = os.path.abspath(self._httpdPath)
@@ -479,29 +486,31 @@ class MochitestServer(object):
         else:
             self._log.error(
                 "TEST-UNEXPECTED-FAIL | runtests.py | Timed out while waiting for server startup.")
             self.stop()
             sys.exit(1)
 
     def stop(self):
         try:
-            with urllib2.urlopen(self.shutdownURL) as c:
+            with closing(urllib2.urlopen(self.shutdownURL)) as c:
                 c.read()
 
             # TODO: need ProcessHandler.poll()
             # https://bugzilla.mozilla.org/show_bug.cgi?id=912285
             #      rtncode = self._process.poll()
             rtncode = self._process.proc.poll()
             if rtncode is None:
                 # TODO: need ProcessHandler.terminate() and/or .send_signal()
                 # https://bugzilla.mozilla.org/show_bug.cgi?id=912285
                 # self._process.terminate()
                 self._process.proc.terminate()
         except:
+            self._log.info("Failed to stop web server on %s" % self.shutdownURL)
+            traceback.print_exc()
             self._process.kill()
 
 
 class WebSocketServer(object):
 
     "Class which encapsulates the mod_pywebsocket server"
 
     def __init__(self, options, scriptdir, logger, debuggerInfo=None):