Bug 1235677 - Add assertion to catch unsafe concurrent use of AutoEnterOOMUnsafeRegion r=terrence
--- a/js/public/Utility.h
+++ b/js/public/Utility.h
@@ -3,16 +3,17 @@
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef js_Utility_h
#define js_Utility_h
#include "mozilla/Assertions.h"
+#include "mozilla/Atomics.h"
#include "mozilla/Attributes.h"
#include "mozilla/Compiler.h"
#include "mozilla/Move.h"
#include "mozilla/Scoped.h"
#include "mozilla/TemplateLib.h"
#include "mozilla/UniquePtr.h"
#include <stdlib.h>
@@ -207,32 +208,37 @@ struct MOZ_RAII AutoEnterOOMUnsafeRegion
MOZ_NORETURN MOZ_COLD void crash(const char* reason);
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
AutoEnterOOMUnsafeRegion()
: oomEnabled_(oom::IsThreadSimulatingOOM() && oom::maxAllocations != UINT64_MAX),
oomAfter_(0)
{
if (oomEnabled_) {
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(nullptr, this));
oomAfter_ = int64_t(oom::maxAllocations) - int64_t(oom::counter);
oom::maxAllocations = UINT64_MAX;
}
}
~AutoEnterOOMUnsafeRegion() {
if (oomEnabled_) {
MOZ_ASSERT(oom::maxAllocations == UINT64_MAX);
int64_t maxAllocations = int64_t(oom::counter) + oomAfter_;
MOZ_ASSERT(maxAllocations >= 0,
"alloc count + oom limit exceeds range, your oom limit is probably too large");
oom::maxAllocations = uint64_t(maxAllocations);
+ MOZ_ALWAYS_TRUE(owner_.compareExchange(this, nullptr));
}
}
private:
+ // Used to catch concurrent use from other threads.
+ static mozilla::Atomic<AutoEnterOOMUnsafeRegion*> owner_;
+
bool oomEnabled_;
int64_t oomAfter_;
#endif
};
} /* namespace js */
static inline void* js_malloc(size_t bytes)
--- a/js/src/jsutil.cpp
+++ b/js/src/jsutil.cpp
@@ -26,16 +26,19 @@
using namespace js;
using mozilla::CeilingLog2Size;
using mozilla::PodArrayZero;
#if defined(DEBUG) || defined(JS_OOM_BREAKPOINT)
/* For OOM testing functionality in Utility.h. */
namespace js {
+
+mozilla::Atomic<AutoEnterOOMUnsafeRegion*> AutoEnterOOMUnsafeRegion::owner_;
+
namespace oom {
JS_PUBLIC_DATA(uint32_t) targetThread = 0;
JS_PUBLIC_DATA(MOZ_THREAD_LOCAL(uint32_t)) threadType;
JS_PUBLIC_DATA(uint64_t) maxAllocations = UINT64_MAX;
JS_PUBLIC_DATA(uint64_t) counter = 0;
JS_PUBLIC_DATA(bool) failAlways = true;