Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Set memory softlimit in nogvl_context_call also #161

Merged
merged 2 commits into from Apr 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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