OW_SafeLibCreate.hpp

Go to the documentation of this file.
00001 /*******************************************************************************
00002 * Copyright (C) 2001-2004 Vintela, Inc. All rights reserved.
00003 *
00004 * Redistribution and use in source and binary forms, with or without
00005 * modification, are permitted provided that the following conditions are met:
00006 *
00007 *  - Redistributions of source code must retain the above copyright notice,
00008 *    this list of conditions and the following disclaimer.
00009 *
00010 *  - Redistributions in binary form must reproduce the above copyright notice,
00011 *    this list of conditions and the following disclaimer in the documentation
00012 *    and/or other materials provided with the distribution.
00013 *
00014 *  - Neither the name of Vintela, Inc. nor the names of its
00015 *    contributors may be used to endorse or promote products derived from this
00016 *    software without specific prior written permission.
00017 *
00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS
00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00028 * POSSIBILITY OF SUCH DAMAGE.
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> // for std::pair
00048 #include <setjmp.h> // for sigsetjmp, siglongjmp and jmp_buf
00049 
00050 // The classes and functions defined in this file are not meant for general
00051 // use, they are internal implementation details.  They may change at any time.
00052 
00053 // Note that using setjmp/longjmp will fail to reset the blocked signal mask after the first time this fails.
00054 // using sigsetjmp/siglongjmp fixes this problem.
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    // this is commented out because it won't compile.  As it is, it may
00191    // invoke undefined behavior if the C calling convention is different
00192    // from the C++ calling convention.  Fortunately that's not the case
00193    // with gcc :-)
00194    //extern "C" {
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    //} // extern "C"
00205    
00206 };
00207 template <typename T>
00208 jmp_buf SafeLibCreate<T>::theLoaderBuf;
00209    
00210 } // end namespace OW_NAMESPACE
00211 
00212 #endif
00213 

Generated on Thu Feb 9 08:48:10 2006 for openwbem by  doxygen 1.4.6