From 2ef5535c5d0c2c3a7bf105129ae235440bd1f6a8 Mon Sep 17 00:00:00 2001 From: zhuzhihui7 Date: Fri, 27 Dec 2024 18:01:00 +0800 Subject: [PATCH] =?UTF-8?q?TaskPool=20&=20Worker=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E5=85=A8=E5=B1=80=E5=BC=82=E5=B8=B8=E5=A4=84=E7=90=86=E4=BC=98?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: zhuzhihui7 Change-Id: I90e7d5925c1def091bc4a264312ad31232f91a9b --- native_engine/impl/ark/ark_native_engine.cpp | 70 +++---------- native_engine/impl/ark/ark_native_engine.h | 6 +- native_engine/native_engine.cpp | 51 ++++++++- native_engine/native_engine.h | 103 ++++++++++--------- test/unittest/engine/test_ark.cpp | 71 ++++++++----- 5 files changed, 167 insertions(+), 134 deletions(-) diff --git a/native_engine/impl/ark/ark_native_engine.cpp b/native_engine/impl/ark/ark_native_engine.cpp index 8c030955..59c62c2f 100644 --- a/native_engine/impl/ark/ark_native_engine.cpp +++ b/native_engine/impl/ark/ark_native_engine.cpp @@ -99,6 +99,7 @@ static std::unordered_set NATIVE_MODULE = {"system.app", "ohos.app" "system.curves", "ohos.curves", "system.matrix4", "ohos.matrix4"}; static constexpr auto NATIVE_MODULE_PREFIX = "@native:"; static constexpr auto OHOS_MODULE_PREFIX = "@ohos:"; +static constexpr int ARGC_THREE = 3; #ifdef ENABLE_HITRACE constexpr auto NAPI_PROFILER_PARAM_SIZE = 10; std::atomic g_chainId = 0; @@ -570,33 +571,17 @@ ArkNativeEngine::ArkNativeEngine(EcmaVM* vm, void* jsEngine, bool isLimitedWorke JSNApi::SetAsyncCleanTaskCallback(vm, [this] (AsyncNativeCallbacksPack *callbacksPack) { this->PostAsyncTask(callbacksPack); }); - RegisterNapiUncaughtExceptionHandler([this] (napi_value exception) -> void { - if (!NativeEngine::IsAlive(this)) { - HILOG_WARN("napi_env has been destoryed!"); - return; - } - std::string name = ""; - if (this->IsWorkerThread() && this->getWorkerNameCallback_) { - name = this->getWorkerNameCallback_(this->worker_); - } else if (this->IsTaskPoolThread()) { - name = this->GetTaskName(); - this->SetTaskName(""); - } - auto hasAllErrorCallback = NapiErrorManager::GetInstance()->GetHasAllErrorCallback(); - if (!hasAllErrorCallback) { - return; - } - if (!hasAllErrorCallback()) { - return; - } - JSNApi::GetAndClearUncaughtException(this->GetEcmaVm()); - auto callback = NapiErrorManager::GetInstance()->GetOnAllErrorCallback(); - if (callback) { - callback(reinterpret_cast(this), exception, - name, this->GetJSThreadTypeInt()); - } - }); - RegisterAllPromiseCallback(); + JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast(PromiseRejectCallback), + reinterpret_cast(this)); + if (IsMainThread()) { + RegisterAllPromiseCallback([this] (napi_value* args) -> void { + if (!NativeEngine::IsAlive(this)) { + HILOG_WARN("napi_env has been destoryed!"); + return; + } + NapiErrorManager::GetInstance()->NotifyUncaughtException(reinterpret_cast(this), args, "", 0); + }); + } #if defined(ENABLE_EVENT_HANDLER) if (JSNApi::IsJSMainThreadOfEcmaVM(vm)) { ArkIdleMonitor::GetInstance()->SetMainThreadEcmaVM(vm); @@ -1966,30 +1951,6 @@ bool ArkNativeEngine::AdjustExternalMemory(int64_t ChangeInBytes, int64_t* Adjus return true; } -void ArkNativeEngine::RegisterAllPromiseCallback() -{ - JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast(PromiseRejectCallback), - reinterpret_cast(this)); - allPromiseRejectCallback_ = [this] (napi_value* args) -> void { - if (!NativeEngine::IsAlive(this)) { - HILOG_WARN("napi_env has been destoryed!"); - return; - } - std::string name = ""; - if (this->IsWorkerThread() && this->getWorkerNameCallback_) { - name = this->getWorkerNameCallback_(this->worker_); - } else if (this->IsTaskPoolThread()) { - name = this->GetTaskName(); - this->SetTaskName(""); - } - auto callback = NapiErrorManager::GetInstance()->GetAllUnhandledRejectionCallback(); - if (callback) { - callback(reinterpret_cast(this), args, - name, this->GetJSThreadTypeInt()); - } - }; -} - void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRef, NativeReference* checkCallbackRef) { if (rejectCallbackRef == nullptr || checkCallbackRef == nullptr) { @@ -1998,8 +1959,6 @@ void ArkNativeEngine::SetPromiseRejectCallback(NativeReference* rejectCallbackRe } promiseRejectCallbackRef_ = rejectCallbackRef; checkCallbackRef_ = checkCallbackRef; - JSNApi::SetHostPromiseRejectionTracker(vm_, reinterpret_cast(PromiseRejectCallback), - reinterpret_cast(this)); } void ArkNativeEngine::PromiseRejectCallback(void* info) @@ -2021,7 +1980,6 @@ void ArkNativeEngine::PromiseRejectCallback(void* info) Local args[] = {type, promise, reason}; if (env->allPromiseRejectCallback_) { - constexpr int ARGC_THREE = 3; napi_value *callErrorArgs = new napi_value[ARGC_THREE]; for (int i = 0; i < ARGC_THREE; i++) { callErrorArgs[i] = JsValueFromLocalValue(args[i]); @@ -2374,7 +2332,7 @@ void ArkNativeEngine::SetMockModuleList(const std::map JSNApi::SetMockModuleList(vm_, list); } -static void OnAllErrorCallbackForThreadFunc(Local value, void *data) +static void OnErrorCallbackForThreadFunc(Local value, void *data) { if (data == nullptr) { return; @@ -2391,7 +2349,7 @@ static void OnAllErrorCallbackForThreadFunc(Local value, void *data) void ArkNativeEngine::RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) { JSNApi::EnableUserUncaughtErrorHandler(vm_); - JSNApi::SetOnAllErrorCallbackForThread(vm_, OnAllErrorCallbackForThreadFunc, static_cast(this)); + JSNApi::SetOnErrorCallback(vm_, OnErrorCallbackForThreadFunc, static_cast(this)); napiUncaughtExceptionCallback_ = callback; } diff --git a/native_engine/impl/ark/ark_native_engine.h b/native_engine/impl/ark/ark_native_engine.h index bb2e5256..49b1d43f 100644 --- a/native_engine/impl/ark/ark_native_engine.h +++ b/native_engine/impl/ark/ark_native_engine.h @@ -296,7 +296,6 @@ public: } void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) override; - void RegisterAllPromiseCallback(); void HandleUncaughtException() override; bool HasPendingException() override; void RegisterPermissionCheck(PermissionCheckCallback callback) override; @@ -317,6 +316,11 @@ public: return promiseRejectCallbackRef_; } + void RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback) override + { + allPromiseRejectCallback_ = callback; + } + void SetPromiseRejectCallBackRef(NativeReference* rejectCallbackRef) override { promiseRejectCallbackRef_ = rejectCallbackRef; diff --git a/native_engine/native_engine.cpp b/native_engine/native_engine.cpp index 232148fc..dc7d48e2 100644 --- a/native_engine/native_engine.cpp +++ b/native_engine/native_engine.cpp @@ -1111,4 +1111,53 @@ NapiErrorManager* NapiErrorManager::GetInstance() } } return instance_; -} \ No newline at end of file +} + +void NapiErrorManager::NotifyUncaughtException(napi_env env, napi_value exception, std::string name, uint32_t type) +{ + auto hasOnErrorCallback = NapiErrorManager::GetInstance()->GetHasErrorCallback(); + if (!hasOnErrorCallback) { + return; + } + if (!hasOnErrorCallback()) { + return; + } + panda::JSNApi::GetAndClearUncaughtException(reinterpret_cast(env)->GetEcmaVm()); + auto callback = NapiErrorManager::GetInstance()->GetOnWorkerErrorCallback(); + if (callback) { + callback(env, exception, name, type); + } +} + +bool NapiErrorManager::NotifyUncaughtException(napi_env env, const std::string &summary, const std::string &name, + const std::string &message, const std::string &stack) +{ + auto hasOnErrorCallback = NapiErrorManager::GetInstance()->GetHasErrorCallback(); + if (!hasOnErrorCallback) { + return false; + } + if (!hasOnErrorCallback()) { + return false; + } + panda::JSNApi::GetAndClearUncaughtException(reinterpret_cast(env)->GetEcmaVm()); + auto callback = NapiErrorManager::GetInstance()->GetOnMainThreadErrorCallback(); + if (!callback) { + return false; + } + return callback(env, summary, name, message, stack); +} + +void NapiErrorManager::NotifyUncaughtException(napi_env env, napi_value* args, std::string name, uint32_t type) +{ + auto hasAllUnhandledRejectionCallback = NapiErrorManager::GetInstance()->GetHasAllUnhandledRejectionCallback(); + if (!hasAllUnhandledRejectionCallback) { + return; + } + if (!hasAllUnhandledRejectionCallback()) { + return; + } + auto callback = NapiErrorManager::GetInstance()->GetAllUnhandledRejectionCallback(); + if (callback) { + callback(env, args, name, type); + } +} diff --git a/native_engine/native_engine.h b/native_engine/native_engine.h index 903f3264..dd19dc9a 100644 --- a/native_engine/native_engine.h +++ b/native_engine/native_engine.h @@ -102,7 +102,7 @@ private: using CleanupCallback = void (*)(void*); using ThreadId = uint32_t; - +static constexpr uint32_t TASKPOOL_TYPE = 2; class NapiOptions; using PostTask = std::function; using CleanEnv = std::function; @@ -119,13 +119,15 @@ using SourceMapTranslateCallback = std::function; using EcmaVM = panda::ecmascript::EcmaVM; using JsFrameInfo = panda::ecmascript::JsFrameInfo; -using GetWorkerNameCallback = std::function; -using NapiOnAllErrorCallback = std::function; +using NapiOnMainThreadErrorCallback = std::function; using NapiAllUnhandledRejectionCallback = std::function; using NapiAllPromiseRejectCallback = std::function; -using NapiHasOnAllErrorCallback = std::function; +using NapiHasOnErrorCallback = std::function; +using NapiHasAllUnhandledRejectionCallback = std::function; class NAPI_EXPORT NativeEngine { public: explicit NativeEngine(void* jsEngine); @@ -415,6 +417,7 @@ public: void RegisterWorkerFunction(const NativeEngine* engine); virtual void RegisterNapiUncaughtExceptionHandler(NapiUncaughtExceptionCallback callback) = 0; + virtual void RegisterAllPromiseCallback(NapiAllPromiseRejectCallback callback) = 0; virtual void HandleUncaughtException() = 0; virtual bool HasPendingException() { @@ -521,36 +524,6 @@ public: return g_mainThreadEngine_; } - void RegisterGetWorkerNameCallback(GetWorkerNameCallback callback, void* worker) - { - getWorkerNameCallback_ = callback; - worker_ = worker; - } - - uint32_t GetJSThreadTypeInt() - { - return GetJSThreadType(); - } - - void SetTaskName(std::string taskName) - { - taskName_ = taskName; - } - - std::string GetTaskName() - { - return taskName_; - } - - void HandleTaskpoolException(napi_value exception, std::string taskName) - { - this->SetTaskName(taskName); - auto callback = this->GetNapiUncaughtExceptionCallback(); - if (callback) { - callback(exception); - } - } - static void SetMainThreadEngine(NativeEngine* engine) { if (g_mainThreadEngine_ == nullptr) { @@ -598,7 +571,6 @@ protected: NativeErrorExtendedInfo lastError_; // register for worker - GetWorkerNameCallback getWorkerNameCallback_ {nullptr}; void* worker_ = nullptr; InitWorkerFunc initWorkerFunc_ {nullptr}; GetAssetFunc getAssetFunc_ {nullptr}; @@ -633,11 +605,6 @@ private: DataProtect jsThreadType_ {DataProtect(uintptr_t(JSThreadType::MAIN_THREAD))}; // current is hostengine, can create old worker, new worker, or no workers on hostengine std::atomic workerVersion_ { WorkerVersion::NONE }; - JSThreadType GetJSThreadType() - { - return static_cast(jsThreadType_.GetData()); - } - #if !defined(PREVIEW) static void UVThreadRunner(void* nativeEngine); void PostLoopTask(); @@ -674,19 +641,32 @@ class NapiErrorManager { public: static NapiErrorManager* GetInstance(); - void RegisterOnAllErrorCallback(NapiOnAllErrorCallback callback) + void RegisterOnErrorCallback(NapiOnWorkerErrorCallback workerErrorCb, + NapiOnMainThreadErrorCallback mainThreadErrorCb) { - onAllErrorCb_ = callback; + if (!onWorkerErrorCb_) { + onWorkerErrorCb_ = workerErrorCb; + } + if (!onMainThreadErrorCb_) { + onMainThreadErrorCb_ = mainThreadErrorCb; + } } - NapiOnAllErrorCallback &GetOnAllErrorCallback() + NapiOnWorkerErrorCallback &GetOnWorkerErrorCallback() { - return onAllErrorCb_; + return onWorkerErrorCb_; + } + + NapiOnMainThreadErrorCallback &GetOnMainThreadErrorCallback() + { + return onMainThreadErrorCb_; } void RegisterAllUnhandledRejectionCallback(NapiAllUnhandledRejectionCallback callback) { - allUnhandledRejectionCb_ = callback; + if (!allUnhandledRejectionCb_) { + allUnhandledRejectionCb_ = callback; + } } NapiAllUnhandledRejectionCallback &GetAllUnhandledRejectionCallback() @@ -694,21 +674,42 @@ public: return allUnhandledRejectionCb_; } - void RegisterHasOnAllErrorCallback(NapiHasOnAllErrorCallback callback) + void RegisterHasOnErrorCallback(NapiHasOnErrorCallback callback) { - hasOnAllErrorCb_ = callback; + if (!hasOnErrorCb_) { + hasOnErrorCb_ = callback; + } } - NapiHasOnAllErrorCallback &GetHasAllErrorCallback() + NapiHasOnErrorCallback &GetHasErrorCallback() { - return hasOnAllErrorCb_; + return hasOnErrorCb_; } + void RegisterHasAllUnhandledRejectionCallback(NapiHasAllUnhandledRejectionCallback callback) + { + if (!hasAllUnhandledRejectionCb_) { + hasAllUnhandledRejectionCb_ = callback; + } + } + + NapiHasAllUnhandledRejectionCallback &GetHasAllUnhandledRejectionCallback() + { + return hasAllUnhandledRejectionCb_; + } + + void NotifyUncaughtException(napi_env env, napi_value exception, std::string name, uint32_t type); + bool NotifyUncaughtException(napi_env env, const std::string &summary, const std::string &name, + const std::string &message, const std::string &stack); + void NotifyUncaughtException(napi_env env, napi_value* exception, std::string name, uint32_t type); + private: static NapiErrorManager *instance_; - NapiOnAllErrorCallback onAllErrorCb_ { nullptr }; + NapiOnWorkerErrorCallback onWorkerErrorCb_ { nullptr }; + NapiOnMainThreadErrorCallback onMainThreadErrorCb_ { nullptr }; NapiAllUnhandledRejectionCallback allUnhandledRejectionCb_ { nullptr }; - NapiHasOnAllErrorCallback hasOnAllErrorCb_ { nullptr }; + NapiHasOnErrorCallback hasOnErrorCb_ { nullptr }; + NapiHasAllUnhandledRejectionCallback hasAllUnhandledRejectionCb_ { nullptr }; }; bool DumpHybridStack(const EcmaVM* vm, std::string &stack, uint32_t ignored = 0, int32_t deepth = -1); diff --git a/test/unittest/engine/test_ark.cpp b/test/unittest/engine/test_ark.cpp index a18ac8c8..b0f28063 100644 --- a/test/unittest/engine/test_ark.cpp +++ b/test/unittest/engine/test_ark.cpp @@ -116,26 +116,31 @@ HWTEST_F(NativeEngineTest, ExecuteTranslateBySourceMapFunc001, testing::ext::Tes HWTEST_F(NativeEngineTest, NapiErrorManagerTest001, testing::ext::TestSize.Level0) { - auto errorManagerCallbackTest = + auto onWorkerErrorCallback = [] (napi_env env, napi_value exception, std::string vm_name, uint32_t type) -> bool { - EXPECT_EQ(type, 0); + EXPECT_EQ(type, 2); EXPECT_EQ(vm_name, ""); return true; }; - - NapiErrorManager::GetInstance()->RegisterOnAllErrorCallback(errorManagerCallbackTest); - ASSERT_NE(NapiErrorManager::GetInstance()->GetOnAllErrorCallback(), nullptr); - auto getWorkerNameCallback = - [] (void* worker) -> std::string { - return "test"; + auto onMainThreadErrorCallback = + [] (napi_env env, std::string summary, std::string name, + std::string message, std::string stack) -> bool { + EXPECT_EQ(name, "name"); + EXPECT_EQ(message, "message"); + return true; + }; + auto hasOnErrorCb = [] () -> bool { + return true; }; - void* worker = nullptr; - engine_->RegisterGetWorkerNameCallback(getWorkerNameCallback, worker); + NapiErrorManager::GetInstance()->RegisterHasOnErrorCallback(hasOnErrorCb); + NapiErrorManager::GetInstance()->RegisterOnErrorCallback(onWorkerErrorCallback, onMainThreadErrorCallback); + ASSERT_NE(NapiErrorManager::GetInstance()->GetOnWorkerErrorCallback(), nullptr); + ASSERT_NE(NapiErrorManager::GetInstance()->GetOnMainThreadErrorCallback(), nullptr); napi_value exception = nullptr; - auto callback = engine_->GetNapiUncaughtExceptionCallback(); - if (callback) { - callback(exception); - } + NapiErrorManager::GetInstance()->NotifyUncaughtException(reinterpret_cast(engine_), + exception, "test", 2); + ASSERT_EQ(NapiErrorManager::GetInstance()->NotifyUncaughtException(reinterpret_cast(engine_), + "", "name", "message", ""), true); } HWTEST_F(NativeEngineTest, NapiErrorManagerTest002, testing::ext::TestSize.Level0) @@ -143,26 +148,42 @@ HWTEST_F(NativeEngineTest, NapiErrorManagerTest002, testing::ext::TestSize.Level auto allUnhandledRejectionCallbackTest = [] (napi_env env, napi_value* exception, std::string vm_name, uint32_t type) -> bool { EXPECT_EQ(type, 0); - EXPECT_EQ(vm_name, ""); + EXPECT_EQ(vm_name, "test"); return true; }; + auto hasAllUnhandledRejectionCb = [] () -> bool { + return false; + }; + NapiErrorManager::GetInstance()->RegisterHasAllUnhandledRejectionCallback(hasAllUnhandledRejectionCb); + napi_value* exception = nullptr; NapiErrorManager::GetInstance()->RegisterAllUnhandledRejectionCallback(allUnhandledRejectionCallbackTest); ASSERT_NE(NapiErrorManager::GetInstance()->GetAllUnhandledRejectionCallback(), nullptr); - Local promise; - Local reason; - panda::PromiseRejectInfo promiseRejectInfo(promise, reason, - static_cast(0), reinterpret_cast(engine_)); + NapiErrorManager::GetInstance()->NotifyUncaughtException(reinterpret_cast(engine_), exception, "test", 0); +} + +HWTEST_F(NativeEngineTest, NapiErrorManagerTest003, testing::ext::TestSize.Level0) +{ + auto hasOnErrorCb = [] () -> bool { + return true; + }; - ArkNativeEngine::PromiseRejectCallback(reinterpret_cast(&promiseRejectInfo)); + NapiErrorManager::GetInstance()->RegisterHasOnErrorCallback(hasOnErrorCb); + auto callback = NapiErrorManager::GetInstance()->GetHasErrorCallback(); + ASSERT_NE(callback, nullptr); + ASSERT_EQ(callback(), true); } -HWTEST_F(NativeEngineTest, HandleTaskpoolExceptionTest001, testing::ext::TestSize.Level0) +HWTEST_F(NativeEngineTest, NapiErrorManagerTest004, testing::ext::TestSize.Level0) { - napi_value exception = nullptr; - std::string taskName = "test"; - engine_->HandleTaskpoolException(exception, taskName); - ASSERT_EQ(engine_->GetTaskName(), "test"); + auto hasAllUnhandledRejectionCb = [] () -> bool { + return false; + }; + + NapiErrorManager::GetInstance()->RegisterHasAllUnhandledRejectionCallback(hasAllUnhandledRejectionCb); + auto callback = NapiErrorManager::GetInstance()->GetHasAllUnhandledRejectionCallback(); + ASSERT_NE(callback, nullptr); + ASSERT_EQ(callback(), false); } HWTEST_F(NativeEngineTest, FinalizersCallbackTest001, testing::ext::TestSize.Level0) -- Gitee