]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Significantly better way of getting the rlm_python path
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 18 Sep 2019 15:34:28 +0000 (10:34 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 18 Sep 2019 15:34:33 +0000 (10:34 -0500)
src/modules/rlm_python/all.mk.in
src/modules/rlm_python/rlm_python.c

index 53ccc2bd367200621d4c3f79ebe500f4c9353dd6..db52f2ebde358b33a343d73f47e24a6cd9f1bda2 100644 (file)
@@ -7,11 +7,7 @@ endif
 SOURCES                := $(TARGETNAME).c
 
 TGT_LDLIBS     := @mod_ldflags@
-
-PYTHON_LIB_PATH := $(shell echo $(TGT_LDLIBS) | sed 's/[ ].*$$//g; s/^-L//g')
-PYTHON_LIB_FILE := $(shell echo $(TGT_LDLIBS) | sed 's/^.*-l\(python.*[^ ]\)/\1/g; s/[ ].*$$//g')
-
-SRC_CFLAGS     := -DPYTHON_LIB_PATH=\"$(PYTHON_LIB_PATH)\" -DPYTHON_LIB_FILE=\"$(PYTHON_LIB_FILE)\" @mod_cflags@
+SRC_CFLAGS     := @mod_cflags@
 
 ifneq "$(TARGETNAME)" ""
 install: $(R)$(modconfdir)/python/example.py
index a640278cd9e44e19ac2134e44aeb4e15d94fbb32..10ca6c054ccfa7c3f4491c3d7954a1b46e62ebe6 100644 (file)
@@ -1238,32 +1238,57 @@ static int mod_thread_detach(UNUSED fr_event_list_t *el, void *thread)
 
 static int mod_load(void)
 {
-       char const *libpython_file = PYTHON_LIB_PATH "/" "lib" PYTHON_LIB_FILE "" DL_EXTENSION;
+       Dl_info         info;
+       void            *sym;
+
+#define PYTHON_TEST_SYMBOL "Py_IsInitialized"
+#define LOAD_INFO(_fmt, ...) fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "rlm_python - " _fmt,  ## __VA_ARGS__)
+#define LOAD_WARN(_fmt, ...) fr_log(LOG_DST, L_WARN, __FILE__, __LINE__, "rlm_python - " _fmt,  ## __VA_ARGS__)
 
        rad_assert(!Py_IsInitialized());
 
-       fr_log(LOG_DST, L_INFO, __FILE__, __LINE__, "Python version: %s", Py_GetVersion());
+       LOAD_INFO("Python version: %s", Py_GetVersion());
        dependency_version_number_add(NULL, "python", Py_GetVersion());
 
+       /*
+        *      Resolve the test symbol in our own
+        *      symbol space.
+        */
+       sym = dlsym(RTLD_SELF, PYTHON_TEST_SYMBOL);
+       if (!sym) {
+               LOAD_WARN("Can't find %s in symbol table, skipping loading python into global symbol table",
+                         PYTHON_TEST_SYMBOL);
+               goto skip_dlopen;
+       }
+
+       /*
+        *      It's unclear whether passing function
+        *      pointers will always "just work",
+        *      which is why we resolve the symbol
+        *      at runtime then call dladdr.
+        */
+       if (dladdr(sym, &info) == 0) {
+               LOAD_WARN("Failed resolving symbol %s (%p) to library path: %s "
+                         ", skipping loading python into global symbol table", PYTHON_TEST_SYMBOL, sym, dlerror());
+               goto skip_dlopen;
+       }
+
        /*
         *      Explicitly load libpython, so symbols will be available to lib-dynload modules
         */
-       python_dlhandle = dlopen(libpython_file, RTLD_NOW | RTLD_GLOBAL);
+       python_dlhandle = dlopen(info.dli_fname, RTLD_NOW | RTLD_GLOBAL);
        if (!python_dlhandle) fr_log(LOG_DST, L_WARN, __FILE__, __LINE__,
                                     "Failed loading libpython symbols from \"%s\" into global symbol table: %s",
-                                    libpython_file, dlerror());
+                                    info.dli_fname, dlerror());
 
+skip_dlopen:
 
 #if PY_MAJOR_VERSION == 3
        /*
         *      Python 3 introduces the concept of a
         *      "inittab", i.e. a list of modules which
-        *      are automatically created when new
-        *      interpreters are spawned.
-        *
-        *      This is what we use to create the radiusd
-        *      interface module in every interpreter
-        *      instance.
+        *      are automatically created when the first
+        *      interpreter is spawned.
         */
        PyImport_AppendInittab("radiusd", python_module_init);
 #endif