зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1249590 - Bullet-proofing AsyncShutdown wrt exceptions;r=froydnj
While investigating bug 1248489, we discovered that some code paths in AsyncShutdown could possibly be sensitive to exceptions being thrown in unexpected places. This patch attempts to make AsyncShutdown more robust to such exceptions. MozReview-Commit-ID: 5ImL9YNVgQr --HG-- extra : rebase_source : 823ee41406f7b341750e0339dfe3d5dbaa6d0cc9
This commit is contained in:
Родитель
dcaae98769
Коммит
48f2be74e2
|
@ -188,6 +188,7 @@ nsHttpConnectionMgr::Shutdown()
|
|||
|
||||
// wait for shutdown event to complete
|
||||
while (!shutdownWrapper->mBool) {
|
||||
fprintf(stderr, "nsHttpConnectionMgr::Shutdown() ProcessNextEvent\n");
|
||||
NS_ProcessNextEvent(NS_GetCurrentThread());
|
||||
}
|
||||
|
||||
|
|
|
@ -194,6 +194,7 @@ PromiseSet.prototype = {
|
|||
* console. We therefore use dump() rather than Cu.reportError().
|
||||
*/
|
||||
function log(msg, prefix = "", error = null) {
|
||||
try {
|
||||
dump(prefix + msg + "\n");
|
||||
if (error) {
|
||||
dump(prefix + error + "\n");
|
||||
|
@ -201,6 +202,9 @@ function log(msg, prefix = "", error = null) {
|
|||
dump(prefix + error.stack + "\n");
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
dump("INTERNAL ERROR in AsyncShutdown: cannot log message.\n");
|
||||
}
|
||||
}
|
||||
const PREF_DEBUG_LOG = "toolkit.asyncshutdown.log";
|
||||
var DEBUG_LOG = false;
|
||||
|
@ -305,6 +309,7 @@ function looseTimer(delay) {
|
|||
* @return object
|
||||
*/
|
||||
function getOrigin(topFrame, filename = null, lineNumber = null, stack = null) {
|
||||
try {
|
||||
// Determine the filename and line number of the caller.
|
||||
let frame = topFrame;
|
||||
|
||||
|
@ -334,6 +339,13 @@ function getOrigin(topFrame, filename = null, lineNumber = null, stack = null) {
|
|||
lineNumber: lineNumber,
|
||||
stack: stack,
|
||||
};
|
||||
} catch (ex) {
|
||||
return {
|
||||
filename: "<internal error: could not get origin>",
|
||||
lineNumber: -1,
|
||||
stack: "<internal error: could not get origin>",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.EXPORTED_SYMBOLS = ["AsyncShutdown"];
|
||||
|
@ -512,16 +524,26 @@ Spinner.prototype = {
|
|||
// nsIObserver.observe
|
||||
observe: function() {
|
||||
let topic = this._topic;
|
||||
debug(`Starting phase ${ topic }`);
|
||||
let barrier = this._barrier;
|
||||
Services.obs.removeObserver(this, topic);
|
||||
|
||||
let satisfied = false; // |true| once we have satisfied all conditions
|
||||
let promise = this._barrier.wait({
|
||||
let promise;
|
||||
try {
|
||||
promise = this._barrier.wait({
|
||||
warnAfterMS: DELAY_WARNING_MS,
|
||||
crashAfterMS: DELAY_CRASH_MS
|
||||
});
|
||||
}).catch(
|
||||
// Additional precaution to be entirely sure that we cannot reject.
|
||||
);
|
||||
} catch (ex) {
|
||||
debug("Error waiting for notification");
|
||||
throw ex;
|
||||
}
|
||||
|
||||
// Now, spin the event loop
|
||||
debug("Spinning the event loop");
|
||||
promise.then(() => satisfied = true); // This promise cannot reject
|
||||
let thread = Services.tm.mainThread;
|
||||
while (!satisfied) {
|
||||
|
@ -597,6 +619,9 @@ function Barrier(name) {
|
|||
/**
|
||||
* The name of the barrier.
|
||||
*/
|
||||
if (typeof name != "string") {
|
||||
throw new TypeError("The name of the barrier must be a string");
|
||||
}
|
||||
this._name = name;
|
||||
|
||||
/**
|
||||
|
@ -665,13 +690,16 @@ function Barrier(name) {
|
|||
throw new TypeError("Expected an object as third argument to `addBlocker`, got " + details);
|
||||
}
|
||||
if (!this._waitForMe) {
|
||||
throw new Error(`Phase "${ this._name } is finished, it is too late to register completion condition "${ name }"`);
|
||||
throw new Error(`Phase "${ this._name }" is finished, it is too late to register completion condition "${ name }"`);
|
||||
}
|
||||
debug(`Adding blocker ${ name } for phase ${ this._name }`);
|
||||
|
||||
// Normalize the details
|
||||
|
||||
let fetchState = details.fetchState || null;
|
||||
if (fetchState != null && typeof fetchState != "function") {
|
||||
throw new TypeError("Expected a function for option `fetchState`");
|
||||
}
|
||||
let filename = details.filename || null;
|
||||
let lineNumber = details.lineNumber || null;
|
||||
let stack = details.stack || null;
|
||||
|
@ -713,7 +741,10 @@ function Barrier(name) {
|
|||
// The error should remain uncaught, to ensure that it
|
||||
// still causes tests to fail.
|
||||
Promise.reject(error);
|
||||
});
|
||||
}).catch(
|
||||
// Added as a last line of defense, in case `warn`, `this._name` or
|
||||
// `safeGetState` somehow throws an error.
|
||||
);
|
||||
|
||||
let topFrame = null;
|
||||
if (filename == null || lineNumber == null || stack == null) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче