Fix crash issue 00/311500/3
authorChanggyu Choi <changyu.choi@samsung.com>
Wed, 22 May 2024 03:56:36 +0000 (12:56 +0900)
committerChanggyu Choi <changyu.choi@samsung.com>
Wed, 22 May 2024 04:55:41 +0000 (13:55 +0900)
In the case of using the preference api after the global resource is destroyed,
a problem occurs by accessing the destroyed pref object.
This patch fixes that issue.

01-01 12:34:23.143+0900 I/CAPI_APPFW_PREFERENCE(P 5722, T 5722): file-backend-internal.cc: ~FileBackend(33) >
01-01 12:34:23.143+0900 I/CAPI_APPFW_PREFERENCE(P 5722, T 5722): file-backend-internal.cc: RemoveWatch(173) >
01-01 12:34:23.206+0900 I/CAPI_APPFW_PREFERENCE(P 5722, T 5742): stub.cc: preference_unset_changed_cb(317) >

Change-Id: I685c3d39ac0ee6e674d91f44b14c8d965edd08bf
Signed-off-by: Changgyu Choi <changyu.choi@samsung.com>
preference/stub.cc

index 5dd96b96033f3b4e9f1273044ff5a6db3080bf4c..dbdafd38fca928f6e75dd32102ce48580033e44c 100644 (file)
@@ -46,6 +46,10 @@ class PrefExt : public preference::internal::Preference,
   PrefExt() : Preference(this) {
   }
 
+  ~PrefExt() {
+    _I("");
+  }
+
   int AddWatch(const char* key, preference_changed_cb cb, void* user_data) {
     std::lock_guard<std::recursive_mutex> lock(GetMutex());
     if (Preference::AddWatch(key) < 0)
@@ -103,7 +107,12 @@ class PrefExt : public preference::internal::Preference,
   mutable std::recursive_mutex mutex_;
 };
 
-PrefExt pref;
+PrefExt* pref = new PrefExt();
+
+__attribute__((destructor)) static void destructor() {
+  delete pref;
+  pref = nullptr;
+}
 
 }  // namespace
 
@@ -113,7 +122,12 @@ extern "C" API int preference_set_int(const char* key, int intval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  int ret = pref.SetInt(key, intval);
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  int ret = pref->SetInt(key, intval);
   if (ret < 0) {
     _E("Failed to set integer value");
     return PREFERENCE_ERROR_IO_ERROR;
@@ -129,7 +143,12 @@ extern "C" API int preference_set_boolean(const char* key, bool boolval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  int ret = pref.SetBoolean(key, boolval);
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  int ret = pref->SetBoolean(key, boolval);
   if (ret < 0) {
     _E("Failed to set boolean value");
     return PREFERENCE_ERROR_IO_ERROR;
@@ -145,7 +164,12 @@ extern "C" API int preference_set_double(const char* key, double dblval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  int ret = pref.SetDouble(key, dblval);
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  int ret = pref->SetDouble(key, dblval);
   if (ret < 0) {
     _E("Failed to set double value");
     return PREFERENCE_ERROR_IO_ERROR;
@@ -162,7 +186,12 @@ extern "C" API int preference_set_string(const char* key, const char* strval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  int ret = pref.SetString(key, strval);
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  int ret = pref->SetString(key, strval);
   if (ret < 0) {
     _E("Failed to set string value");
     return PREFERENCE_ERROR_IO_ERROR;
@@ -178,11 +207,16 @@ extern "C" API int preference_get_int(const char* key, int* intval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key))
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key))
     return PREFERENCE_ERROR_NO_KEY;
 
   try {
-    *intval = pref.GetInt(key);
+    *intval = pref->GetInt(key);
   } catch (const preference::internal::Exception& e) {
     return e.GetErrorCode();
   }
@@ -197,11 +231,16 @@ extern "C" API int preference_get_boolean(const char* key, bool* boolval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key))
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key))
     return PREFERENCE_ERROR_NO_KEY;
 
   try {
-    *boolval = pref.GetBoolean(key);
+    *boolval = pref->GetBoolean(key);
   } catch (const preference::internal::Exception& e) {
     return e.GetErrorCode();
   }
@@ -216,11 +255,16 @@ extern "C" API int preference_get_double(const char* key, double* dblval) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key))
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key))
     return PREFERENCE_ERROR_NO_KEY;
 
   try {
-    *dblval = pref.GetDouble(key);
+    *dblval = pref->GetDouble(key);
   } catch (const preference::internal::Exception& e) {
     return e.GetErrorCode();
   }
