From aa34a52993f971b5e8abeb620df768c470d98308 Mon Sep 17 00:00:00 2001 From: messense Date: Thu, 20 Dec 2018 11:19:56 +0800 Subject: [PATCH] Add timeout and max_memory limit support --- .../extension/mini_racer_extension.cc | 76 ++++++++++++++++--- py_mini_racer/py_mini_racer.py | 40 ++++++++-- tests/test_eval.py | 21 +++++ 3 files changed, 121 insertions(+), 16 deletions(-) diff --git a/py_mini_racer/extension/mini_racer_extension.cc b/py_mini_racer/extension/mini_racer_extension.cc index ccbc5c97..c6929451 100644 --- a/py_mini_racer/extension/mini_racer_extension.cc +++ b/py_mini_racer/extension/mini_racer_extension.cc @@ -35,6 +35,8 @@ enum BinaryTypes { type_execute_exception = 200, type_parse_exception = 201, + type_oom_exception = 202, + type_timeout_exception = 203, }; /* This is a generic store for arbitrary JSON like values. @@ -63,6 +65,8 @@ void BinaryValueFree(BinaryValue *v) { switch(v->type) { case type_execute_exception: case type_parse_exception: + case type_oom_exception: + case type_timeout_exception: case type_str_utf8: free(v->str_val); break; @@ -119,6 +123,7 @@ struct EvalResult { bool parsed; bool executed; bool terminated; + bool timed_out; Persistent* value; Persistent* message; Persistent* backtrace; @@ -144,10 +149,31 @@ typedef struct { Local* eval; useconds_t timeout; EvalResult* result; + size_t max_memory; } EvalParams; +enum IsolateFlags { + MEM_SOFTLIMIT_VALUE, + MEM_SOFTLIMIT_REACHED, +}; + static Platform* current_platform = NULL; +static void gc_callback(Isolate *isolate, GCType type, GCCallbackFlags flags) { + if((bool)isolate->GetData(MEM_SOFTLIMIT_REACHED)) return; + + size_t softlimit = *(size_t*) isolate->GetData(MEM_SOFTLIMIT_VALUE); + + HeapStatistics stats; + isolate->GetHeapStatistics(&stats); + size_t used = stats.used_heap_size(); + + if(used > softlimit) { + isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)true); + isolate->TerminateExecution(); + } +} + static void init_v8() { if (current_platform == NULL) { V8::InitializeICU(); @@ -161,6 +187,7 @@ static void* breaker(void *d) { EvalParams* data = (EvalParams*)d; usleep(data->timeout*1000); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); + data->result->timed_out = true; data->context_info->isolate->TerminateExecution(); return NULL; } @@ -178,10 +205,16 @@ static void* nogvl_context_eval(void* arg) { Context::Scope context_scope(context); + // Memory softlimit + isolate->SetData(MEM_SOFTLIMIT_VALUE, (void*)false); + // Memory softlimit hit flag + isolate->SetData(MEM_SOFTLIMIT_REACHED, (void*)false); + MaybeLocal