diff --git a/frameworks/js/napi/featureAbility/feature_ability.cpp b/frameworks/js/napi/featureAbility/feature_ability.cpp index a4acac3012..617b747241 100644 --- a/frameworks/js/napi/featureAbility/feature_ability.cpp +++ b/frameworks/js/napi/featureAbility/feature_ability.cpp @@ -107,7 +107,10 @@ private: void JsFeatureAbility::Finalizer(NativeEngine *engine, void *data, void *hint) { HILOG_DEBUG("JsFeatureAbility::Finalizer is called"); - std::unique_ptr(static_cast(data)); + auto pthis = std::unique_ptr(static_cast(data)); + if (pthis) { + pthis->RemoveAllCallbacksLocked(); + } } NativeValue* JsFeatureAbilityInit(NativeEngine *engine, NativeValue *exports) diff --git a/frameworks/js/napi/inner/napi_ability_common/js_napi_common_ability.h b/frameworks/js/napi/inner/napi_ability_common/js_napi_common_ability.h index 0d69767ac5..554d2d8855 100644 --- a/frameworks/js/napi/inner/napi_ability_common/js_napi_common_ability.h +++ b/frameworks/js/napi/inner/napi_ability_common/js_napi_common_ability.h @@ -127,6 +127,7 @@ public: std::string ConvertErrorCode(int32_t errCode); void AddFreeInstallObserver(NativeEngine& engine, const AAFwk::Want &want, NativeValue* callback); sptr FindConnectionLocked(const Want &want, int64_t &id); + void RemoveAllCallbacksLocked(); bool CreateConnectionAndConnectAbilityLocked( std::shared_ptr callback, const Want &want, int64_t &id); void RemoveConnectionLocked(const Want &want); diff --git a/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.cpp b/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.cpp index d943127787..e4c0cf9dcb 100644 --- a/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.cpp +++ b/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.cpp @@ -3278,6 +3278,23 @@ size_t NAPIAbilityConnection::GetCallbackSize() return callbacks_.size(); } +size_t NAPIAbilityConnection::ReomveAllCallbacks(ConnectRemoveKeyType key) +{ + size_t result = 0; + std::lock_guard guard(lock_); + for (auto it = callbacks_.begin(); it != callbacks_.end();) { + auto callback = *it; + if (callback && callback->removeKey == key) { + it = callbacks_.erase(it); + result++; + } else { + ++it; + } + } + HILOG_INFO("ReomveAllCallbacks removed size:%{public}zu, left size:%{public}zu", result, callbacks_.size()); + return result; +} + void UvWorkOnAbilityConnectDone(uv_work_t *work, int status) { HILOG_INFO("UvWorkOnAbilityConnectDone, uv_queue_work"); @@ -3983,7 +4000,7 @@ NativeValue* JsNapiCommon::JsConnectAbility( return engine.CreateUndefined(); } - auto connectionCallback = std::make_shared(env, secondParam); + auto connectionCallback = std::make_shared(env, secondParam, this); bool result = false; int32_t errorVal = static_cast(NAPI_ERR_NO_ERROR); int64_t id = 0; @@ -4154,6 +4171,21 @@ sptr JsNapiCommon::FindConnectionLocked(const Want &want, return nullptr; } +void JsNapiCommon::RemoveAllCallbacksLocked() +{ + HILOG_DEBUG("RemoveAllCallbacksLocked begin"); + std::lock_guard lock(connectionsLock_); + for (auto it = connects_.begin(); it != connects_.end();) { + auto connection = it->second; + connection->ReomveAllCallbacks(this); + if (connection->GetCallbackSize() == 0) { + it = connects_.erase(it); + } else { + ++it; + } + } +} + void JsNapiCommon::RemoveConnectionLocked(const Want &want) { std::string deviceId = want.GetElement().GetDeviceID(); diff --git a/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.h b/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.h index 70870938e9..babf74352c 100644 --- a/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.h +++ b/frameworks/js/napi/inner/napi_ability_common/napi_common_ability.h @@ -219,8 +219,10 @@ enum { CONNECTION_STATE_CONNECTING = 1 }; +class JsNapiCommon; +using ConnectRemoveKeyType = JsNapiCommon*; struct ConnectionCallback { - ConnectionCallback(napi_env env, napi_value cbInfo) + ConnectionCallback(napi_env env, napi_value cbInfo, ConnectRemoveKeyType key) { this->env = env; napi_value jsMethod = nullptr; @@ -230,16 +232,19 @@ struct ConnectionCallback { napi_create_reference(env, jsMethod, 1, &disconnectCallbackRef); napi_get_named_property(env, cbInfo, "onFailed", &jsMethod); napi_create_reference(env, jsMethod, 1, &failedCallbackRef); + removeKey = key; } ConnectionCallback(ConnectionCallback &) = delete; ConnectionCallback(ConnectionCallback &&other) : env(other.env), connectCallbackRef(other.connectCallbackRef), - disconnectCallbackRef(other.disconnectCallbackRef), failedCallbackRef(other.failedCallbackRef) + disconnectCallbackRef(other.disconnectCallbackRef), failedCallbackRef(other.failedCallbackRef), + removeKey(other.removeKey) { other.env = nullptr; other.connectCallbackRef = nullptr; other.disconnectCallbackRef = nullptr; other.failedCallbackRef = nullptr; + other.removeKey = nullptr; } const ConnectionCallback &operator=(ConnectionCallback &) = delete; const ConnectionCallback &operator=(ConnectionCallback &&other) @@ -253,6 +258,7 @@ struct ConnectionCallback { other.connectCallbackRef = nullptr; other.disconnectCallbackRef = nullptr; other.failedCallbackRef = nullptr; + other.removeKey = nullptr; return *this; } ~ConnectionCallback() @@ -276,12 +282,14 @@ struct ConnectionCallback { } env = nullptr; } + removeKey = nullptr; } napi_env env = nullptr; napi_ref connectCallbackRef = nullptr; napi_ref disconnectCallbackRef = nullptr; napi_ref failedCallbackRef = nullptr; + ConnectRemoveKeyType removeKey = nullptr; }; class NAPIAbilityConnection : public AAFwk::AbilityConnectionStub { @@ -295,6 +303,7 @@ public: int GetConnectionState() const; void SetConnectionState(int connectionState); size_t GetCallbackSize(); + size_t ReomveAllCallbacks(ConnectRemoveKeyType key); private: std::list> callbacks_;