Blob Blame History Raw

Do not disable interrupt callbacks while showing slow script dialog(s).


It is likely that a site can have more than one slow script, running simultaneously.
It seems that since 2.53.9 each such a script has its own watchdog interrupt.
And it is likely such interrupts are happen at the same or near time.

If the interrupt callbacks are disabled during the handle of the first interrupt,
other scripts seem continue to run. Such still running scripts can put a lot of things
into the main thread's event queue, which cause SpinEventLoopUntil() in
xpfe/appshell/nsXULWindow.cpp:nsXULWindow::ShowModal() to loop forever, and
the dialog window does not appear.

The assumption above is inspired by testing the case of "never appearing slow script dialog"
for the url of https://www.dw.com/de/spaniens-erster-lockdown-war-verfassungswidrig/a-58270280
(for the time of writing this text).


This solution looks safe as it only affects the slow script dialog
(and the dropped statement only exists in one another place in the entire code).
Predecessors of the dropped statement (with the same comment) was introduced in bug 477187.
E10S code use another path at all.

In practice, the ability to halt slow scripts is much preferable
to the theoretical risk of recursively invoking the interrupt callback.


--- dom/base/nsGlobalWindow.cpp.orig	2021-10-26 19:49:54.000000000 +0300
+++ dom/base/nsGlobalWindow.cpp	2021-11-23 01:53:46.594328776 +0300
@@ -11947,26 +11947,22 @@ nsGlobalWindow::ShowSlowScriptDialog(con
                           (nsIPrompt::BUTTON_POS_0 + nsIPrompt::BUTTON_POS_1));
 
   // Add a third button if necessary.
   if (showDebugButton)
     buttonFlags += nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_2;
 
   bool checkboxValue = false;
   int32_t buttonPressed = 0; // In case the user exits dialog by clicking X.
-  {
-    // Null out the operation callback while we're re-entering JS here.
-    AutoDisableJSInterruptCallback disabler(cx);
 
-    // Open the dialog.
-    rv = prompt->ConfirmEx(title.get(), msg.get(), buttonFlags,
-                           waitButton.get(), stopButton.get(),
-                           debugButton.get(), checkboxMsg.get(),
-                           &checkboxValue, &buttonPressed);
-  }
+  // Open the dialog.
+  rv = prompt->ConfirmEx(title.get(), msg.get(), buttonFlags,
+                         waitButton.get(), stopButton.get(),
+                         debugButton.get(), checkboxMsg.get(),
+                         &checkboxValue, &buttonPressed);
 
   if (buttonPressed == 0) {
     if (checkboxValue && !isAddonScript && NS_SUCCEEDED(rv))
       return AlwaysContinueSlowScript;
     return ContinueSlowScript;
   }
 
   if (buttonPressed == 2) {