Bug 1403348: Add debugging assertions for more AsyncStartup failure modes. r?baku draft
authorKris Maglione <maglione.k@gmail.com>
Sun, 29 Oct 2017 18:17:34 -0700
changeset 688367 6d51c56c96251bd4a7f0e42dbd9d1211eb53a8a2
parent 688366 2e37923eab0096bc9303127659123ae323d5deaf
child 737847 3634b2e348ca38672f9deea8b50657fa86fd2fe6
push id86727
push usermaglione.k@gmail.com
push dateMon, 30 Oct 2017 01:18:49 +0000
reviewersbaku
bugs1403348
milestone58.0a1
Bug 1403348: Add debugging assertions for more AsyncStartup failure modes. r?baku Since we don't currently know where or how loading the service is failing, we need logging in two places: 1) In ServiceWorkerRegistrar, which will tell us about any JS errors that occur in the factory constructor. 2) In the XPConnect module loader, which will tell us about any JS errors which happen while loading the top-level module script. If the load fails due to a non-JS error, we'll simply get a nsresult failure code, which well be less informative, but will still tell us something about the failure mode. MozReview-Commit-ID: 1CsDegJfiho
dom/workers/ServiceWorkerRegistrar.cpp
js/xpconnect/loader/mozJSComponentLoader.cpp
--- a/dom/workers/ServiceWorkerRegistrar.cpp
+++ b/dom/workers/ServiceWorkerRegistrar.cpp
@@ -1113,50 +1113,57 @@ ServiceWorkerRegistrar::GetName(nsAStrin
 }
 
 NS_IMETHODIMP
 ServiceWorkerRegistrar::GetState(nsIPropertyBag**)
 {
   return NS_OK;
 }
 
+#define RELEASE_ASSERT_SUCCEEDED(rv, name) do { \
+    if (NS_FAILED(rv)) {                                                       \
+      if (rv == NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS) {                  \
+        if (auto* context = CycleCollectedJSContext::Get()) {                  \
+          if (nsCOMPtr<nsIException> exn = context->GetPendingException()) {   \
+            nsAutoCString msg;                                                 \
+            if (NS_SUCCEEDED(exn->GetMessageMoz(msg))) {                       \
+              MOZ_CRASH_UNSAFE_PRINTF("Failed to get " name ": %s", msg.get());\
+            }                                                                  \
+          }                                                                    \
+        }                                                                      \
+      }                                                                        \
+                                                                               \
+      nsAutoCString errorName;                                                 \
+      GetErrorName(rv, errorName);                                             \
+      MOZ_CRASH_UNSAFE_PRINTF("Failed to get " name ": %s",                    \
+                              errorName.get());                                \
+    }                                                                          \
+  } while (0)
+
+
 nsCOMPtr<nsIAsyncShutdownClient>
 ServiceWorkerRegistrar::GetShutdownPhase() const
 {
-  nsCOMPtr<nsIAsyncShutdownService> svc = services::GetAsyncShutdown();
-  MOZ_RELEASE_ASSERT(svc);
-
-  nsCOMPtr<nsIAsyncShutdownClient> client;
-  nsresult rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
+  nsresult rv;
+  nsCOMPtr<nsIAsyncShutdownService> svc = do_GetService(
+      "@mozilla.org/async-shutdown-service;1", &rv);
   // If this fails, something is very wrong on the JS side (or we're out of
   // memory), and there's no point in continuing startup. Include as much
   // information as possible in the crash report.
-  if (NS_FAILED(rv)) {
-    if (rv == NS_ERROR_XPC_JAVASCRIPT_ERROR_WITH_DETAILS) {
-      if (auto* context = CycleCollectedJSContext::Get()) {
-        if (nsCOMPtr<nsIException> exn = context->GetPendingException()) {
-          nsAutoCString msg;
-          if (NS_SUCCEEDED(exn->GetMessageMoz(msg))) {
-            MOZ_CRASH_UNSAFE_PRINTF("Failed to get profileBeforeChange shutdown blocker: %s",
-                                    msg.get());
+  RELEASE_ASSERT_SUCCEEDED(rv, "async shutdown service");
+
 
-          }
-        }
-      }
-    }
-
-    nsAutoCString errorName;
-    GetErrorName(rv, errorName);
-    MOZ_CRASH_UNSAFE_PRINTF("Failed to get profileBeforeChange shutdown blocker: %s",
-                            errorName.get());
-  }
-  MOZ_RELEASE_ASSERT(client);
+  nsCOMPtr<nsIAsyncShutdownClient> client;
+  rv = svc->GetProfileBeforeChange(getter_AddRefs(client));
+  RELEASE_ASSERT_SUCCEEDED(rv, "profileBeforeChange shutdown blocker");
   return Move(client);
 }
 
+#undef RELEASE_ASSERT_SUCCEEDED
+
 void
 ServiceWorkerRegistrar::Shutdown()
 {
   AssertIsOnBackgroundThread();
   MOZ_ASSERT(!mShuttingDown);
 
   mShuttingDown = true;
   MaybeScheduleShutdownCompleted();
--- a/js/xpconnect/loader/mozJSComponentLoader.cpp
+++ b/js/xpconnect/loader/mozJSComponentLoader.cpp
@@ -31,16 +31,17 @@
 #include "nsIJARURI.h"
 #include "nsNetUtil.h"
 #include "jsprf.h"
 #include "nsJSPrincipals.h"
 #include "nsJSUtils.h"
 #include "xpcprivate.h"
 #include "xpcpublic.h"
 #include "nsContentUtils.h"
+#include "nsReadableUtils.h"
 #include "nsXULAppAPI.h"
 #include "GeckoProfiler.h"
 #include "WrapperFactory.h"
 
 #include "AutoMemMap.h"
 #include "ScriptPreloader-inl.h"
 
 #include "mozilla/AddonPathService.h"
@@ -383,21 +384,39 @@ mozJSComponentLoader::LoadModule(FileLoc
     ModuleEntry* mod;
     if (mModules.Get(spec, &mod))
         return mod;
 
     dom::AutoJSAPI jsapi;
     jsapi.Init();
     JSContext* cx = jsapi.cx();
 
+    bool isCriticalModule = StringEndsWith(spec, NS_LITERAL_CSTRING("/nsAsyncShutdown.js"));
+
     nsAutoPtr<ModuleEntry> entry(new ModuleEntry(RootingContext::get(cx)));
-    RootedValue dummy(cx);
+    RootedValue exn(cx);
     rv = ObjectForLocation(info, file, &entry->obj, &entry->thisObjectKey,
-                           &entry->location, false, &dummy);
+                           &entry->location, isCriticalModule, &exn);
     if (NS_FAILED(rv)) {
+        // Temporary debugging assertion for bug 1403348:
+        if (isCriticalModule && !exn.isUndefined()) {
+            JSAutoCompartment ac(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<nsIComponentManager> cm;
     rv = NS_GetComponentManager(getter_AddRefs(cm));
     if (NS_FAILED(rv))
         return nullptr;