OSDN Git Service

Modify android_dlwarning function to use a callback
authorDimitry Ivanov <dimitry@google.com>
Wed, 2 Mar 2016 21:05:51 +0000 (13:05 -0800)
committerDimitry Ivanov <dimitry@google.com>
Thu, 3 Mar 2016 21:06:41 +0000 (21:06 +0000)
The previous implementation of android_dlwarning was not thread-safe
and could return a pointer soon to become invalid in some situations.
This change fixed the problem. I have also removed android_dlwarning
from the dlext.h header file in case we decide to keep
android_dlwarning in the final release.

Bug: http://b/27453994
Change-Id: If6c896a80a17c4be0e18795e617712ad36a106fe

libc/include/android/dlext.h
libdl/libdl.c
linker/dlfcn.cpp
linker/linker_dlwarning.cpp
linker/linker_dlwarning.h

index 76d19ae..d5ec386 100644 (file)
@@ -194,8 +194,6 @@ extern struct android_namespace_t* android_create_namespace(const char* name,
                                                             uint64_t type,
                                                             const char* permitted_when_isolated_path);
 
-const char* android_dlwarning();
-
 __END_DECLS
 
 #endif /* __ANDROID_DLEXT_H__ */
index d2e5e31..b62ee5c 100644 (file)
@@ -70,4 +70,4 @@ struct android_namespace_t* android_create_namespace(const char* name __unused,
   return 0;
 }
 
-const char* android_dlwarning(void) { return 0; }
+void android_dlwarning(void* obj, void (*f)(void*, const char*)) { f(obj, 0); }
index 89b2a36..64bf9e0 100644 (file)
@@ -137,9 +137,9 @@ uint32_t android_get_application_target_sdk_version() {
   return get_application_target_sdk_version();
 }
 
-const char* android_dlwarning() {
+void android_dlwarning(void* obj, void (*f)(void*, const char*)) {
   ScopedPthreadMutexLocker locker(&g_dl_mutex);
-  return get_dlwarning();
+  get_dlwarning(obj, f);
 }
 
 bool android_init_namespaces(const char* public_ns_sonames,
index f4a3daf..cd76533 100644 (file)
@@ -21,7 +21,6 @@
 #include <string>
 
 static std::string current_msg;
-static std::string old_msg;
 
 void add_dlwarning(const char* sopath, const char* message, const char* value) {
   if (!current_msg.empty()) {
@@ -38,13 +37,12 @@ void add_dlwarning(const char* sopath, const char* message, const char* value) {
 
 // Resets the current one (like dlerror but instead of
 // being thread-local it is process-local).
-const char* get_dlwarning() {
+void get_dlwarning(void* obj, void (*f)(void*, const char*)) {
   if (current_msg.empty()) {
-    return nullptr;
+    f(obj, nullptr);
+  } else {
+    std::string msg = current_msg;
+    current_msg.clear();
+    f(obj, msg.c_str());
   }
-
-  old_msg = current_msg;
-  current_msg.clear();
-
-  return old_msg.c_str();
 }
index b67032c..0263c72 100644 (file)
@@ -20,7 +20,9 @@
 void add_dlwarning(const char* sopath, const char* message, const char* value = nullptr);
 
 // Resets the current one (like dlerror but instead of
-// being thread-local it is process-local).
-const char* get_dlwarning();
+// being thread-local it is process-local). The user_data
+// is used to avoid forcing user into saving the message
+// to a global variable.
+void get_dlwarning(void* user_data, void (*f)(void*, const char*));
 
 #endif  /* __LINKER_DLWARNING_H */