Bug 958897 - ssltunnel lives if mochitest killed. r=jmaher

[PATCH] Made Mochitest.runApp() clean up after itself in case of exception
This commit is contained in:
Kevin Cox 2014-03-23 10:20:32 -04:00
parent 6a0f990094
commit d31a5aa422

View File

@ -907,149 +907,152 @@ class Mochitest(MochitestUtilsMixin):
# copy env so we don't munge the caller's environment
env = env.copy()
# set process log environment variable
tmpfd, processLog = tempfile.mkstemp(suffix='pidlog')
os.close(tmpfd)
env["MOZ_PROCESS_LOG"] = processLog
# make sure we clean up after ourselves.
try:
# set process log environment variable
tmpfd, processLog = tempfile.mkstemp(suffix='pidlog')
os.close(tmpfd)
env["MOZ_PROCESS_LOG"] = processLog
if self.runSSLTunnel:
if self.runSSLTunnel:
# create certificate database for the profile
# TODO: this should really be upstreamed somewhere, maybe mozprofile
certificateStatus = self.fillCertificateDB(self.profile.profile,
certPath,
utilityPath,
xrePath)
if certificateStatus:
log.info("TEST-UNEXPECTED-FAIL | runtests.py | Certificate integration failed")
return certificateStatus
# create certificate database for the profile
# TODO: this should really be upstreamed somewhere, maybe mozprofile
certificateStatus = self.fillCertificateDB(self.profile.profile,
certPath,
utilityPath,
xrePath)
if certificateStatus:
log.info("TEST-UNEXPECTED-FAIL | runtests.py | Certificate integration failed")
return certificateStatus
# start ssltunnel to provide https:// URLs capability
ssltunnel = os.path.join(utilityPath, "ssltunnel" + bin_suffix)
ssltunnel_cfg = os.path.join(self.profile.profile, "ssltunnel.cfg")
ssltunnelProcess = mozprocess.ProcessHandler([ssltunnel, ssltunnel_cfg],
env=environment(xrePath=xrePath))
ssltunnelProcess.run()
log.info("INFO | runtests.py | SSL tunnel pid: %d", ssltunnelProcess.pid)
else:
ssltunnelProcess = None
# start ssltunnel to provide https:// URLs capability
ssltunnel = os.path.join(utilityPath, "ssltunnel" + bin_suffix)
ssltunnel_cfg = os.path.join(self.profile.profile, "ssltunnel.cfg")
ssltunnelProcess = mozprocess.ProcessHandler([ssltunnel, ssltunnel_cfg],
env=environment(xrePath=xrePath))
ssltunnelProcess.run()
log.info("INFO | runtests.py | SSL tunnel pid: %d", ssltunnelProcess.pid)
else:
ssltunnelProcess = None
if interactive:
# If an interactive debugger is attached,
# don't use timeouts, and don't capture ctrl-c.
timeout = None
signal.signal(signal.SIGINT, lambda sigid, frame: None)
if interactive:
# If an interactive debugger is attached,
# don't use timeouts, and don't capture ctrl-c.
timeout = None
signal.signal(signal.SIGINT, lambda sigid, frame: None)
# build command line
cmd = os.path.abspath(app)
args = list(extraArgs)
# TODO: mozrunner should use -foreground at least for mac
# https://bugzilla.mozilla.org/show_bug.cgi?id=916512
args.append('-foreground')
if testUrl:
if debuggerInfo and debuggerInfo['requiresEscapedArgs']:
testUrl = testUrl.replace("&", "\\&")
args.append(testUrl)
# build command line
cmd = os.path.abspath(app)
args = list(extraArgs)
# TODO: mozrunner should use -foreground at least for mac
# https://bugzilla.mozilla.org/show_bug.cgi?id=916512
args.append('-foreground')
if testUrl:
if debuggerInfo and debuggerInfo['requiresEscapedArgs']:
testUrl = testUrl.replace("&", "\\&")
args.append(testUrl)
if mozinfo.info["debug"] and not webapprtChrome:
shutdownLeaks = ShutdownLeaks(log.info)
else:
shutdownLeaks = None
if mozinfo.info["debug"] and not webapprtChrome:
shutdownLeaks = ShutdownLeaks(log.info)
else:
shutdownLeaks = None
# create an instance to process the output
outputHandler = self.OutputHandler(harness=self,
utilityPath=utilityPath,
symbolsPath=symbolsPath,
dump_screen_on_timeout=not debuggerInfo,
hide_subtests=hide_subtests,
shutdownLeaks=shutdownLeaks,
)
# create an instance to process the output
outputHandler = self.OutputHandler(harness=self,
utilityPath=utilityPath,
symbolsPath=symbolsPath,
dump_screen_on_timeout=not debuggerInfo,
hide_subtests=hide_subtests,
shutdownLeaks=shutdownLeaks,
)
def timeoutHandler():
outputHandler.log_output_buffer()
browserProcessId = outputHandler.browserProcessId
self.handleTimeout(timeout, proc, utilityPath, debuggerInfo, browserProcessId)
kp_kwargs = {'kill_on_timeout': False,
'onTimeout': [timeoutHandler]}
kp_kwargs['processOutputLine'] = [outputHandler]
def timeoutHandler():
outputHandler.log_output_buffer()
browserProcessId = outputHandler.browserProcessId
self.handleTimeout(timeout, proc, utilityPath, debuggerInfo, browserProcessId)
kp_kwargs = {'kill_on_timeout': False,
'onTimeout': [timeoutHandler]}
kp_kwargs['processOutputLine'] = [outputHandler]
# create mozrunner instance and start the system under test process
self.lastTestSeen = self.test_name
startTime = datetime.now()
# create mozrunner instance and start the system under test process
self.lastTestSeen = self.test_name
startTime = datetime.now()
# b2g desktop requires FirefoxRunner even though appname is b2g
if mozinfo.info.get('appname') == 'b2g' and mozinfo.info.get('toolkit') != 'gonk':
runner_cls = mozrunner.FirefoxRunner
else:
runner_cls = mozrunner.runners.get(mozinfo.info.get('appname', 'firefox'),
mozrunner.Runner)
runner = runner_cls(profile=self.profile,
binary=cmd,
cmdargs=args,
env=env,
process_class=mozprocess.ProcessHandlerMixin,
kp_kwargs=kp_kwargs,
)
# b2g desktop requires FirefoxRunner even though appname is b2g
if mozinfo.info.get('appname') == 'b2g' and mozinfo.info.get('toolkit') != 'gonk':
runner_cls = mozrunner.FirefoxRunner
else:
runner_cls = mozrunner.runners.get(mozinfo.info.get('appname', 'firefox'),
mozrunner.Runner)
runner = runner_cls(profile=self.profile,
binary=cmd,
cmdargs=args,
env=env,
process_class=mozprocess.ProcessHandlerMixin,
kp_kwargs=kp_kwargs,
)
# XXX work around bug 898379 until mozrunner is updated for m-c; see
# https://bugzilla.mozilla.org/show_bug.cgi?id=746243#c49
runner.kp_kwargs = kp_kwargs
# XXX work around bug 898379 until mozrunner is updated for m-c; see
# https://bugzilla.mozilla.org/show_bug.cgi?id=746243#c49
runner.kp_kwargs = kp_kwargs
# start the runner
runner.start(debug_args=debug_args,
interactive=interactive,
outputTimeout=timeout)
proc = runner.process_handler
log.info("INFO | runtests.py | Application pid: %d", proc.pid)
# start the runner
runner.start(debug_args=debug_args,
interactive=interactive,
outputTimeout=timeout)
proc = runner.process_handler
log.info("INFO | runtests.py | Application pid: %d", proc.pid)
if onLaunch is not None:
# Allow callers to specify an onLaunch callback to be fired after the
# app is launched.
# We call onLaunch for b2g desktop mochitests so that we can
# run a Marionette script after gecko has completed startup.
onLaunch()
if onLaunch is not None:
# Allow callers to specify an onLaunch callback to be fired after the
# app is launched.
# We call onLaunch for b2g desktop mochitests so that we can
# run a Marionette script after gecko has completed startup.
onLaunch()
# wait until app is finished
# XXX copy functionality from
# https://github.com/mozilla/mozbase/blob/master/mozrunner/mozrunner/runner.py#L61
# until bug 913970 is fixed regarding mozrunner `wait` not returning status
# see https://bugzilla.mozilla.org/show_bug.cgi?id=913970
status = proc.wait()
runner.process_handler = None
# wait until app is finished
# XXX copy functionality from
# https://github.com/mozilla/mozbase/blob/master/mozrunner/mozrunner/runner.py#L61
# until bug 913970 is fixed regarding mozrunner `wait` not returning status
# see https://bugzilla.mozilla.org/show_bug.cgi?id=913970
status = proc.wait()
runner.process_handler = None
if timeout is None:
didTimeout = False
else:
didTimeout = proc.didTimeout
if timeout is None:
didTimeout = False
else:
didTimeout = proc.didTimeout
# finalize output handler
outputHandler.finish(didTimeout)
# finalize output handler
outputHandler.finish(didTimeout)
# record post-test information
if status:
log.info("TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s", self.lastTestSeen, status)
else:
self.lastTestSeen = 'Main app process exited normally'
# record post-test information
if status:
log.info("TEST-UNEXPECTED-FAIL | %s | application terminated with exit code %s", self.lastTestSeen, status)
else:
self.lastTestSeen = 'Main app process exited normally'
log.info("INFO | runtests.py | Application ran for: %s", str(datetime.now() - startTime))
log.info("INFO | runtests.py | Application ran for: %s", str(datetime.now() - startTime))
# Do a final check for zombie child processes.
zombieProcesses = self.checkForZombies(processLog, utilityPath, debuggerInfo)
# Do a final check for zombie child processes.
zombieProcesses = self.checkForZombies(processLog, utilityPath, debuggerInfo)
# check for crashes
minidump_path = os.path.join(self.profile.profile, "minidumps")
crashed = mozcrash.check_for_crashes(minidump_path,
symbolsPath,
test_name=self.lastTestSeen)
# check for crashes
minidump_path = os.path.join(self.profile.profile, "minidumps")
crashed = mozcrash.check_for_crashes(minidump_path,
symbolsPath,
test_name=self.lastTestSeen)
if crashed or zombieProcesses:
status = 1
if crashed or zombieProcesses:
status = 1
# cleanup
if os.path.exists(processLog):
os.remove(processLog)
if ssltunnelProcess:
ssltunnelProcess.kill()
finally:
# cleanup
if os.path.exists(processLog):
os.remove(processLog)
if ssltunnelProcess:
ssltunnelProcess.kill()
return status