@@ -235,11 +279,16 @@ extern "C" API int preference_get_string(const char* key, char** value) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key))
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key))
     return PREFERENCE_ERROR_NO_KEY;
 
   try {
-    *value = strdup(pref.GetString(key).c_str());
+    *value = strdup(pref->GetString(key).c_str());
   } catch (const preference::internal::Exception& e) {
     return e.GetErrorCode();
   }
@@ -254,12 +303,17 @@ extern "C" API int preference_remove(const char* key) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key)) {
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key)) {
     _E("%s doesn't exist", key);
     return PREFERENCE_ERROR_NO_KEY;
   }
 
-  int ret = pref.Remove(key);
+  int ret = pref->Remove(key);
   if (ret < 0) {
     _E("Failed to remove key(%s)", key);
     return PREFERENCE_ERROR_IO_ERROR;
@@ -275,13 +329,23 @@ extern "C" API int preference_is_existing(const char* key, bool* exist) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  *exist = pref.IsExisting(key);
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  *exist = pref->IsExisting(key);
   SECURE_LOGD("key(%s), existence(%d)", key, *exist);
   return PREFERENCE_ERROR_NONE;
 }
 
 extern "C" API int preference_remove_all(void) {
-  int ret = pref.RemoveAll();
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  int ret = pref->RemoveAll();
   if (ret < 0) {
     _E("Failed to delete all keys");
     return PREFERENCE_ERROR_IO_ERROR;
@@ -298,12 +362,17 @@ extern "C" API int preference_set_changed_cb(const char* key,
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key)) {
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key)) {
     _E("Failed to find key(%s)", key);
     return PREFERENCE_ERROR_NO_KEY;
   }
 
-  int ret = pref.AddWatch(key, callback, user_data);
+  int ret = pref->AddWatch(key, callback, user_data);
   if (ret < 0) {
     _E("Failed to add watch");
     return PREFERENCE_ERROR_OUT_OF_MEMORY;
@@ -319,12 +388,17 @@ extern "C" API int preference_unset_changed_cb(const char* key) {
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key)) {
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key)) {
     _E("Failed to find key(%s)", key);
     return PREFERENCE_ERROR_NO_KEY;
   }
 
-  int ret = pref.RemoveWatch(key);
+  int ret = pref->RemoveWatch(key);
   if (ret < 0) {
     _E("Failed to remove watch");
     return PREFERENCE_ERROR_NO_KEY;
@@ -341,7 +415,12 @@ extern "C" API int preference_foreach_item(preference_item_cb callback,
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  auto keys = pref.GetKeys();
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  auto keys = pref->GetKeys();
   for (auto& i : keys) {
     if (!callback(i.c_str(), user_data))
       break;
@@ -357,12 +436,17 @@ extern "C" API int preference_get_type(const char* key,
     return PREFERENCE_ERROR_INVALID_PARAMETER;
   }
 
-  if (!pref.IsExisting(key)) {
+  if (pref == nullptr) {
+    _E("global resource was destroyed");
+    return PREFERENCE_ERROR_IO_ERROR;
+  }
+
+  if (!pref->IsExisting(key)) {
     *type = PREFERENCE_TYPE_NONE;
     return PREFERENCE_ERROR_NONE;
   }
 
-  *type = static_cast<preference_type_e>(pref.GetType(key));
+  *type = static_cast<preference_type_e>(pref->GetType(key));
   SECURE_LOGD("key(%s), type(%d)", key, *type);
   return PREFERENCE_ERROR_NONE;
 }