rusty_v8 TryCatch 未捕获堆限制

问题描述 投票:0回答:1

我正在尝试捕获超出其堆内存限制的 v8 隔离,但 v8::TryCatch 没有捕获它,而是转储 C 堆栈跟踪(如下)。

隔离物的创建方式如下:

    let platform = v8::new_default_platform(0, false).make_shared();
    v8::V8::initialize_platform(platform);
    v8::V8::initialize();

    {
        let mb = 1 << 20;
        let params = v8::CreateParams::default().heap_limits(mb, 10 * mb);

        // Create a new Isolate and make it the current one.
        let isolate = &mut v8::Isolate::new(params);

        // Create a stack-allocated handle scope.
        let handle_scope = &mut v8::HandleScope::new(isolate);

        // Create a new context.
        let context = v8::Context::new(handle_scope);

        // Enter the context for compiling and running scripts.
        let scope = &mut v8::ContextScope::new(handle_scope, context);
        let mut scope = v8::TryCatch::new(scope);

// ... more code
}

执行方式如下:

// Create a string containing the JavaScript source code for MyClass.
        let c_source = r#"
            class MyClass {
                multiply(a, b) {
                    let z = []
                    while (true) {
                        z.push("THIS IS A VERY LONG STRING")
                    }
                    return a * b;
                }

                testQuery() {
                    let a = query("SELECT * FROM data", [1, 2.1, 'test', true]);
                    console.log("hey", a)
                    console.error("hey", JSON.stringify(a), JSON.parse(JSON.stringify(a)))
                }
            }
            this.MyClass = MyClass;"#;

        let source = v8::String::new(&mut scope, c_source).unwrap();

        // Compile the source code.
        let script = v8::Script::compile(&mut scope, source, None).unwrap();

        // Run the script to define the class.
        script.run(&mut scope).unwrap();

        // Get the MyClass constructor from the global object.
        let global = context.global(&mut scope);
        let key = v8::String::new(&mut scope, "MyClass").unwrap();
        let class_value = global.get(&mut scope, key.into()).unwrap();

        // Ensure it's a function (constructor).
        if !class_value.is_function() {
            panic!("MyClass is not a function");
        }

        let class_constructor = v8::Local::<v8::Function>::try_from(class_value).unwrap();

        // Create an instance of MyClass.
        let instance = class_constructor.new_instance(&mut scope, &[]).unwrap();

        // Get the multiply method from the instance.
        let multiply_key = v8::String::new(&mut scope, "multiply").unwrap();
        let multiply_value = instance.get(&mut scope, multiply_key.into()).unwrap();

        // Ensure it's a function.
        if !multiply_value.is_function() {
            panic!("multiply is not a function");
        }

        let multiply_fn = v8::Local::<v8::Function>::try_from(multiply_value).unwrap();

        // Now we can call the `multiply` method on the instance from Rust.
        let arg1 = v8::Number::new(&mut scope, 3.0);
        let arg2 = v8::Number::new(&mut scope, 4.0);
        let args = &[arg1.into(), arg2.into()];
        let result = match multiply_fn.call(&mut scope, instance.into(), args) {
            Some(result) => {
                println!("result");
                result
            },
            None => {
                panic!("SOMETHING BAD")
            }
        };

当我

cargo run
我得到:

<--- Last few GCs --->

[94083:0x130008000]       51 ms: Mark-Compact 12.5 (14.2) -> 7.6 (9.2) MB, pooled: 0 MB, 10.54 / 0.00 ms  (average mu = 0.242, current mu = 0.159) allocation failure; scavenge might not succeed
[94083:0x130008000]       68 ms: Mark-Compact 18.7 (20.4) -> 11.3 (13.0) MB, pooled: 0 MB, 13.96 / 0.00 ms  (average mu = 0.192, current mu = 0.154) allocation failure; scavenge might not succeed


<--- JS stacktrace --->



