Backed out 3 changesets (bug 1368072) for timeouts in test_TelemetrySession.js and test_fullscreen-api.html and unhandled "TypeError: Services.tm.mainThread.idleDispatch is not a function" promise rejections
authorPhil Ringnalda <philringnalda@gmail.com>
Tue, 20 Jun 2017 21:41:14 -0700
changeset 416209 e1e4a481b7e88dce163b9cccc2fb72032023befa
parent 416208 c55e582aee5f4dd7c28cd9820156ecd0335e4e79
child 416210 e49151136658c0d0f79b522727b807fd6cd8a79e
child 416235 d748cc75a9a9727c02a8828a196bcfc40450247f
child 416387 a4754c051537dc1b2ede96733d3e2d4a30d571df
push id1517
push userjlorenzo@mozilla.com
push dateThu, 14 Sep 2017 16:50:54 +0000
treeherdermozilla-release@3b41fd564418 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1368072
milestone56.0a1
backs out357635c84e498178cbec4d88ad814d8dab00af21
1797afe16a2a7678f46357b93399aa9952708302
4782401394a9be363d36248098fb519fdf799245
first release with
nightly linux32
e1e4a481b7e8 / 56.0a1 / 20170621100251 / files
nightly linux64
e1e4a481b7e8 / 56.0a1 / 20170621100251 / files
nightly mac
e1e4a481b7e8 / 56.0a1 / 20170621030208 / files
nightly win32
e1e4a481b7e8 / 56.0a1 / 20170621030208 / files
nightly win64
e1e4a481b7e8 / 56.0a1 / 20170621030208 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Backed out 3 changesets (bug 1368072) for timeouts in test_TelemetrySession.js and test_fullscreen-api.html and unhandled "TypeError: Services.tm.mainThread.idleDispatch is not a function" promise rejections Backed out changeset 357635c84e49 (bug 1368072) Backed out changeset 1797afe16a2a (bug 1368072) Backed out changeset 4782401394a9 (bug 1368072) MozReview-Commit-ID: 6kdcSkERjTD
browser/components/nsBrowserGlue.js
browser/components/tests/startupRecorder.js
testing/marionette/components/marionette.js
xpcom/threads/LazyIdleThread.cpp
xpcom/threads/nsIThread.idl
xpcom/threads/nsIThreadManager.idl
xpcom/threads/nsThread.cpp
xpcom/threads/nsThreadManager.cpp
xpcom/threads/nsThreadUtils.cpp
xpcom/threads/nsThreadUtils.h
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -1176,17 +1176,17 @@ BrowserGlue.prototype = {
       if (willPrompt) {
         Services.tm.dispatchToMainThread(function() {
           DefaultBrowserCheck.prompt(RecentWindow.getMostRecentBrowserWindow());
         });
       }
     }
 
     // Let's load the contextual identities.
