Skip to content

Commit

Permalink
Working on #784: util::plugin is throwing an error when a symbol is n…
Browse files Browse the repository at this point in the history
…ot found
  • Loading branch information
hkaiser committed Jun 13, 2013
1 parent 46de69d commit 3e6fe53
Show file tree
Hide file tree
Showing 9 changed files with 310 additions and 114 deletions.
5 changes: 4 additions & 1 deletion hpx/exception.hpp
Expand Up @@ -93,6 +93,7 @@ namespace hpx
duplicate_component_id = 46, ///< The component type has already been registered
unknown_error = 47, ///< An unknown error occurred
bad_plugin_type = 48, ///< The specified plugin type is not known or otherwise invalid
filesystem_error = 49, ///< The specified file does not exist or other filesystem related error

/// \cond NOINTERNAL
last_error,
Expand Down Expand Up @@ -150,7 +151,9 @@ namespace hpx
/* 44 */ "thread_interrupted",
/* 45 */ "thread_not_interruptable",
/* 46 */ "duplicate_component_id",
/* 47 */ "unknown_error"
/* 47 */ "unknown_error",
/* 48 */ "bad_plugin_type",
/* 49 */ "filesystem_error",
/* */ ""
};
/// \endcond
Expand Down
6 changes: 4 additions & 2 deletions hpx/runtime/components/server/runtime_support.hpp
Expand Up @@ -295,9 +295,11 @@ namespace hpx { namespace components { namespace server
boost::program_options::options_description& options,
std::set<std::string>& startup_handled);

bool load_startup_shutdown_functions(hpx::util::plugin::dll& d);
bool load_startup_shutdown_functions(hpx::util::plugin::dll& d,
error_code& ec);
bool load_commandline_options(hpx::util::plugin::dll& d,
boost::program_options::options_description& options);
boost::program_options::options_description& options,
error_code& ec);

// Load all plugins from the ini files found in the configuration
bool load_plugins(util::section& ini);
Expand Down
93 changes: 57 additions & 36 deletions hpx/util/plugin/detail/dll_dlopen.hpp
Expand Up @@ -22,6 +22,7 @@
#include <boost/filesystem/convenience.hpp>
#include <boost/throw_exception.hpp>

#include <hpx/exception.hpp>
#include <hpx/util/plugin/config.hpp>

