00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00035 #ifndef OW_SAFE_LIB_CREATE_HPP_INCLUDE_GUARD_
00036 #define OW_SAFE_LIB_CREATE_HPP_INCLUDE_GUARD_
00037 
00038 #include "OW_config.h"
00039 #include "OW_SharedLibraryReference.hpp"
00040 #include "OW_SharedLibrary.hpp"
00041 #include "OW_SharedLibraryLoader.hpp"
00042 #include "OW_Format.hpp"
00043 #include "OW_SignalScope.hpp"
00044 #include "OW_Exception.hpp"
00045 #include "OW_IntrusiveReference.hpp"
00046 
00047 #include <utility> 
00048 #include <setjmp.h> 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 namespace OW_NAMESPACE
00057 {
00058 
00060 template <typename T>
00061 class SafeLibCreate
00062 {
00063    typedef T* (*createFunc_t)();
00064    typedef const char* (*versionFunc_t)();
00065 public:
00066    typedef std::pair<IntrusiveReference<T>, SharedLibraryRef> return_type;
00067    typedef SharedLibraryReference<IntrusiveReference<T> > return_obj;
00068    
00069    static return_type
00070    loadAndCreate(String const& libname, String const& createFuncName,
00071       const LoggerRef& logger)
00072    {
00073       SharedLibraryLoaderRef sll =
00074          SharedLibraryLoader::createSharedLibraryLoader();
00075       SharedLibraryRef sl = sll->loadSharedLibrary(libname, logger);
00076       T* ptr = 0;
00077       if ( !sl.isNull() )
00078       {
00079          ptr = create(sl, createFuncName, logger);
00080       }
00081       else
00082       {
00083          OW_LOG_DEBUG(logger, Format("safeLibCreate::loadAndCreate"
00084             " FAILED loading library %1", libname));
00085       }
00086       return std::make_pair(IntrusiveReference<T>(ptr),sl);
00087    }
00088    static return_obj
00089    loadAndCreateObject(String const& libname,
00090       String const& createFuncName, const LoggerRef& logger)
00091    {
00092       SharedLibraryLoaderRef sll =
00093          SharedLibraryLoader::createSharedLibraryLoader();
00094       SharedLibraryRef sl = sll->loadSharedLibrary(libname, logger);
00095       T* ptr = 0;
00096       if ( sl )
00097       {
00098          ptr = create(sl, createFuncName, logger);
00099       }
00100       else
00101       {
00102          OW_LOG_DEBUG(logger, Format("safeLibCreate::loadAndCreate"
00103             " FAILED loading library %1", libname));
00104       }
00105       return return_obj(sl, ptr);
00106    }
00107    static T*
00108    create(SharedLibraryRef sl, String const& createFuncName,
00109       const LoggerRef& logger)
00110    {
00111       OW_LOG_DEBUG(logger, Format("safeLibCreate::create called.  createFuncName = %1",
00112          createFuncName).c_str());
00113       
00114       try
00115       {
00116          int sigtype;
00117          SignalScope r1( OW_SIGFPE,  theSignalHandler );
00118          SignalScope r3( OW_SIGSEGV, theSignalHandler );
00119 #ifdef SIGBUS // NetWare doesn't have this signal
00120          SignalScope r4( OW_SIGBUS,  theSignalHandler );
00121 #endif
00122          SignalScope r5( OW_SIGABRT, theSignalHandler );
00123 #ifdef WIN32
00124          sigtype = setjmp(theLoaderBuf);
00125 #else
00126          sigtype = sigsetjmp(theLoaderBuf, 1);
00127 #endif
00128          if ( sigtype == 0 )
00129          {
00130             versionFunc_t versFunc;
00131             if (!sl->getFunctionPointer( "getOWVersion", versFunc))
00132             {
00133                OW_LOG_ERROR(logger, "safeLibCreate::create failed getting"
00134                   " function pointer to \"getOWVersion\" from library");
00135    
00136                return 0;
00137             }
00138    
00139             const char* strVer = 0;
00140             strVer = (*versFunc)();
00141             if (!strVer || strncmp(strVer, OW_VERSION,strlen(OW_VERSION)) != 0)
00142             {
00143                OW_LOG_INFO(logger, Format("safeLibCreate::create - Warning: version returned from \"getOWVersion\""
00144                   " (%1) does not match (%2)", strVer ? strVer : "", OW_VERSION));
00145             }
00146 
00147             createFunc_t createFunc;
00148             if (!sl->getFunctionPointer( createFuncName
00149                , createFunc ))
00150             {
00151                OW_LOG_ERROR(logger, Format("safeLibCreate::create failed"
00152                   " getting function pointer to \"%1\" from"
00153                   " library", createFuncName));
00154 
00155                return 0;
00156             }
00157 
00158             T* ptr = (*createFunc)();
00159 
00160             return ptr;
00161          }
00162          else
00163          {
00164             OW_LOG_ERROR(logger, Format("safeLibCreate::create sigsetjmp call"
00165                " returned %1, we caught a segfault.  "
00166                "getOWVersion() or %2() is misbehaving", sigtype, createFuncName));
00167    
00168             return 0;
00169          }
00170       }
00171       catch(Exception& e)
00172       {
00173          OW_LOG_ERROR(logger, "safeLibCreate::create");
00174          OW_LOG_ERROR(logger, Format("File: %1", e.getFile()));
00175          OW_LOG_ERROR(logger, Format("Line: %1", e.getLine()));
00176          OW_LOG_ERROR(logger, Format("Msg: %1", e.getMessage()));
00177       }
00178       catch (...)
00179       {
00180          OW_LOG_ERROR(logger, "safeLibCreate::create caught unknown"
00181             " exception");
00182       }
00183    
00184       return 0;
00185    }
00186    
00187 private:
00188    static jmp_buf theLoaderBuf;
00189    
00190    
00191    
00192    
00193    
00194    
00195    static void theSignalHandler(int sig)
00196    {
00197 #ifdef WIN32
00198       longjmp(theLoaderBuf, sig);
00199 #else
00200       siglongjmp(theLoaderBuf, sig);
00201 #endif
00202    }
00203    
00204    
00205    
00206 };
00207 template <typename T>
00208 jmp_buf SafeLibCreate<T>::theLoaderBuf;
00209    
00210 } 
00211 
00212 #endif
00213