已合并
稳定性问题处理 #174
guoxu1111创建于 8月5日
稳定性问题处理 #174
已合并
共 2 个文件变更+94-36
| @@ -18,6 +18,7 @@ | |||
| 18 | 18 | ||
| 19 | 19 | ||
| 20 | 20 | ||
| 21 | + | ||
| 21 | 22 | ||
| 22 | 23 | ||
| 23 | 24 | ||
| @@ -184,7 +185,7 @@ private: | |||
| 184 | 185 | ||
| 185 | // 插件 .so 句柄和函数指针 | 186 | // 插件 .so 句柄和函数指针 |
| 186 | void* pluginSo_ = nullptr; | 187 | void* pluginSo_ = nullptr; |
| 187 | - uint32_t pluginUnloadTimerId_ {0}; // 插件自动卸载定时器ID | 188 | + std::atomic<uint32_t> pluginUnloadTimerId_ {0}; // 插件自动卸载定时器ID |
| 188 | DatabaseSaveConfigFunc databaseSave_ = nullptr; | 189 | DatabaseSaveConfigFunc databaseSave_ = nullptr; |
| 189 | DatabaseGetConfigFunc databaseGet_ = nullptr; | 190 | DatabaseGetConfigFunc databaseGet_ = nullptr; |
| 190 | DatabaseIsAvailableFunc databaseAvailable_ = nullptr; | 191 | DatabaseIsAvailableFunc databaseAvailable_ = nullptr; |
| @@ -197,7 +198,7 @@ private: | |||
| 197 | 198 | ||
| 198 | int32_t inputMonitorId_ {-1}; | 199 | int32_t inputMonitorId_ {-1}; |
| 199 | mutable std::mutex mutex_; | 200 | mutable std::mutex mutex_; |
| 200 | - mutable std::mutex pluginMutex_; | 201 | + mutable std::shared_mutex pluginMutex_; |
| 201 | static sptr<ISelectionListener> listener_; | 202 | static sptr<ISelectionListener> listener_; |
| 202 | sptr<SelectionExtensionAbilityConnection> connectInner_ {nullptr}; | 203 | sptr<SelectionExtensionAbilityConnection> connectInner_ {nullptr}; |
| 203 | std::mutex connectMutex_; | 204 | std::mutex connectMutex_; |
| @@ -348,9 +348,18 @@ void SelectionService::PersistSelectionConfig() | |||
| 348 | auto selectionConfig = MemSelectionConfig::GetInstance().GetSelectionConfig(); | 348 | auto selectionConfig = MemSelectionConfig::GetInstance().GetSelectionConfig(); |
| 349 | SELECTION_HILOGI("========== PersistSelectionConfig: Start =========="); | 349 | SELECTION_HILOGI("========== PersistSelectionConfig: Start =========="); |
| 350 | 350 | ||
| 351 | - if (!LoadPluginSo()) { | 351 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); |
| 352 | - SELECTION_HILOGW("Using in-memory config as fallback, service continues to run"); | 352 | + if (!pluginSo_) { |
| 353 | - return; | 353 | + readLock.unlock(); |
| 354 | + if (!LoadPluginSo()) { | ||
| 355 | + SELECTION_HILOGW("Using in-memory config as fallback, service continues to run"); | ||
| 356 | + return; | ||
| 357 | + } | ||
| 358 | + readLock.lock(); | ||
| 359 | + if (!pluginSo_) { | ||
| 360 | + SELECTION_HILOGW("Plugin unloaded during operation, using in-memory config as fallback"); | ||
| 361 | + return; | ||
| 362 | + } | ||
| 354 | } | 363 | } |
| 355 | 364 | ||
| 356 | if (databaseSave_) { | 365 | if (databaseSave_) { |
| @@ -413,12 +422,19 @@ int32_t SelectionService::DoConnectNewExtAbility(const std::string& bundleName, | |||
| 413 | return SELECTION_CONFIG_FAILURE; | 422 | return SELECTION_CONFIG_FAILURE; |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 416 | - if (!LoadPluginSo() || !abilityConnect_) { | 425 | + if (!LoadPluginSo()) { |
| 417 | SELECTION_HILOGE("Ability manager plugin not available"); | 426 | SELECTION_HILOGE("Ability manager plugin not available"); |
| 418 | connectInner_ = nullptr; | 427 | connectInner_ = nullptr; |
| 419 | return SELECTION_CONFIG_FAILURE; | 428 | return SELECTION_CONFIG_FAILURE; |
| 420 | } | 429 | } |
| 421 | 430 | ||
| 431 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 432 | + if (!pluginSo_ || !abilityConnect_) { | ||
| 433 | + SELECTION_HILOGE("Ability manager plugin not available after load"); | ||
| 434 | + connectInner_ = nullptr; | ||
| 435 | + return SELECTION_CONFIG_FAILURE; | ||
| 436 | + } | ||
| 437 | + | ||
| 422 | auto ret = abilityConnect_(&want, &connectInner_, userId); | 438 | auto ret = abilityConnect_(&want, &connectInner_, userId); |
| 423 | if (ret != 0) { | 439 | if (ret != 0) { |
| 424 | SELECTION_HILOGE("[selectevent] StartExtensionAbility failed. error code is %{public}d.", ret); | 440 | SELECTION_HILOGE("[selectevent] StartExtensionAbility failed. error code is %{public}d.", ret); |
| @@ -446,7 +462,9 @@ void SelectionService::DoDisconnectCurrentExtAbility() | |||
| 446 | connectInner_->InitDisconnectPromise(); | 462 | connectInner_->InitDisconnectPromise(); |
| 447 | 463 | ||
| 448 | // 如果插件已卸载,直接清理连接对象,不重新加载插件 | 464 | // 如果插件已卸载,直接清理连接对象,不重新加载插件 |
| 465 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 449 | if (!abilityDisconnect_) { | 466 | if (!abilityDisconnect_) { |
| 467 | + readLock.unlock(); | ||
| 450 | SELECTION_HILOGW("Ability manager plugin not available, clean up connection only"); | 468 | SELECTION_HILOGW("Ability manager plugin not available, clean up connection only"); |
| 451 | connectInner_->DestroyDisconnectPromise(); | 469 | connectInner_->DestroyDisconnectPromise(); |
| 452 | connectInner_ = nullptr; | 470 | connectInner_ = nullptr; |
| @@ -454,6 +472,7 @@ void SelectionService::DoDisconnectCurrentExtAbility() | |||
| 454 | } | 472 | } |
| 455 | 473 | ||
| 456 | int32_t ret = abilityDisconnect_(&connectInner_); | 474 | int32_t ret = abilityDisconnect_(&connectInner_); |
| 475 | + readLock.unlock(); | ||
| 457 | if (ret != ERR_OK) { | 476 | if (ret != ERR_OK) { |
| 458 | connectInner_->DestroyDisconnectPromise(); | 477 | connectInner_->DestroyDisconnectPromise(); |
| 459 | SELECTION_HILOGE("DisconnectServiceAbility failed, ret: %{public}d", ret); | 478 | SELECTION_HILOGE("DisconnectServiceAbility failed, ret: %{public}d", ret); |
| @@ -660,9 +679,18 @@ void SelectionService::SynchronizeSelectionConfig() | |||
| 660 | 679 | ||
| 661 | std::optional<SelectionConfig> SelectionService::LoadDatabaseSelectionConfig() | 680 | std::optional<SelectionConfig> SelectionService::LoadDatabaseSelectionConfig() |
| 662 | { | 681 | { |
| 663 | - if (!LoadPluginSo()) { | 682 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); |
| 664 | - SELECTION_HILOGW("Using system default config as fallback"); | 683 | + if (!pluginSo_) { |
| 665 | - return std::nullopt; | 684 | + readLock.unlock(); |
| 685 | + if (!LoadPluginSo()) { | ||
| 686 | + SELECTION_HILOGW("Using system default config as fallback"); | ||
| 687 | + return std::nullopt; | ||
| 688 | + } | ||
| 689 | + readLock.lock(); | ||
| 690 | + if (!pluginSo_) { | ||
| 691 | + SELECTION_HILOGW("Plugin unloaded during operation, using fallback"); | ||
| 692 | + return std::nullopt; | ||
| 693 | + } | ||
| 666 | } | 694 | } |
| 667 | 695 | ||
| 668 | if (!databaseGet_) { | 696 | if (!databaseGet_) { |
| @@ -691,13 +719,15 @@ void SelectionService::SyncConfigToSystem(const SelectionConfig& config) | |||
| 691 | 719 | ||
| 692 | void SelectionService::SyncConfigToDatabase(int32_t userId, const SelectionConfig& config) | 720 | void SelectionService::SyncConfigToDatabase(int32_t userId, const SelectionConfig& config) |
| 693 | { | 721 | { |
| 694 | - SELECTION_HILOGI("SyncConfigToDatabase: %{public}s", config.ToString().c_str()); | 722 | + if (!LoadPluginSo()) { |
| 695 | - | 723 | + SELECTION_HILOGW("Config saved to system params as fallback"); |
| 696 | - if (!LoadPluginSo() || !databaseSave_) { | 724 | + return; |
| 725 | + } | ||
| 726 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 727 | + if (!pluginSo_ || !databaseSave_) { | ||
| 697 | SELECTION_HILOGW("Config saved to system params as fallback"); | 728 | SELECTION_HILOGW("Config saved to system params as fallback"); |
| 698 | return; | 729 | return; |
| 699 | } | 730 | } |
| 700 | - | ||
| 701 | auto ret = databaseSave_(userId, &config); | 731 | auto ret = databaseSave_(userId, &config); |
| 702 | if (ret != SELECTION_CONFIG_OK) { | 732 | if (ret != SELECTION_CONFIG_OK) { |
| 703 | SELECTION_HILOGE("Save database failed. ret = %{public}d", ret); | 733 | SELECTION_HILOGE("Save database failed. ret = %{public}d", ret); |
| @@ -978,8 +1008,9 @@ void SelectionService::PerformParamBootCompleted(const char* key, const char* va | |||
| 978 | 1008 | ||
| 979 | bool SelectionService::LoadPluginSo() | 1009 | bool SelectionService::LoadPluginSo() |
| 980 | { | 1010 | { |
| 981 | - std::lock_guard<std::mutex> lock(pluginMutex_); | 1011 | + std::unique_lock<std::shared_mutex> lock(pluginMutex_); |
| 982 | if (pluginSo_) { | 1012 | if (pluginSo_) { |
| 1013 | + ResetPluginUnloadTimer(); //新增已加载分支也重置 | ||
| 983 | return true; // 已加载 | 1014 | return true; // 已加载 |
| 984 | } | 1015 | } |
| 985 | 1016 | ||
| @@ -1019,10 +1050,11 @@ bool SelectionService::LoadPluginSo() | |||
| 1019 | 1050 | ||
| 1020 | void SelectionService::UnloadPluginSo() | 1051 | void SelectionService::UnloadPluginSo() |
| 1021 | { | 1052 | { |
| 1053 | + std::unique_lock<std::shared_mutex> lock(pluginMutex_); | ||
| 1022 | // 取消卸载定时器 | 1054 | // 取消卸载定时器 |
| 1023 | - if (pluginUnloadTimerId_ != 0) { | 1055 | + if (pluginUnloadTimerId_.load() != 0) { |
| 1024 | - SelectionFwkTimer::GetInstance()->UnRegister(pluginUnloadTimerId_); | 1056 | + SelectionFwkTimer::GetInstance()->UnRegister(pluginUnloadTimerId_.load()); |
| 1025 | - pluginUnloadTimerId_ = 0; | 1057 | + pluginUnloadTimerId_.store(0); |
| 1026 | } | 1058 | } |
| 1027 | 1059 | ||
| 1028 | if (pluginSo_) { | 1060 | if (pluginSo_) { |
| @@ -1053,15 +1085,15 @@ void SelectionService::UnloadPluginSo() | |||
| 1053 | void SelectionService::ResetPluginUnloadTimer() | 1085 | void SelectionService::ResetPluginUnloadTimer() |
| 1054 | { | 1086 | { |
| 1055 | // 取消旧的定时器 | 1087 | // 取消旧的定时器 |
| 1056 | - if (pluginUnloadTimerId_ != 0) { | 1088 | + if (pluginUnloadTimerId_.load() != 0) { |
| 1057 | - SelectionFwkTimer::GetInstance()->UnRegister(pluginUnloadTimerId_); | 1089 | + SelectionFwkTimer::GetInstance()->UnRegister(pluginUnloadTimerId_.load()); |
| 1058 | - pluginUnloadTimerId_ = 0; | 1090 | + pluginUnloadTimerId_.store(0); |
| 1059 | } | 1091 | } |
| 1060 | 1092 | ||
| 1061 | // 启动新的定时器:5分钟后自动卸载插件 | 1093 | // 启动新的定时器:5分钟后自动卸载插件 |
| 1062 | - pluginUnloadTimerId_ = SelectionFwkTimer::GetInstance()->Register([this]() { | 1094 | + pluginUnloadTimerId_.store(SelectionFwkTimer::GetInstance()->Register([this]() { |
| 1063 | OnPluginUnloadTimer(); | 1095 | OnPluginUnloadTimer(); |
| 1064 | - }, PLUGIN_UNLOAD_TIMEOUT_MS); | 1096 | + }, PLUGIN_UNLOAD_TIMEOUT_MS)); |
| 1065 | 1097 | ||
| 1066 | SELECTION_HILOGI("Plugin unload timer reset: %{public}d ms", PLUGIN_UNLOAD_TIMEOUT_MS); | 1098 | SELECTION_HILOGI("Plugin unload timer reset: %{public}d ms", PLUGIN_UNLOAD_TIMEOUT_MS); |
| 1067 | } | 1099 | } |
| @@ -1080,43 +1112,57 @@ void SelectionService::OnPluginUnloadTimer() | |||
| 1080 | DisconnectCurrentExtAbility(); | 1112 | DisconnectCurrentExtAbility(); |
| 1081 | } | 1113 | } |
| 1082 | UnloadPluginSo(); | 1114 | UnloadPluginSo(); |
| 1083 | - pluginUnloadTimerId_ = 0; | 1115 | + // pluginUnloadTimerId_ is already set to 0 inside UnloadPluginSo() |
| 1084 | } | 1116 | } |
| 1085 | 1117 | ||
| 1086 | int SelectionService::GetDatabaseConfig(int32_t uid, SelectionConfig& config) | 1118 | int SelectionService::GetDatabaseConfig(int32_t uid, SelectionConfig& config) |
| 1087 | { | 1119 | { |
| 1088 | - if (!LoadPluginSo() || !databaseGet_) { | 1120 | + if (!LoadPluginSo()) { |
| 1089 | SELECTION_HILOGE("Database plugin not available"); | 1121 | SELECTION_HILOGE("Database plugin not available"); |
| 1090 | return SELECTION_CONFIG_RDB_NO_INIT; | 1122 | return SELECTION_CONFIG_RDB_NO_INIT; |
| 1091 | } | 1123 | } |
| 1124 | + | ||
| 1125 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 1126 | + if (!pluginSo_ || !databaseGet_) { | ||
| 1127 | + SELECTION_HILOGE("Database plugin not available after load"); | ||
| 1128 | + return SELECTION_CONFIG_RDB_NO_INIT; | ||
| 1129 | + } | ||
| 1092 | 1130 | ||
| 1093 | SelectionConfig* configPtr = &config; | 1131 | SelectionConfig* configPtr = &config; |
| 1094 | int ret = databaseGet_(uid, configPtr); | 1132 | int ret = databaseGet_(uid, configPtr); |
| 1095 | if (ret != 0) { | 1133 | if (ret != 0) { |
| 1096 | SELECTION_HILOGE("DatabaseGetConfig failed, ret=%{public}d", ret); | 1134 | SELECTION_HILOGE("DatabaseGetConfig failed, ret=%{public}d", ret); |
| 1097 | } | 1135 | } |
| 1098 | - ResetPluginUnloadTimer(); // 重置5分钟卸载定时器 | ||
| 1099 | return ret; | 1136 | return ret; |
| 1100 | } | 1137 | } |
| 1101 | 1138 | ||
| 1102 | int SelectionService::SaveDatabaseConfig(int32_t uid, const SelectionConfig& config) | 1139 | int SelectionService::SaveDatabaseConfig(int32_t uid, const SelectionConfig& config) |
| 1103 | { | 1140 | { |
| 1104 | - if (!LoadPluginSo() || !databaseSave_) { | 1141 | + if (!LoadPluginSo()) { |
| 1105 | SELECTION_HILOGE("Database plugin not available"); | 1142 | SELECTION_HILOGE("Database plugin not available"); |
| 1106 | return SELECTION_CONFIG_RDB_NO_INIT; | 1143 | return SELECTION_CONFIG_RDB_NO_INIT; |
| 1107 | } | 1144 | } |
| 1145 | + | ||
| 1146 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 1147 | + if (!pluginSo_ || !databaseSave_) { | ||
| 1148 | + SELECTION_HILOGE("Database plugin not available after load"); | ||
| 1149 | + return SELECTION_CONFIG_RDB_NO_INIT; | ||
| 1150 | + } | ||
| 1108 | 1151 | ||
| 1109 | int ret = databaseSave_(uid, &config); | 1152 | int ret = databaseSave_(uid, &config); |
| 1110 | if (ret != 0) { | 1153 | if (ret != 0) { |
| 1111 | SELECTION_HILOGE("DatabaseSaveConfig failed, ret=%{public}d", ret); | 1154 | SELECTION_HILOGE("DatabaseSaveConfig failed, ret=%{public}d", ret); |
| 1112 | } | 1155 | } |
| 1113 | - ResetPluginUnloadTimer(); // 重置5分钟卸载定时器 | ||
| 1114 | return ret; | 1156 | return ret; |
| 1115 | } | 1157 | } |
| 1116 | 1158 | ||
| 1117 | bool SelectionService::IsDatabaseAvailable() | 1159 | bool SelectionService::IsDatabaseAvailable() |
| 1118 | { | 1160 | { |
| 1119 | - if (!LoadPluginSo() || !databaseAvailable_) { | 1161 | + if (!LoadPluginSo()) { |
| 1162 | + return false; | ||
| 1163 | + } | ||
| 1164 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 1165 | + if (!pluginSo_ || !databaseAvailable_) { | ||
| 1120 | return false; | 1166 | return false; |
| 1121 | } | 1167 | } |
| 1122 | return databaseAvailable_() != 0; | 1168 | return databaseAvailable_() != 0; |
| @@ -1128,34 +1174,45 @@ int SelectionService::GetPasteboardContent(std::string& content, uint32_t window | |||
| 1128 | constexpr uint32_t BYTES_PER_CHINESE_CHAR = 3; | 1174 | constexpr uint32_t BYTES_PER_CHINESE_CHAR = 3; |
| 1129 | constexpr uint32_t bufferSize = MAX_PASTERBOARD_TEXT_LENGTH * BYTES_PER_CHINESE_CHAR + 1; | 1175 | constexpr uint32_t bufferSize = MAX_PASTERBOARD_TEXT_LENGTH * BYTES_PER_CHINESE_CHAR + 1; |
| 1130 | 1176 | ||
| 1131 | - if (!LoadPluginSo() || !pasteboardGetContent_) { | 1177 | + if (!LoadPluginSo()) { |
| 1132 | SELECTION_HILOGE("Pasteboard plugin not available"); | 1178 | SELECTION_HILOGE("Pasteboard plugin not available"); |
| 1133 | return SelectionServiceError::INVALID_DATA; | 1179 | return SelectionServiceError::INVALID_DATA; |
| 1134 | } | 1180 | } |
| 1181 | + | ||
| 1182 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 1183 | + if (!pluginSo_ || !pasteboardGetContent_) { | ||
| 1184 | + SELECTION_HILOGE("Pasteboard plugin not available after load"); | ||
| 1185 | + return SelectionServiceError::INVALID_DATA; | ||
| 1186 | + } | ||
| 1135 | 1187 | ||
| 1136 | char buffer[bufferSize] = {0}; | 1188 | char buffer[bufferSize] = {0}; |
| 1137 | int ret = pasteboardGetContent_(buffer, bufferSize, windowId, bundleName.c_str()); | 1189 | int ret = pasteboardGetContent_(buffer, bufferSize, windowId, bundleName.c_str()); |
| 1138 | if (ret == 0) { | 1190 | if (ret == 0) { |
| 1139 | content = buffer; | 1191 | content = buffer; |
| 1140 | } | 1192 | } |
| 1141 | - ResetPluginUnloadTimer(); // 重置5分钟卸载定时器 | ||
| 1142 | return ret; | 1193 | return ret; |
| 1143 | } | 1194 | } |
| 1144 | 1195 | ||
| 1145 | bool SelectionService::CanGetPasteboardContent() | 1196 | bool SelectionService::CanGetPasteboardContent() |
| 1146 | { | 1197 | { |
| 1147 | - if (!LoadPluginSo() || !pasteboardCanGetContent_) { | 1198 | + if (!LoadPluginSo()) { |
| 1199 | + return false; | ||
| 1200 | + } | ||
| 1201 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); | ||
| 1202 | + if (!pluginSo_ || !pasteboardCanGetContent_) { | ||
| 1148 | return false; | 1203 | return false; |
| 1149 | } | 1204 | } |
| 1150 | bool result = pasteboardCanGetContent_() != 0; | 1205 | bool result = pasteboardCanGetContent_() != 0; |
| 1151 | - ResetPluginUnloadTimer(); // 重置5分钟卸载定时器 | ||
| 1152 | return result; | 1206 | return result; |
| 1153 | } | 1207 | } |
| 1154 | 1208 | ||
| 1155 | void SelectionService::SetPasteboardFlag(bool flag) | 1209 | void SelectionService::SetPasteboardFlag(bool flag) |
| 1156 | { | 1210 | { |
| 1157 | - if (LoadPluginSo() && pasteboardSetFlag_) { | 1211 | + if (!LoadPluginSo()) { |
| 1158 | - pasteboardSetFlag_(flag ? 1 : 0); | 1212 | + return; |
| 1159 | - ResetPluginUnloadTimer(); // 重置5分钟卸载定时器 | ||
| 1160 | } | 1213 | } |
| 1161 | -} | 1214 | + std::shared_lock<std::shared_mutex> readLock(pluginMutex_); |
| 1215 | + if (pluginSo_ && pasteboardSetFlag_) { | ||
| 1216 | + pasteboardSetFlag_(flag ? 1 : 0); | ||
| 1217 | + } | ||
| 1218 | +} | ||