From 3305b96ed75855158e280ba57275853179e4a80d Mon Sep 17 00:00:00 2001 From: Benjamin Smedberg Date: Tue, 10 Mar 2009 13:36:14 -0400 Subject: [PATCH] Bug 481732 - Check for crash minidumps in unit tests and dump them, if the MINIDUMP_STACKWALK path is set in the environment, r=ted --- Makefile.in | 11 ++++++----- build/automation-build.mk | 4 +++- build/automation.py.in | 29 ++++++++++++++++++++++++++++- layout/tools/reftest/runreftest.py | 7 ++++++- testing/mochitest/runtests.py.in | 8 +++++++- 5 files changed, 50 insertions(+), 9 deletions(-) diff --git a/Makefile.in b/Makefile.in index 58ed733d7bb..34a17d842ad 100644 --- a/Makefile.in +++ b/Makefile.in @@ -190,18 +190,19 @@ SYMBOL_INDEX_NAME = \ buildsymbols: ifdef MOZ_CRASHREPORTER echo building symbol store - mkdir -p $(DIST)/crashreporter-symbols/$(BUILDID) + $(RM) -rf $(DIST)/crashreporter-symbols + $(NSINSTALL) -D $(DIST)/crashreporter-symbols $(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/symbolstore.py \ $(MAKE_SYM_STORE_ARGS) \ $(foreach dir,$(SYM_STORE_SOURCE_DIRS),-s $(dir)) \ $(DUMP_SYMS_BIN) \ - $(DIST)/crashreporter-symbols/$(BUILDID) \ + $(DIST)/crashreporter-symbols \ $(MAKE_SYM_STORE_PATH) > \ - $(DIST)/crashreporter-symbols/$(BUILDID)/$(SYMBOL_INDEX_NAME) + $(DIST)/crashreporter-symbols/$(SYMBOL_INDEX_NAME) echo packing symbols mkdir -p $(topsrcdir)/../$(BUILDID) - cd $(DIST)/crashreporter-symbols/$(BUILDID) && \ - zip -r9D ../../$(SYMBOL_ARCHIVE_BASENAME).zip . + cd $(DIST)/crashreporter-symbols && \ + zip -r9D ../$(SYMBOL_ARCHIVE_BASENAME).zip . endif # MOZ_CRASHREPORTER uploadsymbols: diff --git a/build/automation-build.mk b/build/automation-build.mk index f20f04df992..f610e313988 100644 --- a/build/automation-build.mk +++ b/build/automation-build.mk @@ -22,6 +22,7 @@ endif endif _PROFILE_DIR = $(TARGET_DEPTH)/_profile/pgo +_SYMBOLS_PATH = $(TARGET_DIST)/crashreporter-symbols ifneq (,$(filter /%,$(topsrcdir))) # $(topsrcdir) is already an absolute pathname. @@ -38,6 +39,7 @@ AUTOMATION_PPARGS = \ -DBIN_SUFFIX=\"$(BIN_SUFFIX)\" \ -DPROFILE_DIR=\"$(_PROFILE_DIR)\" \ -DCERTS_SRC_DIR=\"$(_CERTS_SRC_DIR)\" \ + -DSYMBOLS_PATH=\"$(_SYMBOLS_PATH)\" \ $(NULL) ifeq ($(OS_ARCH),Darwin) @@ -68,6 +70,6 @@ else AUTOMATION_PPARGS += -DIS_DEBUG_BUILD=0 endif -automation.py: $(topsrcdir)/build/automation.py.in +automation.py: $(topsrcdir)/build/automation.py.in $(topsrcdir)/build/automation-build.mk $(PYTHON) $(topsrcdir)/config/Preprocessor.py \ $(AUTOMATION_PPARGS) $(DEFINES) $(ACDEFINES) $< > $@ diff --git a/build/automation.py.in b/build/automation.py.in index c962df88391..7f763706ba4 100644 --- a/build/automation.py.in +++ b/build/automation.py.in @@ -48,6 +48,7 @@ import signal import subprocess import sys import threading +import glob """ Runs the browser from a script, and provides useful utilities @@ -87,6 +88,7 @@ UNIXISH = not IS_WIN32 and not IS_MAC #expand CERTS_SRC_DIR = __CERTS_SRC_DIR__ #expand IS_TEST_BUILD = __IS_TEST_BUILD__ #expand IS_DEBUG_BUILD = __IS_DEBUG_BUILD__ +#expand SYMBOLS_PATH = __SYMBOLS_PATH__ ########### # LOGGING # @@ -401,8 +403,27 @@ def environment(env = None, xrePath = DIST_BIN): elif IS_WIN32: env["PATH"] = env["PATH"] + ";" + ldLibraryPath + env['MOZ_CRASHREPORTER_NO_REPORT'] = '1' + env['MOZ_CRASHREPORTER'] = '1' + return env +def checkForCrashes(profileDir, symbolsPath): + stackwalkPath = os.environ.get('MINIDUMP_STACKWALK', None) + + foundCrash = False + dumps = glob.glob(os.path.join(profileDir, 'minidumps', '*.dmp')) + for d in dumps: + log.info("TEST-UNEXPECTED-FAIL | (automation.py) | Browser crashed (minidump found)") + if symbolsPath and stackwalkPath: + nullfd = open(os.devnull, 'w') + # eat minidump_stackwalk errors + subprocess.call([stackwalkPath, d, symbolsPath], stderr=nullfd) + nullfd.close() + os.remove(d) + foundCrash = True + return foundCrash + ############### # RUN THE APP # ############### @@ -480,7 +501,10 @@ def processLeakLog(leakLogFile, leakThreshold): log.info("TEST-UNEXPECTED-FAIL | runtests-leaks | missing output line for total leaks!") leaks.close() -def runApp(testURL, env, app, profileDir, extraArgs, runSSLTunnel = False, utilityPath = DIST_BIN, xrePath = DIST_BIN, certPath = CERTS_SRC_DIR, debuggerInfo = None): +def runApp(testURL, env, app, profileDir, extraArgs, + runSSLTunnel = False, utilityPath = DIST_BIN, + xrePath = DIST_BIN, certPath = CERTS_SRC_DIR, + debuggerInfo = None, symbolsPath = SYMBOLS_PATH): "Run the app, log the duration it took to execute, return the status code." if IS_TEST_BUILD and runSSLTunnel: @@ -548,6 +572,9 @@ def runApp(testURL, env, app, profileDir, extraArgs, runSSLTunnel = False, utili log.info("TEST-UNEXPECTED-FAIL | (automation.py) | Exited with code %d during test run", status) log.info("INFO | (automation.py) | Application ran for: %s", str(datetime.now() - startTime)) + if checkForCrashes(profileDir, symbolsPath): + status = -1 + if IS_TEST_BUILD and runSSLTunnel: ssltunnelProcess.kill() diff --git a/layout/tools/reftest/runreftest.py b/layout/tools/reftest/runreftest.py index 076ec8607e4..0ef1e6990c9 100644 --- a/layout/tools/reftest/runreftest.py +++ b/layout/tools/reftest/runreftest.py @@ -84,6 +84,10 @@ def main(): action = "append", dest = "extraProfileFiles", default = [], help = "copy specified files/dirs to testing profile") + parser.add_option("--symbols-path", + action = "store", type = "string", dest = "symbolsPath", + default = automation.SYMBOLS_PATH, + help = "absolute path to directory containing breakpad symbols") options, args = parser.parse_args() if len(args) != 1: @@ -136,7 +140,8 @@ Are you executing $objdir/_tests/reftest/runreftest.py?""" \ # and then exit the app log.info("REFTEST INFO | runreftest.py | Performing extension manager registration: start.\n") status = automation.runApp(None, browserEnv, options.app, profileDir, - extraArgs = ["-silent"]) + extraArgs = ["-silent"], + symbolsPath=options.symbolsPath) # We don't care to call |processLeakLog()| for this step. log.info("\nREFTEST INFO | runreftest.py | Performing extension manager registration: end.") diff --git a/testing/mochitest/runtests.py.in b/testing/mochitest/runtests.py.in index 6525b0e967c..7a7639fa6da 100644 --- a/testing/mochitest/runtests.py.in +++ b/testing/mochitest/runtests.py.in @@ -136,6 +136,11 @@ class MochitestOptions(optparse.OptionParser): help = "absolute path to directory containing utility programs (xpcshell, ssltunnel, certutil)") defaults["utilityPath"] = automation.DIST_BIN + self.add_option("--symbols-path", + action = "store", type = "string", dest = "symbolsPath", + help = "absolute path to directory containing breakpad symbols") + defaults["symbolsPath"] = automation.SYMBOLS_PATH + self.add_option("--certificate-path", action = "store", type = "string", dest = "certPath", help = "absolute path to directory containing certificate store to use testing profile") @@ -472,7 +477,8 @@ Are you executing $objdir/_tests/testing/mochitest/runtests.py?""" utilityPath = options.utilityPath, xrePath = options.xrePath, certPath=options.certPath, - debuggerInfo=debuggerInfo) + debuggerInfo=debuggerInfo, + symbolsPath=options.symbolsPath) # Server's no longer needed, and perhaps more importantly, anything it might # spew to console shouldn't disrupt the leak information table we print next.