From b786ffccd5044de648cb0d2b62c76d15843c4a2f Mon Sep 17 00:00:00 2001 From: ksuprynowicz Date: Sun, 29 Jan 2023 21:39:41 +0100 Subject: [PATCH] Added more debug info to crash with signals --- .../script-engine/src/v8/ScriptEngineV8.cpp | 6 ++ .../src/v8/ScriptObjectV8Proxy.cpp | 68 +++++++++++-------- 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/libraries/script-engine/src/v8/ScriptEngineV8.cpp b/libraries/script-engine/src/v8/ScriptEngineV8.cpp index 3ff6068aa2..206756fbe7 100644 --- a/libraries/script-engine/src/v8/ScriptEngineV8.cpp +++ b/libraries/script-engine/src/v8/ScriptEngineV8.cpp @@ -393,7 +393,13 @@ ScriptEngineV8::ScriptEngineV8(ScriptManager* scriptManager) : // // Based on that, going with 256K for stacks for now. That seems like a reasonable value. // We'll probably need a more complex system on the longer term, with configurable limits. + // Flags to try: + // V8TODO --single-threaded is to check if it fixes random crashes + // --jitless - might improve debugging performance due to no JIT? + // --assert-types + v8::V8::SetFlagsFromString("--stack-size=256"); + //v8::V8::SetFlagsFromString("--stack-size=256 --single-threaded"); v8::Platform* platform = getV8Platform(); v8::V8::InitializePlatform(platform); v8::V8::Initialize(); qCDebug(scriptengine) << "V8 platform initialized"; diff --git a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp index 3cefe59270..2cb627370f 100644 --- a/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp +++ b/libraries/script-engine/src/v8/ScriptObjectV8Proxy.cpp @@ -673,7 +673,7 @@ void ScriptMethodV8Proxy::callback(const v8::FunctionCallbackInfo& ar v8::Locker locker(arguments.GetIsolate()); v8::Isolate::Scope isolateScope(arguments.GetIsolate()); v8::HandleScope handleScope(arguments.GetIsolate()); - Q_ASSERT(!arguments.GetIsolate()->GetCurrentContext().IsEmpty()); + //Q_ASSERT(!arguments.GetIsolate()->GetCurrentContext().IsEmpty()); v8::Context::Scope contextScope(arguments.GetIsolate()->GetCurrentContext()); if (!arguments.Data()->IsObject()) { arguments.GetIsolate()->ThrowError("Method value is not an object"); @@ -1082,40 +1082,50 @@ int ScriptSignalV8Proxy::qt_metacall(QMetaObject::Call call, int id, void** argu args[arg] = _engine->castVariantToValue(argValue).get(); } - QList connections; + /*QList connections; withReadLock([&]{ connections = _connections; - }); + });*/ - for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { - Connection& conn = *iter; - Q_ASSERT(!conn.callback.get().IsEmpty()); - Q_ASSERT(!conn.callback.get()->IsUndefined()); - Q_ASSERT(conn.callback.get()->IsFunction()); - { - v8::Local callback = v8::Local::Cast(conn.callback.get()); - //auto functionContext = callback->CreationContext(); - auto functionContext = _v8Context.Get(_engine->getIsolate()); - _engine->pushContext(functionContext); - v8::Context::Scope functionContextScope(functionContext); + withReadLock([&]{ + //for (ConnectionList::iterator iter = connections.begin(); iter != connections.end(); ++iter) { + for (ConnectionList::iterator iter = _connections.begin(); iter != _connections.end(); ++iter) { + Connection& conn = *iter; + { + //auto functionContext = callback->CreationContext(); + auto functionContext = _v8Context.Get(_engine->getIsolate()); + _engine->pushContext(functionContext); + v8::Context::Scope functionContextScope(functionContext); - v8::Local v8This; - if (conn.thisValue.get()->IsObject()) { - v8This = conn.thisValue.get(); - } else { - v8This = functionContext->Global(); + Q_ASSERT(!conn.callback.get().IsEmpty()); + Q_ASSERT(!conn.callback.get()->IsUndefined()); + Q_ASSERT(!conn.callback.get()->IsNull()); + if (!conn.callback.get()->IsFunction()) { + auto stringV8 = conn.callback.get()->ToDetailString(functionContext).ToLocalChecked(); + QString error = *v8::String::Utf8Value(_engine->getIsolate(), stringV8); + qDebug() << error; + Q_ASSERT(false); + } + v8::Local callback = v8::Local::Cast(conn.callback.get()); + + v8::Local v8This; + if (conn.thisValue.get()->IsObject()) { + v8This = conn.thisValue.get(); + } else { + v8This = functionContext->Global(); + } + + v8::TryCatch tryCatch(isolate); + callback->Call(functionContext, v8This, numArgs, args); + if (tryCatch.HasCaught()) { + qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \"" + << _engine->formatErrorMessageFromTryCatch(tryCatch) + << "\nThis provided: " << conn.thisValue.get()->IsObject(); + } + _engine->popContext(); } - - v8::TryCatch tryCatch(isolate); - callback->Call(functionContext, v8This, numArgs, args); - if (tryCatch.HasCaught()) { - qCDebug(scriptengine) << "Signal proxy " << fullName() << " connection call failed: \"" - << _engine->formatErrorMessageFromTryCatch(tryCatch) - << "\nThis provided: " << conn.thisValue.get()->IsObject(); - } - _engine->popContext(); } - } + }); return -1; }