#if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__APPLE__)
Expand Down Expand Up @@ -124,15 +125,11 @@ namespace hpx { namespace util { namespace plugin {
public:
dll()
: dll_handle (NULL)
{
LoadLibrary();
}
{}

dll(dll const& rhs)
: dll_name(rhs.dll_name), map_name(rhs.map_name), dll_handle(NULL)
{
LoadLibrary();
}
{}

dll(std::string const& name)
: dll_name(name), map_name(""), dll_handle(NULL)
Expand All @@ -146,15 +143,16 @@ namespace hpx { namespace util { namespace plugin {
fs::path dll_path(dll_name);
#endif
map_name = fs::basename(dll_path);
}

LoadLibrary();
void load_library(error_code& ec = throws)
{
LoadLibrary(ec);
}

dll(std::string const& libname, std::string const& mapname)
: dll_name(libname), map_name(mapname), dll_handle(NULL)
{
LoadLibrary();
}
{}

dll &operator=(dll const& rhs)
{
Expand All @@ -180,8 +178,11 @@ namespace hpx { namespace util { namespace plugin {

template<typename SymbolType, typename Deleter>
std::pair<SymbolType, Deleter>
get(std::string const& symbol_name) const
get(std::string const& symbol_name, error_code& ec = throws) const
{
const_cast<dll&>(*this).LoadLibrary(ec); // make sure everything is initialized
if (ec) return std::pair<SymbolType, Deleter>();

initialize_mutex();
boost::mutex::scoped_lock lock(mutex_instance());

Expand All @@ -199,8 +200,10 @@ namespace hpx { namespace util { namespace plugin {
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "' (dlerror: " << dlerror() << ")";

boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));
// report error
HPX_THROWS_IF(ec, filesystem_error,
"plugin::get", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return std::pair<SymbolType, Deleter>();
}

#if !defined(__AIX__)
Expand All @@ -225,55 +228,73 @@ namespace hpx { namespace util { namespace plugin {

dlerror();
MyFreeLibrary(handle);
boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));

// report error
HPX_THROWS_IF(ec, filesystem_error,
"plugin::get", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return std::pair<SymbolType, Deleter>();
}
return std::make_pair(address, free_dll<SymbolType>(handle));
}

void keep_alive()
void keep_alive(error_code& ec = throws)
{
LoadLibrary();
LoadLibrary(ec, true);
}

protected:
void LoadLibrary()
void LoadLibrary(error_code& ec = throws, bool force = false)
{
initialize_mutex();
boost::mutex::scoped_lock lock(mutex_instance());
if (!dll_handle || force)
initialize_mutex();
boost::mutex::scoped_lock lock(mutex_instance());

::dlerror(); // Clear the error state.
dll_handle = MyLoadLibrary((dll_name.empty() ? NULL : dll_name.c_str()));
// std::cout << "open\n";
if (!dll_handle) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "' (dlerror: " << dlerror() << ")";
boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));
::dlerror(); // Clear the error state.
dll_handle = MyLoadLibrary((dll_name.empty() ? NULL : dll_name.c_str()));
// std::cout << "open\n";
if (!dll_handle) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "' (dlerror: " << dlerror() << ")";

HPX_THROWS_IF(ec, filesystem_error,
"plugin::LoadLibrary", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return;
}

init_library(dll_handle); // initialize library
}

init_library(dll_handle); // initialize library
if (&ec != &throws)
ec = make_success_code();
}

public:
#if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__APPLE__)
std::string get_directory() const
{
// now find the full path of the loaded library
char directory[PATH_MAX];
if (::dlinfo(dll_handle, RTLD_DI_ORIGIN, directory) < 0) {
char directory[PATH_MAX] = { '\0' };

#if !defined(__ANDROID__) && !defined(ANDROID) && !defined(__APPLE__)
const_cast<dll&>(*this).LoadLibrary(ec);
if (!ec && ::dlinfo(dll_handle, RTLD_DI_ORIGIN, directory) < 0) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not extract path the shared "
"library '" << dll_name << "' has been loaded from "
"(dlerror: " << dlerror() << ")";
boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));

HPX_THROWS_IF(ec, filesystem_error,
"plugin::get_directory",
HPX_PLUGIN_OSSTREAM_GETSTRING(str));
}
::dlerror(); // Clear the error state.
#endif

if (&ec != &throws)
ec = make_success_code();

return directory;
}
#endif

protected:
void FreeLibrary()
Expand Down
97 changes: 61 additions & 36 deletions hpx/util/plugin/detail/dll_windows.hpp
Expand Up @@ -21,6 +21,7 @@
#include <boost/throw_exception.hpp>

#include <hpx/util/plugin/config.hpp>
#include <hpx/exception.hpp>

#include <windows.h>
#include <Shlwapi.h>
Expand Down Expand Up @@ -54,15 +55,11 @@ namespace hpx { namespace util { namespace plugin {
public:
dll()
: dll_handle(NULL)
{
LoadLibrary();
}
{}

dll(dll const& rhs)
: dll_name(rhs.dll_name), map_name(rhs.map_name), dll_handle(NULL)
{
LoadLibrary();
}
{}

dll(std::string const& libname)
: dll_name(libname), map_name(""), dll_handle(NULL)
Expand All @@ -76,15 +73,16 @@ namespace hpx { namespace util { namespace plugin {
fs::path dll_path(dll_name);
#endif
map_name = fs::basename(dll_path);
}

LoadLibrary();
void load_library(error_code& ec = throws)
{
LoadLibrary(ec);
}

dll(std::string const& libname, std::string const& mapname)
: dll_name(libname), map_name(mapname), dll_handle(NULL)
{
LoadLibrary();
}
{}

dll &operator=(dll const& rhs)
{
Expand All @@ -110,8 +108,11 @@ namespace hpx { namespace util { namespace plugin {

template<typename SymbolType, typename Deleter>
std::pair<SymbolType, Deleter>
get(std::string const& symbol_name) const
get(std::string const& symbol_name, error_code& ec = throws) const
{
const_cast<dll&>(*this).LoadLibrary(ec); // make sure everything is initialized
if (ec) return std::pair<SymbolType, Deleter>();

BOOST_STATIC_ASSERT(boost::is_pointer<SymbolType>::value);
typedef typename boost::remove_pointer<SymbolType>::type PointedType;

Expand All @@ -125,8 +126,10 @@ namespace hpx { namespace util { namespace plugin {
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "'";

boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));
// report error
HPX_THROWS_IF(ec, filesystem_error,
"plugin::get", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return std::pair<SymbolType, Deleter>();
}
BOOST_ASSERT(handle == dll_handle);

Expand All @@ -140,54 +143,76 @@ namespace hpx { namespace util { namespace plugin {
<< dll_name << "'";

::FreeLibrary(handle);
boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));

// report error
HPX_THROWS_IF(ec, filesystem_error,
"plugin::get", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return std::pair<SymbolType, Deleter>();
}
return std::make_pair(address, detail::free_dll<SymbolType>(handle));
}

void keep_alive()
void keep_alive(error_code& ec = throws)
{
LoadLibrary();
LoadLibrary(ec, true);
}

protected:
void LoadLibrary()
void LoadLibrary(error_code& ec = throws, bool force = false)
{
if (dll_name.empty()) {
// load main module
char buffer[_MAX_PATH];
::GetModuleFileName(NULL, buffer, sizeof(buffer));
dll_name = buffer;
if (!dll_handle || force)
{
if (dll_name.empty()) {
// load main module
char buffer[_MAX_PATH];
::GetModuleFileName(NULL, buffer, sizeof(buffer));
dll_name = buffer;
}

dll_handle = ::LoadLibrary(dll_name.c_str());
if (!dll_handle) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "'";

HPX_THROWS_IF(ec, filesystem_error,
"plugin::LoadLibrary",
HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return;
}
}

dll_handle = ::LoadLibrary(dll_name.c_str());
if (!dll_handle) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not open shared library '"
<< dll_name << "'";

boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));
}
if (&ec != &throws)
ec = make_success_code();
}

public:
std::string get_directory() const
std::string get_directory(error_code& ec = throws) const
{
char buffer[_MAX_PATH];
char buffer[_MAX_PATH] = { '\0' };

const_cast<dll&>(*this).LoadLibrary(ec); // make sure everything is initialized
if (ec) return buffer;

DWORD name_length =
GetModuleFileName(dll_handle, buffer, sizeof(buffer));

if (name_length <= 0) {
HPX_PLUGIN_OSSTREAM str;
str << "Hpx.Plugin: Could not extract path the shared "
"library '" << dll_name << "' has been loaded from.";
boost::throw_exception(
std::logic_error(HPX_PLUGIN_OSSTREAM_GETSTRING(str)));

HPX_THROWS_IF(ec, filesystem_error,
"plugin::get_directory", HPX_PLUGIN_OSSTREAM_GETSTRING(str));
return buffer;
}

// extract the directory name
PathRemoveFileSpec(buffer);

if (&ec != &throws)
ec = make_success_code();

return buffer;
}

Expand Down

0 comments on commit 3e6fe53

Please sign in to comment.