代码之家  ›  专栏  ›  技术社区  ›  ddd ddd111111

为什么嵌入C++代码时异常堆栈跟踪在NodeJS中不起作用

  •  1
  • ddd ddd111111  · 技术社区  · 2 年前

    我有以下代码:

    process.on('uncaughtException', (err, origin) => {
        fs.writeFileSync("error.txt", err.toString());
    })
    f = fs.createReadStream("blah");
    f.on('data', (c) => {
           throw new Error("Test event error");
    });
    
    //OR
    setTimeout(function(){
        throw new Error("Timeout error");
    }, 2000)
    

    当我在命令行中使用运行此代码时 node 二进制的 error.txt 包含一个有用的堆栈跟踪:

    at Timeout._onTimeout (init.js:93:11)
    at listOnTimeout (node:internal/timers:573:17)
    at process.processTimers (node:internal/timers:514:7) {
    [stack]: 'Error: Timeout error\n' +
    ' at Timeout._onTimeout (init.js:93:11)\n' +
    ' at listOnTimeout (node:internal/timers:573:17)\n' +
    ' at process.processTimers (node:internal/timers:514:7)',
    [message]: 'Timeout error'
    

    但当我使用C++中的NodeJS embedder API运行完全相同的代码时,它只包含消息字符串,没有任何堆栈跟踪:

    [Error: Error thrown from setTimeout] {
    [stack]: 'Error: Error thrown from setTimeout',
    [message]: 'Error thrown from setTimeout'
    }
    

    当我做回调函数时 async ,它至少打印 init.js:93 (当 setTimeout 嵌套在另一个(我知道事件循环,但V8具有异步堆栈跟踪功能,在Chromium或 节点 命令

    我的C++代码是巨大的,然而,我制作了以下小示例代码来描述我的工作:

    
    int ret = uv_loop_init(&loop);
    if(ret != 0){
        throw LException("Failed to initialize loop: " + LString(uv_err_name(ret)));
    }
    
    v8::Isolate* isolate = node::NewIsolate(allocator, loop, platform)
    isolate->SetAbortOnUncaughtExceptionCallback([](v8::Isolate*) -> bool{
        return false; //UNCAUGHT EXCEPTION IS CAPTURED IN JS CODE (This function gets never executed, because nodeJS registers it's own callback)
    });
    
    isolate->SetPromiseRejectCallback([](v8::PromiseRejectMessage message) -> void{
        //PROMISE REJECTION STACK TRACE WORKS FINE
        ...
        ...
        ...
    });
    
    v8::Isolate::Scope isolate_scope(isolate); //Stack allocated, use every time, when an interaction with isolate is needed in local scope
    
    // Set up a new v8::Context. (used ONLY for initialization)
    
    isolate->SetCaptureStackTraceForUncaughtExceptions(true, 30);
    
    v8::HandleScope handle_scope(isolate);
    v8::Local<v8::Context> context = node::NewContext(isolate, templ);
    if (context.IsEmpty()) {
        fprintf(stderr, "%s: Failed to initialize V8 Context\n", args[0].c_str());
        return 1;
    }
        
    // The v8::Context needs to be entered when node::CreateEnvironment() and
    // node::LoadEnvironment() are being called.
    v8::Context::Scope context_scope(context);
    std::vector<std::string> errors;
    
    this->isolate_data = node::CreateIsolateData(isolate, this->getLoop(), platform, this->getDefaultIsolate()->getAllocator().get());
    this->env = node::CreateEnvironment(isolate_data, context, args, exec_args);
    
    ...
    ...
    
    v8::MaybeLocal<v8::Value> loadenv_ret = node::LoadEnvironment(env, [&](const node::StartExecutionCallbackInfo& info) -> v8::MaybeLocal<v8::Value>{
        this->intern_require = v8::Global<v8::Function>(isolate, info.native_require);
        this->process.Reset(isolate, info.process_object);
        
        v8::Local<v8::Object> octx = context->Global();
        octx->Set(context, v8::String::NewFromUtf8Literal(isolate, "process"), info.process_object);
        v8::Local<v8::String> source = v8::String::NewFromUtf8(isolate, "process.on('uncaughtException', function(err){ __lt_reportUncaughtError(err); return false; }); //  process.on('unhandledRejection', function(err, prom){ process.exit(255); __lt_reportUncaughtError(err) })").ToLocalChecked();
        v8::Local<v8::Script> script = v8::Script::Compile(context, source).ToLocalChecked();
        script->Run(context);
        return v8::Number::New(isolate, 0.0d);
    });
    
    if(loadenv_ret.IsEmpty()){  // There has been a JS exception.
        throw LException("node::LoadEnvironment returned empty result"L, "NodeInstance::init()"L);
    }
    
    ...
    ...
    
    v8::Isolate::Scope iscope(isolate->get());
    v8::HandleScope hscope(isolate->get());
    v8::Context::Scope cscope(lcontext);
    uint32_t sl = scripts.size();
    for(uint32_t i = 0; i < sl; i++){
        v8::Local<v8::Script> lscript = v8::Local<v8::Script>::New(isolate->get(), scripts[i]);
        v8::Local<v8::Context> scriptctx = v8::Local<v8::Context>::New(isolate->get(), contexts[i]);
        v8::Local<v8::Object> glb = scriptctx->Global();
        
        lscript->Run(lcontext);
    }
    

    我已经报告了一个错误,因为我不知道为什么会发生这种情况
    几天前,我的程序也崩溃了 async hook stack has become corrupted 错误,当从引发异常时 setImmediate callback(我不得不将setImmediate包装到 setImmediate = cb => setTimeout(cb, 0) 使其工作(无堆栈跟踪))

    我是否忘记了要初始化的内容,输入了一些Scopes,上下文错误。。。?
    难道不是有一些众所周知的错误导致了这种奇怪的行为吗?
    提前感谢您的帮助。

    0 回复  |  直到 2 年前
    推荐文章