Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding a RAII class to promote an object containt a symbol to be dlopened with RTLD_GLOBAL #1000

Merged
merged 4 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/core/PlumedMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1091,7 +1091,7 @@ void PlumedMain::update() {
}
}

void PlumedMain::load(const std::string& fileName, const bool loadGlobal) {
void PlumedMain::load(const std::string& fileName) {
if(DLLoader::installed()) {
std::string libName=fileName;
size_t n=libName.find_last_of(".");
Expand All @@ -1118,7 +1118,7 @@ void PlumedMain::load(const std::string& fileName, const bool loadGlobal) {
base="./"+base;
}
libName=base+"."+config::getSoExt();
void *p=dlloader.load(libName,loadGlobal);
void *p=dlloader.load(libName);
if(!p) {
plumed_error()<<"I cannot load library " << fileName << " " << dlloader.error();
}
Expand Down
2 changes: 1 addition & 1 deletion src/core/PlumedMain.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,7 +368,7 @@ class PlumedMain:
/// Stop the run
void exit(int c=0);
/// Load a shared library
void load(const std::string&, bool=false);
void load(const std::string&);
/// Get the suffix string
const std::string & getSuffix()const;
/// Set the suffix string
Expand Down
5 changes: 1 addition & 4 deletions src/setup/Load.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,6 @@ PLUMED_REGISTER_ACTION(Load,"LOAD")
void Load::registerKeywords( Keywords& keys ) {
ActionSetup::registerKeywords(keys);
keys.add("compulsory","FILE","file to be loaded");
keys.addFlag("GLOBAL",false,"when selected the shared object is LOADed with RTLD_GLOBAL instead of RTLD_LOCAL");
}

Load::Load(const ActionOptions&ao):
Expand All @@ -115,10 +114,8 @@ Load::Load(const ActionOptions&ao):
{
std::string f;
parse("FILE",f);
bool loadWithGlobal=false;
parseFlag("GLOBAL",loadWithGlobal);
checkRead();
plumed.load(f,loadWithGlobal);
plumed.load(f);
}

}
Expand Down
45 changes: 39 additions & 6 deletions src/tools/DLLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
along with plumed. If not, see <http://www.gnu.org/licenses/>.
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */
#include "DLLoader.h"

#include <cstdlib>

#ifdef __PLUMED_HAS_DLOPEN
Expand All @@ -37,13 +38,9 @@ bool DLLoader::installed() {
}


void* DLLoader::load(const std::string&s, const bool useGlobal) {
void* DLLoader::load(const std::string&s) {
#ifdef __PLUMED_HAS_DLOPEN
void* p=nullptr;
if (useGlobal)
p=dlopen(s.c_str(),RTLD_NOW|RTLD_GLOBAL);
else
p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL);
void* p=dlopen(s.c_str(),RTLD_NOW|RTLD_LOCAL);
if(!p) {
lastError=dlerror();
} else {
Expand Down Expand Up @@ -79,5 +76,41 @@ DLLoader::DLLoader() {
// do nothing
}

DLLoader::EnsureGlobalDLOpen::EnsureGlobalDLOpen(const void *symbol) noexcept {
#ifdef __PLUMED_HAS_DLOPEN
#ifdef __PLUMED_HAS_DLADDR
Dl_info info;
// from the manual:
// If the address specified in addr could not be matched to a shared
// object, then these functions return 0. In this case, an error
// message is not available via dlerror(3).
int zeroIsError=dladdr(symbol, &info);
if(zeroIsError!=0) {
//This "promotes" to GLOBAL the object with the symbol pointed by ptr
handle_ = dlopen(info.dli_fname, RTLD_GLOBAL | RTLD_NOW);
} else {
std::fprintf(stderr,
"+++WARNING+++"
"Failure in finding any object that contains the symbol %p.\n",
symbol);

}
#else
std::fprintf(stderr,
"+++WARNING+++"
"I can't use dladdr for promoting the library containing the symbol %p.\n"
"This system seems not to support dladdr",
symbol);
#endif //__PLUMED_HAS_DLADDR
#endif //__PLUMED_HAS_DLOPEN
}

DLLoader::EnsureGlobalDLOpen::~EnsureGlobalDLOpen() {
#ifdef __PLUMED_HAS_DLOPEN
if (handle_) {
dlclose(handle_);
}
#endif //__PLUMED_HAS_DLOPEN
}

} // namespace PLMD
15 changes: 14 additions & 1 deletion src/tools/DLLoader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,24 @@ class DLLoader {
/// Cleanup
~DLLoader();
/// Load a library, returning its handle
void* load(const std::string&, bool=false);
void* load(const std::string&);
/// Returns the last error in dynamic loader
const std::string & error();
/// Returns true if the dynamic loader is available (on some systems it may not).
static bool installed();

/// RAII helper for promoting RTLD_LOCAL loaded objects to RTLD_GLOBAL
class EnsureGlobalDLOpen {
void* handle_=nullptr;
public:
/// makes sure that object defining ptr is globally available
explicit EnsureGlobalDLOpen(const void* symbol) noexcept;
/// dlclose the dlopened object
~EnsureGlobalDLOpen();
///Confevert a const reference to a
template<typename T> EnsureGlobalDLOpen(const T&p) noexcept
: EnsureGlobalDLOpen(reinterpret_cast<const void*>(p)) {}
};
};

} // namespace PLMD
Expand Down