Mesa (master): loader: Look for any version of currently linked libudev.so

Chris Wilson ickle at kemper.freedesktop.org
Wed Jul 8 10:13:08 UTC 2015


Module: Mesa
Branch: master
Commit: f2413457937f8f4a92e11379569be69e508d7477
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=f2413457937f8f4a92e11379569be69e508d7477

Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Wed Jun 10 08:28:13 2015 +0100

loader: Look for any version of currently linked libudev.so

Since there was an ABI break and linking twice against libudev.so.0 and
libudev.so.1 causes the application to quickly crash, we first check if
the application is currently linked against libudev before dlopening a
local handle. However for backwards/forwards compatability, we need to
inspect the application for current linkage against all known versions
first. Not doing so causes a crash when both libraries are present and
so mesa chooses libudev.so.1 but the application was linked against
libudev.so.0.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

Emil Velikov:

I'm ever so slightly conserned that RTLD_NOLOAD is not part of the POSIX
standard, thus it's missing on some platforms (*BSD seems ok, while
Solaris, MacOS are not).

Reviewed-by: Emil Velikov <emil.l.velikov at gmail.com>
Cc: mesa-stable at lists.freedesktop.org

---

 src/loader/loader.c |   46 ++++++++++++++++++++++++++++------------------
 1 file changed, 28 insertions(+), 18 deletions(-)

diff --git a/src/loader/loader.c b/src/loader/loader.c
index 8452cd3..8780587 100644
--- a/src/loader/loader.c
+++ b/src/loader/loader.c
@@ -128,26 +128,36 @@ static void *udev_handle = NULL;
 static void *
 udev_dlopen_handle(void)
 {
-   if (!udev_handle) {
-      udev_handle = dlopen("libudev.so.1", RTLD_LOCAL | RTLD_LAZY);
-
-      if (!udev_handle) {
-         /* libudev.so.1 changed the return types of the two unref functions
-          * from voids to pointers.  We don't use those return values, and the
-          * only ABI I've heard that cares about this kind of change (calling
-          * a function with a void * return that actually only returns void)
-          * might be ia64.
-          */
-         udev_handle = dlopen("libudev.so.0", RTLD_LOCAL | RTLD_LAZY);
-
-         if (!udev_handle) {
-            log_(_LOADER_WARNING, "Couldn't dlopen libudev.so.1 or "
-                 "libudev.so.0, driver detection may be broken.\n");
-         }
+   char name[80];
+   unsigned flags = RTLD_NOLOAD | RTLD_LOCAL | RTLD_LAZY;
+   int version;
+
+   /* libudev.so.1 changed the return types of the two unref functions
+    * from voids to pointers.  We don't use those return values, and the
+    * only ABI I've heard that cares about this kind of change (calling
+    * a function with a void * return that actually only returns void)
+    * might be ia64.
+    */
+
+   /* First try opening an already linked libudev, then try loading one */
+   do {
+      for (version = 1; version >= 0; version--) {
+         snprintf(name, sizeof(name), "libudev.so.%d", version);
+         udev_handle = dlopen(name, flags);
+         if (udev_handle)
+            return udev_handle;
       }
-   }
 
-   return udev_handle;
+      if ((flags & RTLD_NOLOAD) == 0)
+         break;
+
+      flags &= ~RTLD_NOLOAD;
+   } while (1);
+
+   log_(_LOADER_WARNING,
+        "Couldn't dlopen libudev.so.1 or "
+        "libudev.so.0, driver detection may be broken.\n");
+   return NULL;
 }
 
 static int dlsym_failed = 0;




More information about the mesa-commit mailing list