Skip to content

Commit 9c02aa1

Browse files
committed
configure: use dlopen instead of ltdl by default
Try dlopen first, then ltdl, or fail to enable dynamically loaded plugins. dlopen may be disabled with --disable-plugin-dlopen (not --disable-dlopen because $enable_dlopen is already used/set somewhere in the configury) Requested by IBM, already done in OMPI a while ago. Closes #262 Signed-off-by: Brice Goglin <[email protected]>
1 parent 17f3cce commit 9c02aa1

File tree

8 files changed

+208
-25
lines changed

8 files changed

+208
-25
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ Version 2.2.0
2727
+ Remove support for Intel Xeon Phi (MIC, Knights Corner) co-processors.
2828
* Tools
2929
+ Add --uid to filter the hwloc-ps output by uid on Linux.
30+
* Misc
31+
+ Use the native dlopen instead of libltdl,
32+
unless --disable-plugin-dlopen is passed at configure time.
33+
3034

3135
Version 2.1.0
3236
-------------

config/hwloc.m4

+53-6
Original file line numberDiff line numberDiff line change
@@ -1184,8 +1184,17 @@ return clGetDeviceIDs(0, 0, 0, NULL, NULL);
11841184
AC_MSG_RESULT($hwloc_have_plugins)
11851185
11861186
if test "x$hwloc_have_plugins" = xyes; then
1187-
# ltdl (at least 2.4.2) doesn't work on AIX
1187+
# dlopen and ltdl (at least 2.4.2) doesn't work on AIX
11881188
# posix linkers don't work well with plugins and windows dll constraints
1189+
if test "x$enable_plugin_dlopen" = x; then
1190+
if test "x$hwloc_aix" = "xyes"; then
1191+
AC_MSG_WARN([dlopen does not work on AIX, disabled by default.])
1192+
enable_plugin_dlopen=no
1193+
else if test "x$hwloc_windows" = "xyes"; then
1194+
AC_MSG_WARN([dlopen not supported on non-native Windows build, disabled by default.])
1195+
enable_plugin_dlopen=no
1196+
fi fi
1197+
fi
11891198
if test "x$enable_plugin_ltdl" = x; then
11901199
if test "x$hwloc_aix" = "xyes"; then
11911200
AC_MSG_WARN([ltdl does not work on AIX, disabled by default.])
@@ -1196,27 +1205,37 @@ return clGetDeviceIDs(0, 0, 0, NULL, NULL);
11961205
fi fi
11971206
fi
11981207
1208+
# Look for dlopen
1209+
if test "x$enable_plugin_dlopen" != xno; then
1210+
HWLOC_CHECK_DLOPEN([hwloc_dlopen_ready], [hwloc_dlopen_libs])
1211+
fi
11991212
# Look for ltdl
12001213
if test "x$enable_plugin_ltdl" != xno; then
12011214
HWLOC_CHECK_LTDL([hwloc_ltdl_ready], [hwloc_ltdl_libs])
12021215
fi
12031216
1204-
# Now use ltdl, or just fail to enable plugins
1217+
# Now use dlopen by default, or ltdl, or just fail to enable plugins
12051218
AC_MSG_CHECKING([which library to use for loading plugins])
1206-
if test x$hwloc_ltdl_ready = xyes; then
1219+
if test "x$hwloc_dlopen_ready" = xyes; then
1220+
AC_MSG_RESULT([dlopen])
1221+
hwloc_plugins_load=dlopen
1222+
# Now enable dlopen libs
1223+
HWLOC_DL_LIBS="$hwloc_dlopen_libs"
1224+
AC_SUBST(HWLOC_DL_LIBS)
1225+
else if test x$hwloc_ltdl_ready = xyes; then
12071226
AC_MSG_RESULT([ltdl])
12081227
hwloc_plugins_load=ltdl
12091228
# Now enable ltdl libs
1229+
AC_DEFINE([HWLOC_HAVE_LTDL], 1, [Define to 1 if the hwloc library should use ltdl for loading plugins])
12101230
HWLOC_LTDL_LIBS="$hwloc_ltdl_libs"
12111231
AC_SUBST(HWLOC_LTDL_LIBS)
12121232
# Add ltdl static-build dependencies to hwloc.pc
12131233
HWLOC_CHECK_LTDL_DEPS
1214-
hwloc_plugins_load=ltdl
12151234
else
12161235
AC_MSG_RESULT([none])
1217-
AC_MSG_WARN([Plugin support requested, but could not enable ltdl])
1236+
AC_MSG_WARN([Plugin support requested, but could not enable dlopen or ltdl])
12181237
AC_MSG_ERROR([Cannot continue])
1219-
fi
1238+
fi fi
12201239
12211240
AC_DEFINE([HWLOC_HAVE_PLUGINS], 1, [Define to 1 if the hwloc library should support dynamically-loaded plugins])
12221241
fi
@@ -1440,6 +1459,34 @@ AC_DEFUN([_HWLOC_CHECK_DECLS], [
14401459

14411460
#-----------------------------------------------------------------------
14421461

1462+
dnl HWLOC_CHECK_DLOPEN
1463+
dnl
1464+
dnl set $1 to yes or not
1465+
dnl set $2 to -ldl or so
1466+
AC_DEFUN([HWLOC_CHECK_DLOPEN], [
1467+
[$1]=no
1468+
AC_MSG_CHECKING([for dlopen])
1469+
AC_LINK_IFELSE([
1470+
AC_LANG_PROGRAM([[
1471+
#include <dlfcn.h>
1472+
#include <stdlib.h>
1473+
void *handle;
1474+
]], [[
1475+
handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL);
1476+
]])],
1477+
[AC_MSG_RESULT([yes])
1478+
[$1]=yes],
1479+
[AC_MSG_RESULT([no])
1480+
AC_CHECK_HEADER([dlfcn.h],
1481+
[AC_CHECK_LIB([dl], [dlopen],
1482+
[[$1]=yes
1483+
[$2]=-ldl])
1484+
])
1485+
])
1486+
])
1487+
1488+
#-----------------------------------------------------------------------
1489+
14431490
dnl HWLOC_CHECK_LTDL
14441491
dnl
14451492
dnl set $1 to yes or not

config/hwloc_internal.m4

+6
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@ AC_DEFUN([HWLOC_DEFINE_ARGS],[
104104
AS_HELP_STRING([--enable-plugins=name,...],
105105
[Build the given components as dynamically-loaded plugins]))
106106
107+
# Look for dlopen
108+
# Not --disable-dlopen because $enable_dlopen is already used/set
109+
AC_ARG_ENABLE([plugin-dlopen],
110+
AC_HELP_STRING([--disable-plugin-dlopen],
111+
[Do not use dlopen for loading plugins.]))
107112
# Look for ltdl
113+
# Not --disable-ltdl for consistency wrt dlopen above
108114
AC_ARG_ENABLE([plugin-ltdl],
109115
AC_HELP_STRING([--disable-plugin-ltdl],
110116
[Do not use ltdl for loading plugins.]))

doc/hwloc.doxy

+3-3
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ The hwloc core may also benefit from the following development packages:
157157
The relevant development package is usually <tt>libudev-devel</tt>
158158
or <tt>libudev-dev</tt>.
159159
</li>
160-
<li>libtool's ltdl library for dynamic plugin loading.
160+
<li>libtool's ltdl library for dynamic plugin loading if the native dlopen cannot be used.
161161
The relevant development package is usually <tt>libtool-ltdl-devel</tt>
162162
or <tt>libltdl-dev</tt>.
163163
</li>
@@ -2710,15 +2710,15 @@ configure script. You can then invoke hwloc's configuration tests and
27102710
build setup by calling an m4 macro (see below).
27112711

27122712
Although hwloc dynamic shared object plugins may be used in embedded
2713-
mode, the embedder project will have to manually setup libltdl in its
2713+
mode, the embedder project will have to manually setup dlopen or libltdl in its
27142714
build system so that hwloc can load its plugins at run time.
27152715
Also, embedders should be aware of complications that can arise due to
27162716
public and private linker namespaces (e.g., if the embedder project is
27172717
loaded into a private namespace and then hwloc tries to dynamically
27182718
load its plugins, such loading may fail since the hwloc plugins can't
27192719
find the hwloc symbols they need).
27202720
The embedder project is <b>strongly</b> advised not to use hwloc's
2721-
dynamically loading plugins / libltdl capability.
2721+
dynamically loading plugins / dlopen / libltdl capability.
27222722

27232723

27242724
\htmlonly

hwloc.pc.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -9,4 +9,4 @@ Version: @HWLOC_VERSION@
99
Requires.private: @HWLOC_REQUIRES@
1010
Cflags: -I${includedir}
1111
Libs: -L${libdir} -lhwloc
12-
Libs.private: @HWLOC_LIBS@ @HWLOC_LTDL_LIBS@ @HWLOC_LIBS_PRIVATE@
12+
Libs.private: @HWLOC_LIBS@ @HWLOC_DL_LIBS@ @HWLOC_LTDL_LIBS@ @HWLOC_LIBS_PRIVATE@

hwloc/Makefile.am

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ endif
2121

2222
pluginsdir = @HWLOC_PLUGINS_DIR@
2323
plugins_LTLIBRARIES =
24-
plugins_ldflags = -module -avoid-version $(HWLOC_LTDL_LIBS)
24+
plugins_ldflags = -module -avoid-version $(HWLOC_DL_LIBS) $(HWLOC_LTDL_LIBS)
2525
# Beware that files are not rebuilt automatically when reconfiguring with different paths in these flags.
2626
AM_CPPFLAGS += -DHWLOC_PLUGINS_PATH="\"$(HWLOC_PLUGINS_PATH)\"" -DRUNSTATEDIR="\"$(HWLOC_runstatedir)\""
2727

@@ -199,7 +199,7 @@ endif HWLOC_HAVE_WINDOWS
199199
# Installable library
200200

201201
libhwloc_la_SOURCES = $(sources)
202-
libhwloc_la_LDFLAGS = $(ldflags) -version-info $(libhwloc_so_version) $(HWLOC_LIBS) $(HWLOC_LTDL_LIBS) $(HWLOC_LDFLAGS)
202+
libhwloc_la_LDFLAGS = $(ldflags) -version-info $(libhwloc_so_version) $(HWLOC_LIBS) $(HWLOC_DL_LIBS) $(HWLOC_LTDL_LIBS) $(HWLOC_LDFLAGS)
203203

204204
if HWLOC_HAVE_PLUGINS
205205
libhwloc_la_LDFLAGS += -export-dynamic

hwloc/components.c

+124-10
Original file line numberDiff line numberDiff line change
@@ -63,22 +63,136 @@ static pthread_mutex_t hwloc_components_mutex = PTHREAD_MUTEX_INITIALIZER;
6363

6464
#ifdef HWLOC_HAVE_PLUGINS
6565

66+
#ifdef HWLOC_HAVE_LTDL
67+
/* ltdl-based plugin load */
6668
#include <ltdl.h>
69+
typedef lt_dlhandle hwloc_dlhandle;
70+
#define hwloc_dlinit lt_dlinit
71+
#define hwloc_dlexit lt_dlexit
72+
#define hwloc_dlopenext lt_dlopenext
73+
#define hwloc_dlclose lt_dlclose
74+
#define hwloc_dlerror lt_dlerror
75+
#define hwloc_dlsym lt_dlsym
76+
#define hwloc_dlforeachfile lt_dlforeachfile
77+
78+
#else /* !HWLOC_HAVE_LTDL */
79+
/* no-ltdl plugin load relies on less portable libdl */
80+
#include <dlfcn.h>
81+
typedef void * hwloc_dlhandle;
82+
static __hwloc_inline int hwloc_dlinit(void) { return 0; }
83+
static __hwloc_inline int hwloc_dlexit(void) { return 0; }
84+
#define hwloc_dlclose dlclose
85+
#define hwloc_dlerror dlerror
86+
#define hwloc_dlsym dlsym
87+
88+
#include <sys/stat.h>
89+
#include <sys/types.h>
90+
#include <dirent.h>
91+
#include <unistd.h>
92+
93+
static hwloc_dlhandle hwloc_dlopenext(const char *_filename)
94+
{
95+
hwloc_dlhandle handle;
96+
char *filename = NULL;
97+
asprintf(&filename, "%s.so", _filename);
98+
if (!filename)
99+
return NULL;
100+
handle = dlopen(filename, RTLD_NOW|RTLD_LOCAL);
101+
free(filename);
102+
return handle;
103+
}
104+
105+
static int
106+
hwloc_dlforeachfile(const char *_paths,
107+
int (*func)(const char *filename, void *data),
108+
void *data)
109+
{
110+
char *paths = NULL, *path;
111+
112+
paths = strdup(_paths);
113+
if (!paths)
114+
return -1;
115+
116+
path = paths;
117+
while (*path) {
118+
char *colon;
119+
DIR *dir;
120+
struct dirent *dirent;
121+
122+
colon = strchr(path, ':');
123+
if (colon)
124+
*colon = '\0';
125+
126+
if (hwloc_plugins_verbose)
127+
fprintf(stderr, " Looking under %s\n", path);
128+
129+
dir = opendir(path);
130+
if (!dir)
131+
goto next;
132+
133+
while ((dirent = readdir(dir)) != NULL) {
134+
char *abs_name, *suffix;
135+
struct stat stbuf;
136+
int err;
137+
138+
err = asprintf(&abs_name, "%s/%s", path, dirent->d_name);
139+
if (err < 0)
140+
continue;
141+
142+
err = stat(abs_name, &stbuf);
143+
if (err < 0) {
144+
free(abs_name);
145+
continue;
146+
}
147+
if (!S_ISREG(stbuf.st_mode)) {
148+
free(abs_name);
149+
continue;
150+
}
151+
152+
/* Only keep .so files, and remove that suffix to get the component basename */
153+
suffix = strrchr(abs_name, '.');
154+
if (!suffix || strcmp(suffix, ".so")) {
155+
free(abs_name);
156+
continue;
157+
}
158+
*suffix = '\0';
159+
160+
err = func(abs_name, data);
161+
if (err) {
162+
free(abs_name);
163+
continue;
164+
}
165+
166+
free(abs_name);
167+
}
168+
169+
closedir(dir);
170+
171+
next:
172+
if (!colon)
173+
break;
174+
path = colon+1;
175+
}
176+
177+
free(paths);
178+
return 0;
179+
}
180+
#endif /* !HWLOC_HAVE_LTDL */
67181

68182
/* array of pointers to dynamically loaded plugins */
69183
static struct hwloc__plugin_desc {
70184
char *name;
71185
struct hwloc_component *component;
72186
char *filename;
73-
lt_dlhandle handle;
187+
hwloc_dlhandle handle;
74188
struct hwloc__plugin_desc *next;
75189
} *hwloc_plugins = NULL;
76190

77191
static int
78192
hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
79193
{
80194
const char *basename;
81-
lt_dlhandle handle;
195+
hwloc_dlhandle handle;
82196
struct hwloc_component *component;
83197
struct hwloc__plugin_desc *desc, **prevdesc;
84198
char *componentsymbolname;
@@ -99,10 +213,10 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
99213
}
100214

101215
/* dlopen and get the component structure */
102-
handle = lt_dlopenext(filename);
216+
handle = hwloc_dlopenext(filename);
103217
if (!handle) {
104218
if (hwloc_plugins_verbose)
105-
fprintf(stderr, "Failed to load plugin: %s\n", lt_dlerror());
219+
fprintf(stderr, "Failed to load plugin: %s\n", hwloc_dlerror());
106220
goto out;
107221
}
108222

@@ -114,7 +228,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
114228
goto out_with_handle;
115229
}
116230
sprintf(componentsymbolname, "%s_component", basename);
117-
component = lt_dlsym(handle, componentsymbolname);
231+
component = hwloc_dlsym(handle, componentsymbolname);
118232
if (!component) {
119233
if (hwloc_plugins_verbose)
120234
fprintf(stderr, "Failed to find component symbol `%s'\n",
@@ -175,7 +289,7 @@ hwloc__dlforeach_cb(const char *filename, void *_data __hwloc_attribute_unused)
175289
return 0;
176290

177291
out_with_handle:
178-
lt_dlclose(handle);
292+
hwloc_dlclose(handle);
179293
out:
180294
return 0;
181295
}
@@ -191,15 +305,15 @@ hwloc_plugins_exit(void)
191305
desc = hwloc_plugins;
192306
while (desc) {
193307
next = desc->next;
194-
lt_dlclose(desc->handle);
308+
hwloc_dlclose(desc->handle);
195309
free(desc->name);
196310
free(desc->filename);
197311
free(desc);
198312
desc = next;
199313
}
200314
hwloc_plugins = NULL;
201315

202-
lt_dlexit();
316+
hwloc_dlexit();
203317
}
204318

205319
static int
@@ -215,7 +329,7 @@ hwloc_plugins_init(void)
215329

216330
hwloc_plugins_blacklist = getenv("HWLOC_PLUGINS_BLACKLIST");
217331

218-
err = lt_dlinit();
332+
err = hwloc_dlinit();
219333
if (err)
220334
goto out;
221335

@@ -227,7 +341,7 @@ hwloc_plugins_init(void)
227341

228342
if (hwloc_plugins_verbose)
229343
fprintf(stderr, "Starting plugin dlforeach in %s\n", path);
230-
err = lt_dlforeachfile(path, hwloc__dlforeach_cb, NULL);
344+
err = hwloc_dlforeachfile(path, hwloc__dlforeach_cb, NULL);
231345
if (err)
232346
goto out_with_init;
233347

0 commit comments

Comments
 (0)