diff options
author | Jonathan Reams <jbreams@mongodb.com> | 2016-10-14 13:11:17 -0400 |
---|---|---|
committer | Jonathan Reams <jbreams@mongodb.com> | 2016-10-17 11:19:15 -0400 |
commit | 40c24abaa05450c612f00209b81d63d3c6acd35b (patch) | |
tree | a193eea66cdde7e03e0343f87f85ef3b9f3c0e6a | |
parent | 030fa6ba25c329f8ff5f29b3bbb5a95c6556115d (diff) | |
download | mongo-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.cpp | 42 | ||||
-rw-r--r-- | src/mongo/scripting/mozjs/implscope.h | 7 |
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; }; /** |