tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

head_watchdog.js (3469B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 //
      6 // Pref management.
      7 //
      8 
      9 var {PromiseTestUtils} = ChromeUtils.importESModule("resource://testing-common/PromiseTestUtils.sys.mjs");
     10 
     11 ///////////////////
     12 //
     13 // Whitelisting these tests.
     14 // As part of bug 1077403, the shutdown crash should be fixed.
     15 //
     16 // These tests may crash intermittently on shutdown if the DOM Promise uncaught
     17 // rejection observers are still registered when the watchdog operates.
     18 PromiseTestUtils.thisTestLeaksUncaughtRejectionsAndShouldBeFixed();
     19 
     20 var gPrefs = Cc["@mozilla.org/preferences-service;1"].getService(Ci.nsIPrefBranch);
     21 
     22 function setWatchdogEnabled(enabled) {
     23  gPrefs.setBoolPref("dom.use_watchdog", enabled);
     24 }
     25 
     26 function isWatchdogEnabled() {
     27  return gPrefs.getBoolPref("dom.use_watchdog");
     28 }
     29 
     30 function setScriptTimeout(seconds) {
     31  var oldTimeout = gPrefs.getIntPref("dom.max_script_run_time");
     32  gPrefs.setIntPref("dom.max_script_run_time", seconds);
     33  return oldTimeout;
     34 }
     35 
     36 //
     37 // Utilities.
     38 //
     39 
     40 function busyWait(ms) {
     41  var start = new Date();
     42  while ((new Date()) - start < ms) {}
     43 }
     44 
     45 function do_log_info(aMessage)
     46 {
     47  print("TEST-INFO | " + _TEST_FILE + " | " + aMessage);
     48 }
     49 
     50 // We don't use do_execute_soon, because that inserts a
     51 // do_test_{pending,finished} pair that gets screwed up when we terminate scripts
     52 // from the operation callback.
     53 function executeSoon(fn) {
     54  var tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager);
     55  tm.dispatchToMainThread({run: fn});
     56 }
     57 
     58 //
     59 // Asynchronous watchdog diagnostics.
     60 //
     61 // When running, the watchdog wakes up every second, and fires the operation
     62 // callback if the script has been running for >= the minimum script timeout.
     63 // As such, if the script timeout is 1 second, a script should never be able to
     64 // run for two seconds or longer without servicing the operation callback.
     65 // We wait 3 seconds, just to be safe.
     66 //
     67 
     68 function checkWatchdog(expectInterrupt) {
     69  var oldTimeout = setScriptTimeout(1);
     70  var lastWatchdogWakeup = Cu.getWatchdogTimestamp("WatchdogWakeup");
     71 
     72  return new Promise(resolve => {
     73    let inBusyWait = false;
     74    setInterruptCallback(function() {
     75      // If the watchdog didn't actually trigger the operation callback, ignore
     76      // this call. This allows us to test the actual watchdog behavior without
     77      // interference from other sites where we trigger the operation callback.
     78      if (lastWatchdogWakeup == Cu.getWatchdogTimestamp("WatchdogWakeup")) {
     79        return true;
     80      }
     81      if (!inBusyWait) {
     82        Assert.ok(true, "Not in busy wait, ignoring interrupt callback");
     83        return true;
     84      }
     85 
     86      Assert.ok(expectInterrupt, "Interrupt callback fired");
     87      setInterruptCallback(undefined);
     88      setScriptTimeout(oldTimeout);
     89      // Schedule the promise for resolution before we kill this script.
     90      executeSoon(resolve);
     91      return false;
     92    });
     93 
     94    executeSoon(function() {
     95      inBusyWait = true;
     96      busyWait(3000);
     97      inBusyWait = false;
     98      Assert.ok(!expectInterrupt, "Interrupt callback didn't fire");
     99      setInterruptCallback(undefined);
    100      setScriptTimeout(oldTimeout);
    101      resolve();
    102    });
    103  });
    104 }
    105 
    106 function run_test() {
    107 
    108  // Run async.
    109  do_test_pending();
    110 
    111  // Run the async function.
    112  testBody().then(() => {
    113    do_test_finished();
    114  });
    115 }