-    Services.tm.idleDispatchToMainThread(() => {
+    Services.tm.mainThread.idleDispatch(() => {
       ContextualIdentityService.load();
     });
 
     this._sanitizer.onStartup();
     E10SAccessibilityCheck.onWindowsRestored();
   },
 
   _createExtraDefaultProfile() {
--- a/browser/components/tests/startupRecorder.js
+++ b/browser/components/tests/startupRecorder.js
@@ -63,20 +63,19 @@ startupRecorder.prototype = {
       for (let t of topics)
         Services.obs.addObserver(this, t);
       return;
     }
 
     Services.obs.removeObserver(this, topic);
 
     if (topic == "sessionstore-windows-restored") {
-      // We use idleDispatchToMainThread here to record the set of
-      // loaded scripts after we are fully done with startup and ready
-      // to react to user events.
-      Services.tm.idleDispatchToMainThread(
+      // We use idleDispatch here to record the set of loaded scripts after we
+      // are fully done with startup and ready to react to user events.
+      Services.tm.mainThread.idleDispatch(
         this.record.bind(this, "before handling user events"));
     } else {
       const topicsToNames = {
         "profile-do-change": "before profile selection",
         "toplevel-window-ready": "before opening first browser window",
       };
       topicsToNames[firstPaintNotification] = "before first paint";
       this.record(topicsToNames[topic]);
--- a/testing/marionette/components/marionette.js
+++ b/testing/marionette/components/marionette.js
@@ -246,19 +246,19 @@ MarionetteComponent.prototype.suppressSa
 };
 
 MarionetteComponent.prototype.init = function () {
   if (this.running || !this.enabled || !this.finalUIStartup) {
     return;
   }
 
   // Delay initialization until we are done with delayed startup...
-  Services.tm.idleDispatchToMainThread(() => {
+  Services.tm.mainThread.idleDispatch(() => {
     // ... and with startup tests.
-    Services.tm.idleDispatchToMainThread(() => {
+    Services.tm.mainThread.idleDispatch(() => {
       let s;
       try {
         Cu.import("chrome://marionette/content/server.js");
         s = new server.TCPListener(prefs.port);
         s.start();
         this.logger.info(`Listening on port ${s.port}`);
       } finally {
         if (s) {
--- a/xpcom/threads/LazyIdleThread.cpp
+++ b/xpcom/threads/LazyIdleThread.cpp
@@ -508,16 +508,22 @@ LazyIdleThread::HasPendingEvents(bool* a
 
 NS_IMETHODIMP
 LazyIdleThread::IdleDispatch(already_AddRefed<nsIRunnable> aEvent)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
+LazyIdleThread::IdleDispatchFromScript(nsIRunnable* aEvent)
+{
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+NS_IMETHODIMP
 LazyIdleThread::RegisterIdlePeriod(already_AddRefed<nsIIdlePeriod> aIdlePeriod)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
 NS_IMETHODIMP
 LazyIdleThread::ProcessNextEvent(bool aMayWait,
                                  bool* aEventWasProcessed)
--- a/xpcom/threads/nsIThread.idl
+++ b/xpcom/threads/nsIThread.idl
@@ -145,17 +145,32 @@ interface nsIThread : nsISerialEventTarg
    *   NOTE that the event will be leaked if it fails to dispatch.
    *
    * @throws NS_ERROR_INVALID_ARG
    *   Indicates that event is null.
    * @throws NS_ERROR_UNEXPECTED
    *   Indicates that the thread is shutting down and has finished processing
    * events, so this event would never run and has not been dispatched.
    */
-  [noscript] void idleDispatch(in alreadyAddRefed_nsIRunnable event);
+  [noscript, binaryname(IdleDispatch)] void idleDispatchFromC(in alreadyAddRefed_nsIRunnable event);
+
+  /**
+   * Dispatch an event to the thread's idle queue.  This function may be called
+   * from any thread, and it may be called re-entrantly.
+   *
+   * @param event
+   *   The (raw) event to dispatch.
+   *
+   * @throws NS_ERROR_INVALID_ARG
+   *   Indicates that event is null.
+   * @throws NS_ERROR_UNEXPECTED
+   *   Indicates that the thread is shutting down and has finished processing
+   * events, so this event would never run and has not been dispatched.
+   */
+  [binaryname(IdleDispatchFromScript)] void idleDispatch(in nsIRunnable event);
 
   /**
    * Use this attribute to dispatch runnables to the thread. Eventually, the
    * eventTarget attribute will be the only way to dispatch events to a
    * thread--nsIThread will no longer inherit from nsIEventTarget.
    */
   readonly attribute nsIEventTarget eventTarget;
 
--- a/xpcom/threads/nsIThreadManager.idl
+++ b/xpcom/threads/nsIThreadManager.idl
@@ -85,23 +85,9 @@ interface nsIThreadManager : nsISupports
    * This queues a runnable to the main thread. It's a shortcut for JS callers
    * to be used instead of
    *   .mainThread.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
    * or
    *   .currentThread.dispatch(runnable, Ci.nsIEventTarget.DISPATCH_NORMAL);
    * C++ callers should instead use NS_DispatchToMainThread.
    */
   void dispatchToMainThread(in nsIRunnable event);
-
-  /**
-   * This queues a runnable to the main thread's idle queue.
-   *
-   * @param event
-   *   The event to dispatch.
-   * @param timeout
-   *   The time in milliseconds until this event should be moved from the idle
-   *   queue to the regular queue if it hasn't been executed by then.  If not
-   *   passed or a zero value is specified, the event will never be moved to
-   *   the regular queue.
-   */
-  void idleDispatchToMainThread(in nsIRunnable event,
-                                [optional] in uint32_t timeout);
 };
--- a/xpcom/threads/nsThread.cpp
+++ b/xpcom/threads/nsThread.cpp
@@ -1157,16 +1157,23 @@ nsThread::IdleDispatch(already_AddRefed<
     NS_WARNING("An idle event was posted to a thread that will never run it (rejected)");
     return NS_ERROR_UNEXPECTED;
   }
 
   mIdleEvents.PutEvent(event.take(), lock);
   return NS_OK;
 }
 
+NS_IMETHODIMP
+nsThread::IdleDispatchFromScript(nsIRunnable* aEvent)
+{
+  nsCOMPtr<nsIRunnable> event(aEvent);
+  return IdleDispatch(event.forget());
+}
+
 #ifdef MOZ_CANARY
 void canary_alarm_handler(int signum);
 
 class Canary
 {
   //XXX ToDo: support nested loops
 public:
   Canary()
--- a/xpcom/threads/nsThreadManager.cpp
+++ b/xpcom/threads/nsThreadManager.cpp
@@ -258,17 +258,17 @@ nsThreadManager::NewThread(uint32_t aCre
 }
 
 NS_IMETHODIMP
 nsThreadManager::NewNamedThread(const nsACString& aName,
                                 uint32_t aStackSize,
                                 nsIThread** aResult)
 {
   // Note: can be called from arbitrary threads
-
+  
   // No new threads during Shutdown
   if (NS_WARN_IF(!mInitialized)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   RefPtr<nsThread> thr = new nsThread(nsThread::NOT_MAIN_THREAD, aStackSize);
   nsresult rv = thr->Init(aName);  // Note: blocks until the new thread has been set up
   if (NS_FAILED(rv)) {
@@ -362,23 +362,8 @@ nsThreadManager::DispatchToMainThread(ns
 
   // Keep this functioning during Shutdown
   if (NS_WARN_IF(!mMainThread)) {
     return NS_ERROR_NOT_INITIALIZED;
   }
 
   return mMainThread->DispatchFromScript(aEvent, 0);
 }
-
-NS_IMETHODIMP
-nsThreadManager::IdleDispatchToMainThread(nsIRunnable *aEvent, uint32_t aTimeout)
-{
-  // Note: C++ callers should instead use NS_IdleDispatchToThread or
-  // NS_IdleDispatchToCurrentThread.
-  MOZ_ASSERT(NS_IsMainThread());
-
-  nsCOMPtr<nsIRunnable> event(aEvent);
-  if (aTimeout) {
-    return NS_IdleDispatchToThread(event.forget(), aTimeout, mMainThread);
-  }
-
-  return NS_IdleDispatchToThread(event.forget(), mMainThread);
-}
--- a/xpcom/threads/nsThreadUtils.cpp
+++ b/xpcom/threads/nsThreadUtils.cpp
@@ -274,46 +274,47 @@ NS_DelayedDispatchToCurrentThread(alread
     return rv;
   }
 #endif
 
   return thread->DelayedDispatch(event.forget(), aDelayMs);
 }
 
 nsresult
-NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
-                        nsIThread* aThread)
+NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
 {
   nsresult rv;
   nsCOMPtr<nsIRunnable> event(aEvent);
   NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
-  if (!aThread) {
+#ifdef MOZILLA_INTERNAL_API
+  nsIThread* thread = NS_GetCurrentThread();
+  if (!thread) {
     return NS_ERROR_UNEXPECTED;
   }
+#else
+  nsCOMPtr<nsIThread> thread;
+  rv = NS_GetCurrentThread(getter_AddRefs(thread));
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+#endif
   // To keep us from leaking the runnable if dispatch method fails,
   // we grab the reference on failures and release it.
   nsIRunnable* temp = event.get();
-  rv = aThread->IdleDispatch(event.forget());
+  rv = thread->IdleDispatch(event.forget());
   if (NS_WARN_IF(NS_FAILED(rv))) {
     // Dispatch() leaked the reference to the event, but due to caller's
     // assumptions, we shouldn't leak here. And given we are on the same
     // thread as the dispatch target, it's mostly safe to do it here.
     NS_RELEASE(temp);
   }
 
   return rv;
 }
 
-nsresult
-NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent)
-{
-  return NS_IdleDispatchToThread(Move(aEvent),
-                                 NS_GetCurrentThread());
-}
-
 class IdleRunnableWrapper : public IdleRunnable
 {
 public:
   explicit IdleRunnableWrapper(already_AddRefed<nsIRunnable>&& aEvent)
     : mRunnable(Move(aEvent))
   {
   }
 
@@ -359,19 +360,18 @@ private:
     }
   }
 
   nsCOMPtr<nsITimer> mTimer;
   nsCOMPtr<nsIRunnable> mRunnable;
 };
 
 extern nsresult
-NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
-                        uint32_t aTimeout,
-                        nsIThread* aThread)
+NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent,
+                               uint32_t aTimeout)
 {
   nsCOMPtr<nsIRunnable> event(Move(aEvent));
   NS_ENSURE_TRUE(event, NS_ERROR_INVALID_ARG);
 
   //XXX Using current thread for now as the nsIEventTarget.
   nsIEventTarget* target = mozilla::GetCurrentThreadEventTarget();
   if (!target) {
     return NS_ERROR_UNEXPECTED;
@@ -381,25 +381,17 @@ NS_IdleDispatchToThread(already_AddRefed
 
   if (!idleEvent) {
     idleEvent = new IdleRunnableWrapper(event.forget());
     event = do_QueryInterface(idleEvent);
     MOZ_DIAGNOSTIC_ASSERT(event);
   }
   idleEvent->SetTimer(aTimeout, target);
 
-  return NS_IdleDispatchToThread(event.forget(), aThread);
-}
-
-extern nsresult
-NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent,
-                               uint32_t aTimeout)
-{
-  return NS_IdleDispatchToThread(Move(aEvent), aTimeout,
-                                 NS_GetCurrentThread());
+  return NS_IdleDispatchToCurrentThread(event.forget());
 }
 
 #ifndef XPCOM_GLUE_AVOID_NSPR
 nsresult
 NS_ProcessPendingEvents(nsIThread* aThread, PRIntervalTime aTimeout)
 {
   nsresult rv = NS_OK;
 
--- a/xpcom/threads/nsThreadUtils.h
+++ b/xpcom/threads/nsThreadUtils.h
@@ -147,58 +147,16 @@ NS_IdleDispatchToCurrentThread(already_A
  * @returns NS_ERROR_INVALID_ARG
  *   If event is null.
  * @returns NS_ERROR_UNEXPECTED
  *   If the thread is shutting down.
  */
 extern nsresult
 NS_IdleDispatchToCurrentThread(already_AddRefed<nsIRunnable>&& aEvent, uint32_t aTimeout);
 
-/**
- * Dispatch the given event to the idle queue of a thread.
- *
- * @param aEvent The event to dispatch.
- *
- * @param aThread The target thread for the dispatch.
- *
- * @returns NS_ERROR_INVALID_ARG
- *   If event is null.
- * @returns NS_ERROR_UNEXPECTED
- *   If the thread is shutting down.
- */
-extern nsresult
-NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
-                        nsIThread* aThread);
-
-/**
- * Dispatch the given event to the idle queue of a thread.
- *
- * @param aEvent The event to dispatch. If the event implements
- *   nsIIdleRunnable, it will receive a call on
- *   nsIIdleRunnable::SetTimer when dispatched, with the value of
- *   aTimeout.
- *
- * @param aTimeout The time in milliseconds until the event should be
- *   moved from the idle queue to the regular queue, if it hasn't been
- *   executed. If aEvent is also an nsIIdleRunnable, it is expected
- *   that it should handle the timeout itself, after a call to
- *   nsIIdleRunnable::SetTimer.
- *
- * @param aThread The target thread for the dispatch.
- *
- * @returns NS_ERROR_INVALID_ARG
- *   If event is null.
- * @returns NS_ERROR_UNEXPECTED
- *   If the thread is shutting down.
- */
-extern nsresult
-NS_IdleDispatchToThread(already_AddRefed<nsIRunnable>&& aEvent,
-                        uint32_t aTimeout,
-                        nsIThread* aThread);
-
 #ifndef XPCOM_GLUE_AVOID_NSPR
 /**
  * Process all pending events for the given thread before returning.  This
  * method simply calls ProcessNextEvent on the thread while HasPendingEvents
  * continues to return true and the time spent in NS_ProcessPendingEvents
  * does not exceed the given timeout value.
  *
  * @param aThread