diff --git a/dom/serviceworkers/ServiceWorkerRegistrar.cpp b/dom/serviceworkers/ServiceWorkerRegistrar.cpp index ef6943f62299..0aad701e7d3d 100644 --- a/dom/serviceworkers/ServiceWorkerRegistrar.cpp +++ b/dom/serviceworkers/ServiceWorkerRegistrar.cpp @@ -31,6 +31,7 @@ #include "mozilla/ResultExtensions.h" #include "mozilla/Services.h" #include "mozilla/StaticPtr.h" +#include "mozJSComponentLoader.h" #include "nsAppDirectoryServiceDefs.h" #include "nsComponentManagerUtils.h" #include "nsContentUtils.h" @@ -1212,6 +1213,7 @@ ServiceWorkerRegistrar::GetState(nsIPropertyBag** aBagOut) { #define RELEASE_ASSERT_SUCCEEDED(rv, name) \ do { \ if (NS_FAILED(rv)) { \ + mozJSComponentLoader::Get()->AnnotateCrashReport(); \ if (rv == NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS) { \ if (auto* context = CycleCollectedJSContext::Get()) { \ if (RefPtr exn = context->GetPendingException()) { \ diff --git a/dom/serviceworkers/moz.build b/dom/serviceworkers/moz.build index 0b074442d79c..7f7fac7ba724 100644 --- a/dom/serviceworkers/moz.build +++ b/dom/serviceworkers/moz.build @@ -112,6 +112,10 @@ include("/ipc/chromium/chromium-config.mozbuild") FINAL_LIBRARY = "xul" +LOCAL_INCLUDES += [ + "/js/xpconnect/loader", +] + MOCHITEST_MANIFESTS += [ "test/mochitest.ini", ] diff --git a/js/xpconnect/loader/mozJSComponentLoader.cpp b/js/xpconnect/loader/mozJSComponentLoader.cpp index a73013c8d591..db930d28e355 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.cpp +++ b/js/xpconnect/loader/mozJSComponentLoader.cpp @@ -335,6 +335,39 @@ static JSObject* ResolveModuleObjectProperty(JSContext* aCx, return aModObj; } +static mozilla::Result ReadScript( + ComponentLoaderInfo& aInfo); + +static nsresult AnnotateScriptContents(CrashReporter::Annotation aName, + const nsACString& aURI) { + ComponentLoaderInfo info(aURI); + + nsCString str; + MOZ_TRY_VAR(str, ReadScript(info)); + + // The crash reporter won't accept any strings with embedded nuls. We + // shouldn't have any here, but if we do because of data corruption, we + // still want the annotation. So replace any embedded nuls before + // annotating. + str.ReplaceSubstring("\0"_ns, "\\0"_ns); + + CrashReporter::AnnotateCrashReport(aName, str); + + return NS_OK; +} + +nsresult mozJSComponentLoader::AnnotateCrashReport() { + Unused << AnnotateScriptContents( + CrashReporter::Annotation::nsAsyncShutdownComponent, + "resource://gre/components/nsAsyncShutdown.js"_ns); + + Unused << AnnotateScriptContents( + CrashReporter::Annotation::AsyncShutdownModule, + "resource://gre/modules/AsyncShutdown.jsm"_ns); + + return NS_OK; +} + const mozilla::Module* mozJSComponentLoader::LoadModule(FileLocation& aFile) { if (!NS_IsMainThread()) { MOZ_ASSERT(false, "Don't use JS components off the main thread"); @@ -364,12 +397,34 @@ const mozilla::Module* mozJSComponentLoader::LoadModule(FileLocation& aFile) { jsapi.Init(); JSContext* cx = jsapi.cx(); + bool isCriticalModule = StringEndsWith(spec, "/nsAsyncShutdown.js"_ns); + auto entry = MakeUnique(RootingContext::get(cx)); RootedValue exn(cx); rv = ObjectForLocation(info, file, &entry->obj, &entry->thisObjectKey, - &entry->location, /* aPropagateExceptions */ false, - &exn); - NS_ENSURE_SUCCESS(rv, nullptr); + &entry->location, isCriticalModule, &exn); + if (NS_FAILED(rv)) { + // Temporary debugging assertion for bug 1403348: + if (isCriticalModule && !exn.isUndefined()) { + AnnotateCrashReport(); + + JSAutoRealm ar(cx, xpc::PrivilegedJunkScope()); + JS_WrapValue(cx, &exn); + + nsAutoCString file; + uint32_t line; + uint32_t column; + nsAutoString msg; + nsContentUtils::ExtractErrorValues(cx, exn, file, &line, &column, msg); + + NS_ConvertUTF16toUTF8 cMsg(msg); + MOZ_CRASH_UNSAFE_PRINTF( + "Failed to load module \"%s\": " + "[\"%s\" {file: \"%s\", line: %u}]", + spec.get(), cMsg.get(), file.get(), line); + } + return nullptr; + } nsCOMPtr cm; rv = NS_GetComponentManager(getter_AddRefs(cm)); diff --git a/js/xpconnect/loader/mozJSComponentLoader.h b/js/xpconnect/loader/mozJSComponentLoader.h index 665a2ae7173b..e1a85a321cda 100644 --- a/js/xpconnect/loader/mozJSComponentLoader.h +++ b/js/xpconnect/loader/mozJSComponentLoader.h @@ -74,6 +74,14 @@ class mozJSComponentLoader final : public nsIMemoryReporter { size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf); + /** + * Temporary diagnostic function for startup crashes in bug 1403348: + * + * Annotate the crash report with the contents of the async shutdown + * module/component scripts. + */ + nsresult AnnotateCrashReport(); + protected: mozJSComponentLoader(); ~mozJSComponentLoader(); diff --git a/toolkit/crashreporter/CrashAnnotations.yaml b/toolkit/crashreporter/CrashAnnotations.yaml index c8c753fcd0d6..e7186191c3f5 100644 --- a/toolkit/crashreporter/CrashAnnotations.yaml +++ b/toolkit/crashreporter/CrashAnnotations.yaml @@ -92,6 +92,19 @@ ApplicationBuildID: Product application's build ID. type: string +AsyncShutdownModule: + description: > + Holds the contents of the AsyncShutdown.js script + type: string + +AsyncShutdownTimeout: + description: > + This annotation is present if a shutdown blocker was not released in time + and the browser was crashed instead of waiting for shutdown to finish. The + condition that caused the hang is contained in the annotation. + type: string + ping: true + AvailablePageFile: description: > Available commit-space in bytes.