summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Reams <jbreams@mongodb.com>2016-10-14 13:11:17 -0400
committerJonathan Reams <jbreams@mongodb.com>2016-10-17 11:19:15 -0400
commit40c24abaa05450c612f00209b81d63d3c6acd35b (patch)
treea193eea66cdde7e03e0343f87f85ef3b9f3c0e6a
parent030fa6ba25c329f8ff5f29b3bbb5a95c6556115d (diff)
downloadmongo-40c24abaa05450c612f00209b81d63d3c6acd35b.tar.gz
SERVER-26596 Make sure test doesn't break other tests and fix memory leak
-rw-r--r--jstests/noPassthrough/low_js_heap_limit.js (renamed from jstests/noPassthroughWithMongod/low_js_heap_limit.js)3
-rw-r--r--src/mongo/scripting/mozjs/implscope.cpp42
-rw-r--r--src/mongo/scripting/mozjs/implscope.h7
3 files changed, 28 insertions, 24 deletions
diff --git a/jstests/noPassthroughWithMongod/low_js_heap_limit.js b/jstests/noPassthrough/low_js_heap_limit.js
index 9eb644271d4..68c28a232a4 100644
--- a/jstests/noPassthroughWithMongod/low_js_heap_limit.js
+++ b/jstests/noPassthrough/low_js_heap_limit.js
@@ -3,6 +3,9 @@
(function() {
'use strict';
+ const conn = MongoRunner.runMongod();
+ var db = conn.getDB('db');
+
assert.commandWorked(db.adminCommand({setParameter: 1, jsHeapLimitMB: 1}));
assert.commandFailedWithCode(db.runCommand({$eval: 'sleep(10000);'}),
diff --git a/src/mongo/scripting/mozjs/implscope.cpp b/src/mongo/scripting/mozjs/implscope.cpp
index a59d3016ed7..6a250c0b897 100644
--- a/src/mongo/scripting/mozjs/implscope.cpp
+++ b/src/mongo/scripting/mozjs/implscope.cpp
@@ -44,6 +44,7 @@
#include "mongo/scripting/mozjs/objectwrapper.h"
#include "mongo/scripting/mozjs/valuereader.h"
#include "mongo/scripting/mozjs/valuewriter.h"
+#include "mongo/stdx/memory.h"
#include "mongo/stdx/mutex.h"
#include "mongo/util/concurrency/threadlocal.h"
#include "mongo/util/log.h"
@@ -218,7 +219,8 @@ bool MozJSImplScope::_interruptCallback(JSContext* cx) {
}
// If we are on the right thread, in the middle of an operation, and we have a registered opCtx,
// then we should check the opCtx for interrupts.
- if ((scope->_mr._thread == PR_GetCurrentThread()) && (scope->_inOp > 0) && scope->_opCtx) {
+ if ((scope->_mr._thread.get() == PR_GetCurrentThread()) && (scope->_inOp > 0) &&
+ scope->_opCtx) {
auto status = scope->_opCtx->checkForInterruptNoAssert();
if (!status.isOK()) {
scope->_status = status;
@@ -263,7 +265,15 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) {
// without falling over.
auto thread = PR_GetCurrentThread();
if (!thread) {
- PR_BindThread(_thread = PR_CreateFakeThread());
+ _thread = std::unique_ptr<PRThread, std::function<void(PRThread*)>>(
+ PR_CreateFakeThread(), [](PRThread* ptr) {
+ if (ptr) {
+ invariant(PR_GetCurrentThread() == ptr);
+ PR_DestroyFakeThread(ptr);
+ PR_BindThread(nullptr);
+ }
+ });
+ PR_BindThread(_thread.get());
}
{
@@ -278,12 +288,13 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) {
gFirstRuntimeCreated = true;
}
- _runtime = JS_NewRuntime(kMaxBytesBeforeGC);
+ _runtime = std::unique_ptr<JSRuntime, std::function<void(JSRuntime*)>>(
+ JS_NewRuntime(kMaxBytesBeforeGC), [](JSRuntime* ptr) { JS_DestroyRuntime(ptr); });
uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSRuntime", _runtime);
// We turn on a variety of optimizations if the jit is enabled
if (engine->isJITEnabled()) {
- JS::RuntimeOptionsRef(_runtime)
+ JS::RuntimeOptionsRef(_runtime.get())
.setAsmJS(true)
.setThrowOnAsmJSValidationFailure(true)
.setBaseline(true)
@@ -318,36 +329,27 @@ MozJSImplScope::MozRuntime::MozRuntime(const MozJSScriptEngine* engine) {
const int reserve_stack_space = 64 * 1024;
#endif
- JS_SetNativeStackQuota(_runtime, available_stack_space - reserve_stack_space);
+ JS_SetNativeStackQuota(_runtime.get(), available_stack_space - reserve_stack_space);
}
// The memory limit is in megabytes
- JS_SetGCParametersBasedOnAvailableMemory(_runtime, engine->getJSHeapLimitMB());
+ JS_SetGCParametersBasedOnAvailableMemory(_runtime.get(), engine->getJSHeapLimitMB());
}
- _context = JS_NewContext(_runtime, kStackChunkSize);
+ _context = std::unique_ptr<JSContext, std::function<void(JSContext*)>>(
+ JS_NewContext(_runtime.get(), kStackChunkSize),
+ [](JSContext* ptr) { JS_DestroyContext(ptr); });
uassert(ErrorCodes::JSInterpreterFailure, "Failed to initialize JSContext", _context);
uassert(ErrorCodes::ExceededMemoryLimit,
"Out of memory while trying to initialize javascript scope",
mallocMemoryLimit == 0 || mongo::sm::get_total_bytes() < mallocMemoryLimit);
}
-MozJSImplScope::MozRuntime::~MozRuntime() {
- JS_DestroyContext(_context);
- JS_DestroyRuntime(_runtime);
-
- if (_thread) {
- invariant(PR_GetCurrentThread() == _thread);
- PR_DestroyFakeThread(_thread);
- PR_BindThread(nullptr);
- }
-}
-
MozJSImplScope::MozJSImplScope(MozJSScriptEngine* engine)
: _engine(engine),
_mr(engine),
- _runtime(_mr._runtime),
- _context(_mr._context),
+ _runtime(_mr._runtime.get()),
+ _context(_mr._context.get()),
_globalProto(_context),
_global(_globalProto.getProto()),
_funcs(),
diff --git a/src/mongo/scripting/mozjs/implscope.h b/src/mongo/scripting/mozjs/implscope.h
index d34921578b7..f6d90d1678e 100644
--- a/src/mongo/scripting/mozjs/implscope.h
+++ b/src/mongo/scripting/mozjs/implscope.h
@@ -330,11 +330,10 @@ private:
struct MozRuntime {
public:
MozRuntime(const MozJSScriptEngine* engine);
- ~MozRuntime();
- PRThread* _thread = nullptr;
- JSRuntime* _runtime = nullptr;
- JSContext* _context = nullptr;
+ std::unique_ptr<PRThread, std::function<void(PRThread*)>> _thread;
+ std::unique_ptr<JSRuntime, std::function<void(JSRuntime*)>> _runtime;
+ std::unique_ptr<JSContext, std::function<void(JSContext*)>> _context;
};
/**