From e1dff473a625cdbecbaddb89d48fc675efea09f0 Mon Sep 17 00:00:00 2001 From: Gabriele Svelto Date: Tue, 8 May 2012 20:17:01 +0200 Subject: Enabled plug-in loading on all hosts with support for dlopen() Previously the code used for loading plug-ins would be built only on Linux hosts. Now the required functions are checked for and plug-in loading code is enabled if those are present on all platforms. Using lstat() to check for file types also increases portability to hosts that do not have the dirent.d_type field. If shared libraries support is disabled plug-ins will also be automatically disabled. Signed-off-by: Gabriele Svelto --- configure.ac | 36 ++++++++++++++++++++++++++++++++++-- src/ctx.cpp | 45 ++++++++++++++++++++++++++++++++------------- src/ctx.hpp | 7 +++---- 3 files changed, 69 insertions(+), 19 deletions(-) diff --git a/configure.ac b/configure.ac index 339cc37..50b4457 100644 --- a/configure.ac +++ b/configure.ac @@ -99,8 +99,6 @@ AS_CASE(["${host_os}"], AC_DEFINE([XS_HAVE_ANDROID], [1], [Have Android OS]) ] ) - - AC_CHECK_LIB([dl], [dlopen]) ], [*solaris*], [ AC_DEFINE([XS_HAVE_SOLARIS], [1], [Have Solaris OS]) @@ -191,7 +189,11 @@ LIBXS_CHECK_DOC_BUILD # Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS([ \ + link.h \ + dirent.h \ + dlfcn.h \ errno.h \ + fcntl.h \ arpa/inet.h \ netinet/tcp.h \ netinet/in.h \ @@ -199,6 +201,7 @@ AC_CHECK_HEADERS([ \ stdlib.h \ string.h \ sys/socket.h \ + sys/stat.h \ sys/time.h \ sys/types.h \ time.h \ @@ -374,6 +377,34 @@ AS_IF([test "x$enable_libzmq" != "xno"], [ libxs_libzmq="yes" ]) +# Plug-in support +AC_ARG_ENABLE([plugins], [AS_HELP_STRING([--enable-plugins], + [enable plugins [default=auto]])], + [enable_plugins=$enableval], [enable_plugins=auto]) + +AS_IF([test "x$enable_plugins" != "xno"], [ + # Check if libdl is required, then check for dlopen and lstat, they are + # both needed to enable plug-in support + AC_SEARCH_LIBS([dlopen], [dl]) + AC_CHECK_FUNCS([lstat dlopen], [], [ + AS_IF([test "x$enable_plugins" = "xyes"], [ + AC_MSG_ERROR([Plugins support not available]) + ], [ + AC_MSG_WARN([Plugins support disabled]) + enable_plugins=no + ]) + ]) + + # If shared library support is disabled disable plugins support + AS_IF([test "x$enable_shared" = "xno"], [ + AC_MSG_WARN([Shared library support disabled, disabling plug-ins]) + enable_plugins=no + ], [ + enable_plugins=yes + AC_DEFINE([XS_HAVE_PLUGINS], [1], [Whether plugins support is enabled]) + ]) +]) + # PGM extension libxs_pgm_ext="no" @@ -525,6 +556,7 @@ Configuration for $PACKAGE_STRING Polling system: $libxs_cv_poller Disable eventfd: $xs_disable_eventfd Build libzmq compatibility library and headers: $libxs_libzmq + Plugins support: $enable_plugins PGM extension: $with_pgm_ext Use system-provided PGM library: $with_system_pgm_ext Build documentation: $libxs_build_doc diff --git a/src/ctx.cpp b/src/ctx.cpp index f5d9719..063f96c 100644 --- a/src/ctx.cpp +++ b/src/ctx.cpp @@ -23,12 +23,27 @@ #if defined XS_HAVE_WINDOWS #include "windows.hpp" #else -#include -#endif - -#if defined XS_HAVE_LINUX -#include -#include +# if HAVE_UNISTD_H +# include +# endif +# if HAVE_SYS_TYPES_H +# include +# endif +# if HAVE_SYS_STAT_H +# include +# endif +# if HAVE_DLFCN_H +# include +# endif +# if HAVE_LINK_H +# include +# endif +# if HAVE_FCNTL_H +# include +# endif +# if HAVE_DIRENT_H +# include +# endif #endif #include @@ -114,7 +129,7 @@ next: BOOL brc = FindClose (fh); win_assert (brc != 0); -#elif defined XS_HAVE_LINUX +#elif XS_HAVE_PLUGINS // Load all the installed plug-ins. std::string path (XS_PREFIX_PATH); @@ -126,12 +141,17 @@ next: errno_assert (dp); dirent dir, *dirp; + struct stat stats; + while (true) { rc = readdir_r (dp, &dir, &dirp); assert (rc == 0); if (!dirp) break; - if (dir.d_type == DT_REG) { + + rc = lstat (dirp->d_name, &stats); + + if ((rc == 0) && S_ISREG (stats.st_mode)) { // Ignore the files without .xsp extension. std::string file = dir.d_name; @@ -139,7 +159,7 @@ next: continue; if (file.substr (file.size () - 4) != ".xsp") continue; - + // Open the specified dynamic library. std::string filename = path + "/" + file; void *dl = dlopen (filename.c_str (), RTLD_LOCAL | RTLD_NOW); @@ -260,7 +280,7 @@ int xs::ctx_t::terminate () it != plugins.end (); ++it) FreeLibrary (*it); opt_sync.unlock (); -#elif defined XS_HAVE_LINUX +#elif XS_HAVE_PLUGINS opt_sync.lock (); for (plugins_t::iterator it = plugins.begin (); it != plugins.end (); ++it) @@ -412,7 +432,7 @@ void xs::ctx_t::destroy_socket (class socket_base_t *socket_) // Free the associared thread slot. uint32_t tid = socket_->get_tid (); empty_slots.push_back (tid); - slots [tid] = NULL; + slots [tid] = NULL; // Remove the socket from the list of sockets. sockets.erase (socket_); @@ -497,7 +517,7 @@ void xs::ctx_t::unregister_endpoints (socket_base_t *socket_) } ++it; } - + endpoints_sync.unlock (); } @@ -528,4 +548,3 @@ xs::endpoint_t xs::ctx_t::find_endpoint (const char *addr_) // is a global variable. Thus, even sockets created in different contexts have // unique IDs. xs::atomic_counter_t xs::ctx_t::max_socket_id; - diff --git a/src/ctx.hpp b/src/ctx.hpp index 7b0b74b..8e2fd03 100644 --- a/src/ctx.hpp +++ b/src/ctx.hpp @@ -54,7 +54,7 @@ namespace xs // Context object encapsulates all the global state associated with // the library. - + class ctx_t { public: @@ -173,7 +173,7 @@ namespace xs #if defined XS_HAVE_WINDOWS typedef std::vector plugins_t; plugins_t plugins; -#elif defined XS_HAVE_LINUX +#elif defined XS_HAVE_PLUGINS typedef std::vector plugins_t; plugins_t plugins; #endif @@ -185,8 +185,7 @@ namespace xs ctx_t (const ctx_t&); const ctx_t &operator = (const ctx_t&); }; - + } #endif - -- cgit v1.2.3