dlopen: simple dl component based on POSIX dlopen
Works on systems with dlopen (e.g., Linux and OS X). It requires dlfcn.h and libdl, which many systems have installed by default.
Этот коммит содержится в:
родитель
e81c070ef0
Коммит
7d340c0c26
23
opal/mca/dl/dlopen/Makefile.am
Обычный файл
23
opal/mca/dl/dlopen/Makefile.am
Обычный файл
@ -0,0 +1,23 @@
|
||||
#
|
||||
# Copyright (c) 2004-2010 The Trustees of Indiana University.
|
||||
# All rights reserved.
|
||||
# Copyright (c) 2014-2015 Cisco Systems, Inc. All rights reserved.
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
sources = \
|
||||
dl_dlopen.h \
|
||||
dl_dlopen_component.c \
|
||||
dl_dlopen_module.c
|
||||
|
||||
# This component will only ever be built statically -- never as a DSO.
|
||||
|
||||
noinst_LTLIBRARIES = libmca_dl_dlopen.la
|
||||
|
||||
libmca_dl_dlopen_la_SOURCES = $(sources)
|
||||
libmca_dl_dlopen_la_LDFLAGS = -module -avoid-version
|
||||
libmca_dl_dlopen_la_LIBS = $(opal_dl_dlopen_LIBS)
|
55
opal/mca/dl/dlopen/configure.m4
Обычный файл
55
opal/mca/dl/dlopen/configure.m4
Обычный файл
@ -0,0 +1,55 @@
|
||||
# -*- shell-script -*-
|
||||
#
|
||||
# Copyright (c) 2009-2015 Cisco Systems, Inc. All rights reserved.
|
||||
#
|
||||
# $COPYRIGHT$
|
||||
#
|
||||
# Additional copyrights may follow
|
||||
#
|
||||
# $HEADER$
|
||||
#
|
||||
|
||||
AC_DEFUN([MCA_opal_dl_dlopen_PRIORITY], [80])
|
||||
|
||||
#
|
||||
# Force this component to compile in static-only mode
|
||||
#
|
||||
AC_DEFUN([MCA_opal_dl_dlopen_COMPILE_MODE], [
|
||||
AC_MSG_CHECKING([for MCA component $2:$3 compile mode])
|
||||
$4="static"
|
||||
AC_MSG_RESULT([$$4])
|
||||
])
|
||||
|
||||
# MCA_dl_dlopen_CONFIG([action-if-can-compile],
|
||||
# [action-if-cant-compile])
|
||||
# ------------------------------------------------
|
||||
AC_DEFUN([MCA_opal_dl_dlopen_CONFIG],[
|
||||
AC_CONFIG_FILES([opal/mca/dl/dlopen/Makefile])
|
||||
|
||||
dnl This is effectively a back-door for Open MPI developers to
|
||||
dnl force the use of the libltdl dl component.
|
||||
AC_ARG_ENABLE([dl-dlopen],
|
||||
[AS_HELP_STRING([--disable-dl-dlopen],
|
||||
[Disable the "dlopen" DL component (and probably force the use of the "libltdl" DL component). This option should really only be used by Open MPI developers. You are probably actually looking for the "--disable-dlopen" option, which disables all dlopen-like functionality from Open MPI.])
|
||||
])
|
||||
|
||||
opal_dl_dlopen_happy=no
|
||||
AS_IF([test "$enable_dl_dlopen" != "no"],
|
||||
[OPAL_CHECK_PACKAGE([opal_dl_dlopen],
|
||||
[dlfcn.h],
|
||||
[dl],
|
||||
[dlopen],
|
||||
[],
|
||||
[],
|
||||
[],
|
||||
[opal_dl_dlopen_happy=yes],
|
||||
[opal_dl_dlopen_happy=no])
|
||||
])
|
||||
|
||||
AS_IF([test "$opal_dl_dlopen_happy" = "yes"],
|
||||
[opal_dl_dlopen_ADD_LIBS=$opal_dl_dlopen_LIBS
|
||||
$1],
|
||||
[$2])
|
||||
|
||||
AC_SUBST(opal_dl_dlopen_LIBS)
|
||||
])
|
40
opal/mca/dl/dlopen/dl_dlopen.h
Обычный файл
40
opal/mca/dl/dlopen/dl_dlopen.h
Обычный файл
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#ifndef OPAL_DL_DLOPEN
|
||||
#define OPAL_DL_DLOPEN
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include "opal/mca/dl/dl.h"
|
||||
|
||||
OPAL_DECLSPEC extern opal_dl_base_module_t opal_dl_dlopen_module;
|
||||
|
||||
/*
|
||||
* Dynamic library handles generated by this component.
|
||||
*
|
||||
* If we're debugging, keep a copy of the name of the file we've opened.
|
||||
*/
|
||||
struct opal_dl_handle_t {
|
||||
void *dlopen_handle;
|
||||
#if OPAL_ENABLE_DEBUG
|
||||
void *filename;
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
opal_dl_base_component_t base;
|
||||
|
||||
char *filename_suffixes_mca_storage;
|
||||
char **filename_suffixes;
|
||||
} opal_dl_dlopen_component_t;
|
||||
|
||||
OPAL_DECLSPEC extern opal_dl_dlopen_component_t mca_dl_dlopen_component;
|
||||
|
||||
#endif /* OPAL_DL_DLOPEN */
|
128
opal/mca/dl/dlopen/dl_dlopen_component.c
Обычный файл
128
opal/mca/dl/dlopen/dl_dlopen_component.c
Обычный файл
@ -0,0 +1,128 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/dl/dl.h"
|
||||
#include "opal/util/argv.h"
|
||||
|
||||
#include "dl_dlopen.h"
|
||||
|
||||
|
||||
/*
|
||||
* Public string showing the sysinfo ompi_linux component version number
|
||||
*/
|
||||
const char *opal_dl_dlopen_component_version_string =
|
||||
"OPAL dl dlopen MCA component version " OPAL_VERSION;
|
||||
|
||||
|
||||
/*
|
||||
* Local functions
|
||||
*/
|
||||
static int dlopen_component_register(void);
|
||||
static int dlopen_component_open(void);
|
||||
static int dlopen_component_close(void);
|
||||
static int dlopen_component_query(mca_base_module_t **module, int *priority);
|
||||
|
||||
/*
|
||||
* Instantiate the public struct with all of our public information
|
||||
* and pointers to our public functions in it
|
||||
*/
|
||||
|
||||
opal_dl_dlopen_component_t mca_dl_dlopen_component = {
|
||||
|
||||
/* Fill in the mca_dl_base_component_t */
|
||||
.base = {
|
||||
|
||||
/* First, the mca_component_t struct containing meta information
|
||||
about the component itself */
|
||||
.base_version = {
|
||||
OPAL_DL_BASE_VERSION_1_0_0,
|
||||
|
||||
/* Component name and version */
|
||||
"dlopen",
|
||||
OPAL_MAJOR_VERSION,
|
||||
OPAL_MINOR_VERSION,
|
||||
OPAL_RELEASE_VERSION,
|
||||
|
||||
/* Component functions */
|
||||
.mca_register_component_params = dlopen_component_register,
|
||||
.mca_open_component = dlopen_component_open,
|
||||
.mca_close_component = dlopen_component_close,
|
||||
.mca_query_component = dlopen_component_query,
|
||||
},
|
||||
|
||||
.base_data = {
|
||||
/* The component is checkpoint ready */
|
||||
MCA_BASE_METADATA_PARAM_CHECKPOINT
|
||||
},
|
||||
|
||||
/* The dl framework members */
|
||||
.priority = 80
|
||||
},
|
||||
|
||||
/* Now fill in the dlopen component-specific members */
|
||||
.filename_suffixes_mca_storage = ".so,.dylib,.dll,.sl",
|
||||
.filename_suffixes = NULL
|
||||
};
|
||||
|
||||
|
||||
static int dlopen_component_register(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret =
|
||||
mca_base_component_var_register(&mca_dl_dlopen_component.base.base_version,
|
||||
"filename_suffixes",
|
||||
"Comma-delimited list of filename suffixes that the dlopen component will try",
|
||||
MCA_BASE_VAR_TYPE_STRING,
|
||||
NULL,
|
||||
0,
|
||||
MCA_BASE_VAR_FLAG_SETTABLE,
|
||||
OPAL_INFO_LVL_5,
|
||||
MCA_BASE_VAR_SCOPE_LOCAL,
|
||||
&mca_dl_dlopen_component.filename_suffixes_mca_storage);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
mca_dl_dlopen_component.filename_suffixes =
|
||||
opal_argv_split(mca_dl_dlopen_component.filename_suffixes_mca_storage,
|
||||
',');
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
static int dlopen_component_open(void)
|
||||
{
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int dlopen_component_close(void)
|
||||
{
|
||||
if (NULL != mca_dl_dlopen_component.filename_suffixes) {
|
||||
opal_argv_free(mca_dl_dlopen_component.filename_suffixes);
|
||||
mca_dl_dlopen_component.filename_suffixes = NULL;
|
||||
}
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int dlopen_component_query(mca_base_module_t **module, int *priority)
|
||||
{
|
||||
/* The priority value is somewhat meaningless here; by
|
||||
opal/mca/dl/configure.m4, there's at most one component
|
||||
available. */
|
||||
*priority = mca_dl_dlopen_component.base.priority;
|
||||
*module = &opal_dl_dlopen_module.super;
|
||||
|
||||
return OPAL_SUCCESS;
|
||||
}
|
263
opal/mca/dl/dlopen/dl_dlopen_module.c
Обычный файл
263
opal/mca/dl/dlopen/dl_dlopen_module.c
Обычный файл
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Cisco Systems, Inc. All rights reserved.
|
||||
* $COPYRIGHT$
|
||||
*
|
||||
* Additional copyrights may follow
|
||||
*
|
||||
* $HEADER$
|
||||
*/
|
||||
|
||||
#include "opal_config.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "opal/constants.h"
|
||||
#include "opal/mca/dl/dl.h"
|
||||
#include "opal/util/argv.h"
|
||||
|
||||
#include "dl_dlopen.h"
|
||||
|
||||
|
||||
/*
|
||||
* Trivial helper function to avoid replicating code
|
||||
*/
|
||||
static void do_dlopen(const char *fname, int flags,
|
||||
void **handle, char **err_msg)
|
||||
{
|
||||
assert(fname);
|
||||
assert(handle);
|
||||
|
||||
*handle = dlopen(fname, flags);
|
||||
|
||||
if (NULL != err_msg) {
|
||||
if (NULL != *handle) {
|
||||
*err_msg = NULL;
|
||||
} else {
|
||||
*err_msg = dlerror();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int dlopen_open(const char *fname, bool use_ext, bool private_namespace,
|
||||
opal_dl_handle_t **handle, char **err_msg)
|
||||
{
|
||||
assert(fname);
|
||||
assert(handle);
|
||||
|
||||
*handle = NULL;
|
||||
|
||||
/* Setup the dlopen flags */
|
||||
int flags = RTLD_LAZY;
|
||||
if (private_namespace) {
|
||||
flags |= RTLD_LOCAL;
|
||||
} else {
|
||||
flags |= RTLD_GLOBAL;
|
||||
}
|
||||
|
||||
/* If the caller wants to use filename extensions, loop through
|
||||
them */
|
||||
void *local_handle = NULL;
|
||||
if (use_ext) {
|
||||
int i;
|
||||
char *ext;
|
||||
|
||||
for (i = 0, ext = mca_dl_dlopen_component.filename_suffixes[i];
|
||||
NULL != ext;
|
||||
ext = mca_dl_dlopen_component.filename_suffixes[++i]) {
|
||||
char *name;
|
||||
|
||||
asprintf(&name, "%s%s", fname, ext);
|
||||
if (NULL == name) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
|
||||
/* Does the file exist? */
|
||||
struct stat buf;
|
||||
if (stat(name, &buf) < 0) {
|
||||
free(name);
|
||||
if (NULL != err_msg) {
|
||||
*err_msg = "File not found";
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Yes, the file exists -- try to dlopen it. If we can't
|
||||
dlopen it, bail. */
|
||||
do_dlopen(name, flags, &local_handle, err_msg);
|
||||
free(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, the caller does not want to use filename extensions,
|
||||
so just use the single filename that the caller provided */
|
||||
else {
|
||||
do_dlopen(fname, flags, &local_handle, err_msg);
|
||||
}
|
||||
|
||||
if (NULL != local_handle) {
|
||||
*handle = calloc(1, sizeof(opal_dl_handle_t));
|
||||
(*handle)->dlopen_handle = local_handle;
|
||||
|
||||
#if OPAL_ENABLE_DEBUG
|
||||
(*handle)->filename = strdup(fname);
|
||||
#endif
|
||||
}
|
||||
return (NULL != local_handle) ? OPAL_SUCCESS : OPAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int dlopen_lookup(opal_dl_handle_t *handle, const char *symbol,
|
||||
void **ptr, char **err_msg)
|
||||
{
|
||||
assert(handle);
|
||||
assert(handle->dlopen_handle);
|
||||
assert(symbol);
|
||||
assert(ptr);
|
||||
|
||||
*ptr = dlsym(handle->dlopen_handle, symbol);
|
||||
if (NULL != *ptr) {
|
||||
return OPAL_SUCCESS;
|
||||
}
|
||||
|
||||
if (NULL != err_msg) {
|
||||
*err_msg = dlerror();
|
||||
}
|
||||
return OPAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
static int dlopen_close(opal_dl_handle_t *handle)
|
||||
{
|
||||
assert(handle);
|
||||
|
||||
int ret;
|
||||
ret = dlclose(handle->dlopen_handle);
|
||||
|
||||
#if OPAL_ENABLE_DEBUG
|
||||
free(handle->filename);
|
||||
#endif
|
||||
free(handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan all the files in a directory (or path) and invoke a callback
|
||||
* on each one.
|
||||
*/
|
||||
static int dlopen_foreachfile(const char *search_path,
|
||||
int (*func)(const char *filename, void *data),
|
||||
void *data)
|
||||
{
|
||||
int ret;
|
||||
DIR *dp = NULL;
|
||||
char **dirs = NULL;
|
||||
char **good_files = NULL;
|
||||
|
||||
dirs = opal_argv_split(search_path, OPAL_ENV_SEP);
|
||||
for (int i = 0; NULL != dirs[i]; ++i) {
|
||||
|
||||
dp = opendir(dirs[i]);
|
||||
if (NULL == dp) {
|
||||
return OPAL_ERR_IN_ERRNO;
|
||||
}
|
||||
|
||||
struct dirent *de;
|
||||
while (NULL != (de = readdir(dp))) {
|
||||
|
||||
/* Make the absolute path name */
|
||||
char *abs_name = NULL;
|
||||
asprintf(&abs_name, "%s/%s", dirs[i], de->d_name);
|
||||
if (NULL == abs_name) {
|
||||
ret = OPAL_ERR_IN_ERRNO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Stat the file */
|
||||
struct stat buf;
|
||||
if (stat(abs_name, &buf) < 0) {
|
||||
free(abs_name);
|
||||
ret = OPAL_ERR_IN_ERRNO;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Skip if not a file */
|
||||
if (!S_ISREG(buf.st_mode)) {
|
||||
free(abs_name);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Find the suffix */
|
||||
char *ptr = strrchr(abs_name, '.');
|
||||
if (NULL != ptr) {
|
||||
|
||||
/* Skip libtool files */
|
||||
if (strcmp(ptr, ".la") == 0 ||
|
||||
strcmp(ptr, ".lo") == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
/* Have we already found this file? Or already found a
|
||||
file with the same basename (but different suffix)? */
|
||||
if (NULL != good_files) {
|
||||
for (int j = 0; NULL != good_files[j]; ++j) {
|
||||
if (strcmp(good_files[j], abs_name) == 0) {
|
||||
free(abs_name);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
opal_argv_append_nosize(&good_files, abs_name);
|
||||
free(abs_name);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
dp = NULL;
|
||||
|
||||
/* Invoke the callback on all the found files */
|
||||
if (NULL != good_files) {
|
||||
for (int i = 0; NULL != good_files[i]; ++i) {
|
||||
ret = func(good_files[i], data);
|
||||
if (OPAL_SUCCESS != ret) {
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ret = OPAL_SUCCESS;
|
||||
|
||||
error:
|
||||
if (NULL != dp) {
|
||||
closedir(dp);
|
||||
}
|
||||
if (NULL != dirs) {
|
||||
opal_argv_free(dirs);
|
||||
}
|
||||
if (NULL != good_files) {
|
||||
opal_argv_free(good_files);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Module definition
|
||||
*/
|
||||
opal_dl_base_module_t opal_dl_dlopen_module = {
|
||||
.open = dlopen_open,
|
||||
.lookup = dlopen_lookup,
|
||||
.close = dlopen_close,
|
||||
.foreachfile = dlopen_foreachfile
|
||||
};
|
Загрузка…
x
Ссылка в новой задаче
Block a user