Bug 1282986 - Disallow creation of workers while running simulated OOM tests r=terrence
--- a/js/src/builtin/TestingFunctions.cpp
+++ b/js/src/builtin/TestingFunctions.cpp
@@ -1276,19 +1276,16 @@ OOMTest(JSContext* cx, unsigned argc, Va
if (fuzzingSafe)
expectExceptionOnFailure = false;
if (disableOOMFunctions) {
args.rval().setUndefined();
return true;
}
- MOZ_ASSERT(!cx->isExceptionPending());
- cx->runtime()->hadOutOfMemory = false;
-
RootedFunction function(cx, &args[0].toObject().as<JSFunction>());
bool verbose = EnvVarIsDefined("OOM_VERBOSE");
unsigned threadStart = oom::THREAD_TYPE_MAIN;
unsigned threadEnd = oom::THREAD_TYPE_MAX;
// Test a single thread type if specified by the OOM_THREAD environment variable.
@@ -1298,16 +1295,26 @@ OOMTest(JSContext* cx, unsigned argc, Va
JS_ReportError(cx, "OOM_THREAD value out of range.");
return false;
}
threadStart = threadOption;
threadEnd = threadOption + 1;
}
+ JSRuntime* rt = cx->runtime();
+ if (rt->runningOOMTest) {
+ JS_ReportError(cx, "Nested call to oomTest() is not allowed.");
+ return false;
+ }
+ rt->runningOOMTest = true;
+
+ MOZ_ASSERT(!cx->isExceptionPending());
+ rt->hadOutOfMemory = false;
+
JS_SetGCZeal(cx->runtime(), 0, JS_DEFAULT_ZEAL_FREQ);
for (unsigned thread = threadStart; thread < threadEnd; thread++) {
if (verbose)
fprintf(stderr, "thread %d\n", thread);
HelperThreadState().waitForAllThreads();
js::oom::targetThread = thread;
@@ -1353,16 +1360,17 @@ OOMTest(JSContext* cx, unsigned argc, Va
allocation++;
} while (handledOOM);
if (verbose) {
fprintf(stderr, " finished after %d allocations\n", allocation - 2);
}
}
+ rt->runningOOMTest = false;
args.rval().setUndefined();
return true;
}
#endif
#ifdef SPIDERMONKEY_PROMISE
static bool
SettlePromiseNow(JSContext* cx, unsigned argc, Value* vp)
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/gc/bug-1282986.js
@@ -0,0 +1,17 @@
+if (!('oomTest' in this))
+ quit();
+
+var lfLogBuffer = `
+evalInWorker(\`
+ try { oomAfterAllocations(2); } catch(e) {}
+ \`);
+`;
+loadFile("");
+loadFile(lfLogBuffer);
+function loadFile(lfVarx) {
+ oomTest(function() {
+ let m = parseModule(lfVarx);
+ m.declarationInstantiation();
+ m.evaluation();
+ });
+}
--- a/js/src/shell/js.cpp
+++ b/js/src/shell/js.cpp
@@ -3021,16 +3021,23 @@ EvalInWorker(JSContext* cx, unsigned arg
}
CallArgs args = CallArgsFromVp(argc, vp);
if (!args.get(0).isString()) {
JS_ReportError(cx, "Invalid arguments to evalInWorker");
return false;
}
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+ if (cx->runtime()->runningOOMTest) {
+ JS_ReportError(cx, "Can't create workers while running simulated OOM test");
+ return false;
+ }
+#endif
+
if (!args[0].toString()->ensureLinear(cx))
return false;
if (!workerThreadsLock) {
workerThreadsLock = js_new<Mutex>();
if (!workerThreadsLock) {
ReportOutOfMemory(cx);
return false;
--- a/js/src/vm/Runtime.cpp
+++ b/js/src/vm/Runtime.cpp
@@ -199,16 +199,19 @@ JSRuntime::JSRuntime(JSRuntime* parentRu
emptyString(nullptr),
spsProfiler(thisFromCtor()),
profilingScripts(false),
suppressProfilerSampling(false),
hadOutOfMemory(false),
#ifdef DEBUG
handlingInitFailure(false),
#endif
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+ runningOOMTest(false),
+#endif
allowRelazificationForTesting(false),
data(nullptr),
signalHandlersInstalled_(false),
canUseSignalHandlers_(false),
defaultFreeOp_(thisFromCtor()),
debuggerMutations(0),
securityCallbacks(&NullSecurityCallbacks),
DOMcallbacks(nullptr),
--- a/js/src/vm/Runtime.h
+++ b/js/src/vm/Runtime.h
@@ -1201,16 +1201,21 @@ struct JSRuntime : public JS::shadow::Ru
/* Had an out-of-memory error which did not populate an exception. */
bool hadOutOfMemory;
#ifdef DEBUG
/* We are currently deleting an object due to an initialization failure. */
bool handlingInitFailure;
#endif
+#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
+ /* We are currently running a simulated OOM test. */
+ bool runningOOMTest;
+#endif
+
/*
* Allow relazifying functions in compartments that are active. This is
* only used by the relazifyFunctions() testing function.
*/
bool allowRelazificationForTesting;
/* Linked list of all Debugger objects in the runtime. */
mozilla::LinkedList<js::Debugger> debuggerList;