#
# Fatal JavaScript out of memory: Reached heap limit
#
==== C stack trace ===============================

    0   rust_v8                             0x0000000104782b38 v8::base::debug::StackTrace::StackTrace() + 24
    1   rust_v8                             0x0000000104787998 v8::platform::(anonymous namespace)::PrintStackTrace() + 24
    2   rust_v8                             0x0000000104778860 v8::base::FatalOOM(v8::base::OOMType, char const*) + 68
    3   rust_v8                             0x00000001047d66fc v8::internal::V8::FatalProcessOutOfMemory(v8::internal::Isolate*, char const*, v8::OOMDetails const&) + 628
    4   rust_v8                             0x0000000104978430 v8::internal::Heap::stack() + 0
    5   rust_v8                             0x0000000104976954 v8::internal::Heap::CollectGarbage(v8::internal::AllocationSpace, v8::internal::GarbageCollectionReason, v8::GCCallbackFlags) + 920
    6   rust_v8                             0x000000010496bcac v8::internal::HeapAllocator::AllocateRawWithLightRetrySlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) + 1888
    7   rust_v8                             0x000000010496c558 v8::internal::HeapAllocator::AllocateRawWithRetryOrFailSlowPath(int, v8::internal::AllocationType, v8::internal::AllocationOrigin, v8::internal::AllocationAlignment) + 52
    8   rust_v8                             0x00000001049520c0 v8::internal::Factory::AllocateRaw(int, v8::internal::AllocationType, v8::internal::AllocationAlignment) + 440
    9   rust_v8                             0x0000000104947eb8 v8::internal::FactoryBase<v8::internal::Factory>::NewFixedArray(int, v8::internal::AllocationType) + 72
    10  rust_v8                             0x0000000104ae4d88 v8::internal::(anonymous namespace)::ElementsAccessorBase<v8::internal::(anonymous namespace)::FastPackedObjectElementsAccessor, v8::internal::(anonymous namespace)::ElementsKindTraits<(v8::internal::ElementsKind)2>>::ConvertElementsWithCapacity(v8::internal::Handle<v8::internal::JSObject>, v8::internal::Handle<v8::internal::FixedArrayBase>, v8::internal::ElementsKind, unsigned int, unsigned int, unsigned int) + 156
    11  rust_v8                             0x0000000104ae3668 v8::internal::(anonymous namespace)::ElementsAccessorBase<v8::internal::(anonymous namespace)::FastPackedObjectElementsAccessor, v8::internal::(anonymous namespace)::ElementsKindTraits<(v8::internal::ElementsKind)2>>::GrowCapacity(v8::internal::Handle<v8::internal::JSObject>, unsigned int) + 236
    12  rust_v8                             0x0000000104d44064 v8::internal::Runtime_GrowArrayElements(int, unsigned long*, v8::internal::Isolate*) + 252
    13  rust_v8                             0x0000000105931834 Builtins_CEntry_Return1_ArgvOnStack_NoBuiltinExit + 84
    14  ???                                 0x000000016f6004d0 0x0 + 6163530960
    15  rust_v8                             0x0000000105893648 Builtins_JSEntryTrampoline + 168
    16  rust_v8                             0x0000000105893294 Builtins_JSEntry + 180
    17  rust_v8                             0x00000001048d5efc v8::internal::(anonymous namespace)::Invoke(v8::internal::Isolate*, v8::internal::(anonymous namespace)::InvokeParams const&) + 1828
    18  rust_v8                             0x00000001048d57a8 v8::internal::Execution::Call(v8::internal::Isolate*, v8::internal::Handle<v8::internal::Object>, v8::internal::Handle<v8::internal::Object>, int, v8::internal::Handle<v8::internal::Object>*) + 140
    19  rust_v8                             0x00000001047dcd3c v8::Function::Call(v8::Local<v8::Context>, v8::Local<v8::Value>, int, v8::Local<v8::Value>*) + 532
    20  rust_v8                             0x000000010475e108 _ZN2v88function36_$LT$impl$u20$v8..data..Function$GT$4call28_$u7b$$u7b$closure$u7d$$u7d$17he6ea0103300fadb1E + 276
    21  rust_v8                             0x00000001047509d8 _ZN2v88function36_$LT$impl$u20$v8..data..Function$GT$4call17h8aef9e084672239aE + 1076
    22  rust_v8                             0x000000010473fa30 rust_v8::main::h456c1786d30674fc + 48744
    23  rust_v8                             0x0000000104759dbc core::ops::function::FnOnce::call_once::hc25835c1f1743493 + 20
    24  rust_v8                             0x0000000104733528 std::sys_common::backtrace::__rust_begin_short_backtrace::h0b79715916e323b7 + 24
    25  rust_v8                             0x0000000104732598 _ZN3std2rt10lang_start28_$u7b$$u7b$closure$u7d$$u7d$17h410c755b067bb036E + 28
    26  rust_v8                             0x0000000105a92b7c std::rt::lang_start_internal::h0e09503d2b7f298e + 656
    27  rust_v8                             0x0000000104732564 std::rt::lang_start::h9455c4f327998a81 + 84
    28  rust_v8                             0x000000010474d5f4 main + 36
    29  dyld                                0x0000000197a660e0 start + 2360
[1]    94083 trace trap  cargo run
rust v8
1个回答
0
投票

我相信我已经解决了。

方法是首先设置一个指向isolate的

heap_limit_callback
回调:

extern "C" fn oom_handler(_: *const std::os::raw::c_char, _: &v8::OomDetails) {
            panic!("OOM! I should never happen")
        }
        isolate.set_oom_error_handler(oom_handler);

        extern "C" fn heap_limit_callback(
            data: *mut c_void,
            current_heap_limit: usize,
            _initial_heap_limit: usize,
        ) -> usize {
            let isolate = unsafe {&mut *(data as *mut v8::Isolate)};
            // murder the isolate
            let terminated = isolate.terminate_execution();
            println!("near limit! {:?}", terminated);
            current_heap_limit * 2 // give us some space to kill it
        }
        let isolate_ptr: &mut v8::Isolate = &mut isolate;

        // Cast the isolate pointer to *mut c_void
        let data: *mut c_void = isolate_ptr as *mut v8::Isolate as *mut c_void;
        isolate.add_near_heap_limit_callback(heap_limit_callback, data);

当您在隔离运行时终止它时,会发生预期的故障:

let result = match multiply_fn.call(&mut scope, instance.into(), args) {
            Some(result) => {
                println!("result");
                result
            }
            None => {
                println!("Has caught: {}, can continue: {}", scope.has_caught(), scope.can_continue());
                panic!("exiting now")
            }
        };
© www.soinside.com 2019 - 2024. All rights reserved.