Skip to content

Commit

Permalink
FEATURE: Set memory softlimit in nogvl_context_call also (#161)
Browse files Browse the repository at this point in the history
* Set softlimit in nogvl_context_call also

* Set up Ruby unit test
  • Loading branch information
masongup-mdsol committed Apr 21, 2020
1 parent b457294 commit dcf1deb
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
14 changes: 14 additions & 0 deletions ext/mini_racer_extension/mini_racer_extension.cc
Expand Up @@ -127,6 +127,7 @@ typedef struct {
Local<Function> fun;
Local<Value> *argv;
EvalResult result;
size_t max_memory;
} FunctionCall;

enum IsolateFlags {
Expand Down Expand Up @@ -1454,6 +1455,12 @@ nogvl_context_call(void *args) {
// terminate ASAP
isolate->SetData(DO_TERMINATE, (void*)false);

if (call->max_memory > 0) {
isolate->SetData(MEM_SOFTLIMIT_VALUE, &call->max_memory);
isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)false);
isolate->AddGCEpilogueCallback(gc_callback);
}

Isolate::Scope isolate_scope(isolate);
EscapableHandleScope handle_scope(isolate);
TryCatch trycatch(isolate);
Expand Down Expand Up @@ -1511,6 +1518,13 @@ static VALUE rb_context_call_unsafe(int argc, VALUE *argv, VALUE self) {
call_argv = argv + 1;
}

call.max_memory = 0;
VALUE mem_softlimit = rb_iv_get(self, "@max_memory");
if (mem_softlimit != Qnil) {
unsigned long sl_int = NUM2ULONG(mem_softlimit);
call.max_memory = (size_t)sl_int;
}

bool missingFunction = false;
{
Locker lock(isolate);
Expand Down
27 changes: 27 additions & 0 deletions test/mini_racer_test.rb
Expand Up @@ -298,6 +298,33 @@ def test_max_memory
assert_raises(MiniRacer::V8OutOfMemoryError) { context.eval('let s = 1000; var a = new Array(s); a.fill(0); while(true) {s *= 1.1; let n = new Array(Math.floor(s)); n.fill(0); a = a.concat(n); };') }
end

def test_max_memory_for_call
context = MiniRacer::Context.new(max_memory: 200_000_000)
context.eval(<<~JS)
let s;
function memory_test() {
var a = new Array(s);
a.fill(0);
while(true) {
s *= 1.1;
let n = new Array(Math.floor(s));
n.fill(0);
a = a.concat(n);
if (s > 1000000) {
return;
}
}
}
function set_s(val) {
s = val;
}
JS
context.call('set_s', 1000)
assert_raises(MiniRacer::V8OutOfMemoryError) { context.call('memory_test') }
s = context.eval('s')
assert_operator(s, :>, 100_000)
end

def test_negative_max_memory
context = MiniRacer::Context.new(max_memory: -200_000_000)
assert_nil(context.instance_variable_get(:@max_memory))
Expand Down

0 comments on commit dcf1deb

Please sign in to comment.