#include <DLL_Manager.h>
Public Member Functions | |
ACE_DLL_Handle (void) | |
Default construtor. | |
~ACE_DLL_Handle (void) | |
Destructor. | |
const ACE_TCHAR * | dll_name () const |
Returns the name of the shared library (without prefixes or suffixes). | |
int | open (const ACE_TCHAR *dll_name, int open_mode, ACE_SHLIB_HANDLE handle) |
int | close (int unload=0) |
sig_atomic_t | refcount (void) const |
Return the current refcount. | |
void * | symbol (const ACE_TCHAR *symbol_name, int ignore_errors=0) |
ACE_SHLIB_HANDLE | get_handle (int become_owner=0) |
Private Member Functions | |
auto_ptr< ACE_TString > | error (void) |
void | get_dll_names (const ACE_TCHAR *dll_name, ACE_Array< ACE_TString > &try_names) |
ACE_DLL_Handle (const ACE_DLL_Handle &) | |
void | operator= (const ACE_DLL_Handle &) |
Private Attributes | |
sig_atomic_t | refcount_ |
ACE_TCHAR * | dll_name_ |
Name of the shared library. | |
ACE_SHLIB_HANDLE | handle_ |
Handle to the actual library loaded by the OS. | |
Static Private Attributes | |
sig_atomic_t | open_called_ = 0 |
This class is an wrapper over the various methods for utilizing a dynamically linked library (DLL), which is called a shared library on some platforms. It is refcounted and managed by ACE_DLL_Manager, so there will only be a single instance of this class for each dll loaded, no matter how many instances of ACE_DLL an application has open. Operations , , and have been implemented to help opening/closing and extracting symbol information from a DLL, respectively.
Most of this class came from the original ACE_DLL class. ACE_DLL is now just an interface that passed all it's calls either directly or via ACE_DLL_Manager to this class for execution.
Definition at line 59 of file DLL_Manager.h.
|
Default construtor.
Definition at line 27 of file DLL_Manager.cpp. References ACE_SHLIB_INVALID_HANDLE, and ACE_TRACE.
|
|
Destructor.
Definition at line 35 of file DLL_Manager.cpp. References ACE_TRACE, and close().
|
|
|
|
Call to close the DLL object. If unload = 0, it only decrements the refcount, but if unload = 1, then it will actually unload the library when the refcount == 0; Definition at line 217 of file DLL_Manager.cpp. References ACE_DEBUG, ACE_ERROR, ACE_GUARD_RETURN, ACE_LIB_TEXT, ACE_SHLIB_INVALID_HANDLE, ACE_TRACE, ACE::debug(), ACE_OS::dlclose(), ACE_Framework_Repository::instance(), LM_DEBUG, LM_ERROR, refcount_, and ACE_Framework_Repository::remove_dll_components(). Referenced by ACE_DLL_Manager::unload_dll(), and ~ACE_DLL_Handle().
00218 { 00219 ACE_TRACE ("ACE_DLL_Handle::close"); 00220 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00221 00222 int retval = 0; 00223 00224 // Since we don't actually unload the dll as soon as the refcount 00225 // reaches zero, we need to make sure we don't decrement it below 00226 // zero. 00227 if (this->refcount_ > 0) 00228 --this->refcount_; 00229 else 00230 this->refcount_ = 0; 00231 00232 if (ACE::debug ()) 00233 ACE_DEBUG ((LM_DEBUG, 00234 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::close: ") 00235 ACE_LIB_TEXT ("closing %s (%d), refcount is down to %d\n"), 00236 this->dll_name_, 00237 this->handle_, 00238 this->refcount_)); 00239 00240 if (this->refcount_ == 0 && 00241 this->handle_ != ACE_SHLIB_INVALID_HANDLE && 00242 unload == 1) 00243 { 00244 if (ACE::debug ()) 00245 ACE_DEBUG ((LM_DEBUG, 00246 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::close: ") 00247 ACE_LIB_TEXT ("Unloading %s (%d)\n"), 00248 this->dll_name_, 00249 this->handle_)); 00250 00251 // First remove any associated Framework Components. 00252 ACE_Framework_Repository * frPtr= ACE_Framework_Repository::instance (); 00253 00254 if (frPtr) 00255 { 00256 frPtr->remove_dll_components (this->dll_name_); 00257 } 00258 00259 retval = ACE_OS::dlclose (this->handle_); 00260 this->handle_ = ACE_SHLIB_INVALID_HANDLE; 00261 } 00262 00263 if (retval != 0) 00264 ACE_ERROR ((LM_ERROR, 00265 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::close: ") 00266 ACE_LIB_TEXT ("failed with: \"%s\".\n"), 00267 this->error ()->c_str ())); 00268 00269 return retval; 00270 } |
|
Returns the name of the shared library (without prefixes or suffixes).
Definition at line 43 of file DLL_Manager.cpp. References ACE_TRACE.
|
|
Returns a pointer to a string explaining why or failed. This is used internal to print out the error to the log, but since this object is shared, we can't store or return the error to the caller. Definition at line 355 of file DLL_Manager.cpp. References ACE_LIB_TEXT, ACE_TCHAR, ACE_TRACE, ACE_TString, and ACE_OS::dlerror(). Referenced by open(), and symbol().
00356 { 00357 ACE_TRACE ("ACE_DLL_Handle::error"); 00358 const ACE_TCHAR *error = ACE_OS::dlerror (); 00359 auto_ptr<ACE_TString> str 00360 (new ACE_TString (error ? error : ACE_LIB_TEXT ("no error"))); 00361 return str; 00362 } |
|
Definition at line 365 of file DLL_Manager.cpp. References ACE_DIRECTORY_SEPARATOR_CHAR, ACE_DLL_PREFIX, ACE_DLL_SUFFIX, ACE_LIB_TEXT, ACE_TCHAR, ACE_TString, ACE_String_Base< CHAR >::length(), ACE_Array_Base< T >::max_size(), ACE_String_Base< CHAR >::rfind(), ACE_Array_Base< T >::set(), ACE_Array_Base< T >::size(), ssize_t, and ACE_String_Base< CHAR >::substr(). Referenced by open().
00367 { 00368 // Build the array of DLL names to try on this platform by applying the 00369 // proper prefixes and/or suffixes to the specified dll_name. 00370 ACE_TString base (dll_name); 00371 ACE_TString base_dir, base_file, base_suffix; 00372 00373 // 1. Separate the dll_name into the dir part and the file part. We 00374 // only decorate the file part to determine the names to try loading. 00375 ssize_t pos = base.rfind (ACE_DIRECTORY_SEPARATOR_CHAR); 00376 if (pos != ACE_TString::npos) 00377 { 00378 base_dir = base.substr (0, pos + 1); 00379 base_file = base.substr (pos + 1); 00380 } 00381 else 00382 base_file = base; 00383 00384 // 2. Locate the file suffix, if there is one. Move the '.' and the 00385 // suffix to base_suffix. 00386 if ((pos = base_file.rfind (ACE_LIB_TEXT ('.'))) != ACE_TString::npos) 00387 { 00388 base_suffix = base_file.substr (pos); 00389 base_file = base_file.substr (0, pos); 00390 } 00391 00392 // 3. Build the combinations to try for this platform. 00393 // Try these combinations: 00394 // - name with decorator and platform's suffix appended (if not supplied) 00395 // - name with platform's suffix appended (if not supplied) 00396 // - name with platform's dll prefix (if it has one) and suffix 00397 // - name with platform's dll prefix, decorator, and suffix. 00398 // - name as originally given 00399 // We first try to find the file using the decorator so that when a 00400 // filename with and without decorator is used, we get the file with 00401 // the same decorator as the ACE dll has and then as last resort 00402 // the one without. For example with msvc, the debug build has a "d" 00403 // decorator, but the release build has none and we really want to get 00404 // the debug version of the library in a debug application instead 00405 // of the release one. 00406 // So we need room for 5 entries in try_names. 00407 try_names.size (0); 00408 if ((try_names.max_size () - try_names.size ()) < 5) 00409 try_names.max_size (try_names.max_size () + 5); 00410 #if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) 00411 ACE_TString decorator (ACE_LD_DECORATOR_STR); 00412 #endif 00413 ACE_TString suffix (ACE_DLL_SUFFIX); 00414 ACE_TString prefix (ACE_DLL_PREFIX); 00415 00416 for (size_t i = 0; i < 5 && try_names.size () < try_names.max_size (); ++i) 00417 { 00418 ACE_TString try_this; 00419 size_t j = try_names.size (); 00420 switch (i) 00421 { 00422 case 0: // Name + decorator + suffix 00423 case 1: // Name + suffix 00424 case 2: // Prefix + name + decorator + suffix 00425 case 3: // Prefix + name + suffix 00426 if ( 00427 base_suffix.length () > 0 00428 #if !(defined(ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)) 00429 || (i == 1 || i == 3) // No decorator desired; skip 00430 #endif 00431 ) 00432 break; 00433 try_this = base_dir; 00434 if (i > 1) 00435 try_this += prefix; 00436 try_this += base_file; 00437 if (base_suffix.length () > 0) 00438 try_this += base_suffix; 00439 else 00440 { 00441 #if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) 00442 try_this += decorator; 00443 #endif 00444 try_this += suffix; 00445 } 00446 break; 00447 case 4: 00448 try_this = dll_name; 00449 break; 00450 } 00451 00452 if (try_this.length ()) 00453 { 00454 try_names.size (j + 1); 00455 try_names.set (try_this, j); 00456 } 00457 } 00458 return; 00459 } |
|
Return the handle to the caller. If become_owner is non-0 then caller assumes ownership of the handle so we decrement the retcount. Definition at line 316 of file DLL_Manager.cpp. References ACE_DEBUG, ACE_ERROR, ACE_GUARD_RETURN, ACE_LIB_TEXT, ACE_SHLIB_HANDLE, ACE_SHLIB_INVALID_HANDLE, ACE_TRACE, ACE::debug(), LM_DEBUG, LM_ERROR, and refcount_. Referenced by ACE_DLL::get_handle().
00317 { 00318 ACE_TRACE ("ACE_DLL_Handle::get_handle"); 00319 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00320 00321 ACE_SHLIB_HANDLE handle = ACE_SHLIB_INVALID_HANDLE; 00322 00323 if (this->refcount_ == 0 && become_owner != 0) 00324 { 00325 if (ACE::debug ()) 00326 ACE_ERROR ((LM_ERROR, 00327 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::get_handle: ") 00328 ACE_LIB_TEXT ("cannot become owner, refcount == 0.\n"))); 00329 00330 return ACE_SHLIB_INVALID_HANDLE; 00331 } 00332 00333 handle = this->handle_; 00334 00335 if (become_owner != 0) 00336 { 00337 if (--this->refcount_ == 0) 00338 this->handle_ = ACE_SHLIB_INVALID_HANDLE; 00339 } 00340 00341 if (ACE::debug ()) 00342 ACE_DEBUG ((LM_DEBUG, 00343 ACE_LIB_TEXT ("ACE_DLL_Handle::get_handle: ") 00344 ACE_LIB_TEXT ("post call: handle %s, refcount %d\n"), 00345 this->handle_ == ACE_SHLIB_INVALID_HANDLE ? 00346 ACE_LIB_TEXT ("invalid") : ACE_LIB_TEXT ("valid"), 00347 this->refcount_)); 00348 00349 return handle; 00350 } |
|
This method opens and dynamically links dll_name. The default mode is , which loads identifier symbols but not the symbols for functions, which are loaded dynamically on-demand. Other supported modes include: , which performs all necessary relocations when dll_name is first loaded and , which makes symbols available for relocation processing of any other DLLs. Returns -1 on failure and 0 on success. Definition at line 50 of file DLL_Manager.cpp. References ACE_DEBUG, ACE_ERROR, ACE_GUARD_RETURN, ACE_LIB_TEXT, ACE_SHLIB_HANDLE, ACE_SHLIB_INVALID_HANDLE, ACE_TCHAR, ACE_TRACE, ACE_TString, ACE_Array_Iterator< T >::advance(), ACE_String_Base< CHAR >::c_str(), ACE::debug(), ACE_OS::dlopen(), error(), get_dll_names(), ACE::ldfind(), ACE_String_Base< CHAR >::length(), LM_DEBUG, LM_ERROR, ACE_Array_Base< T >::max_size(), MAXPATHLEN, ACE_Array_Iterator< T >::next(), open_called_, refcount_, ACE_Array_Base< T >::set(), ACE_Array_Base< T >::size(), ACE_OS::strcat(), ACE_OS::strcmp(), ACE_OS::strncpy(), ACE::strnew(), and ACE_String_Base< CHAR >::strstr(). Referenced by ACE_DLL_Manager::open_dll().
00053 { 00054 ACE_TRACE ("ACE_DLL_Handle::open"); 00055 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00056 00057 if (this->dll_name_) 00058 { 00059 // Once dll_name_ has been set, it can't be changed.. 00060 if (ACE_OS::strcmp (this->dll_name_, dll_name) != 0) 00061 { 00062 if (ACE::debug ()) 00063 ACE_ERROR ((LM_ERROR, 00064 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::open: error, ") 00065 ACE_LIB_TEXT ("tried to reopen %s with name %s\n"), 00066 this->dll_name_, 00067 dll_name)); 00068 00069 return -1; 00070 } 00071 } 00072 else 00073 this->dll_name_ = ACE::strnew (dll_name); 00074 00075 if (!this->open_called_) 00076 this->open_called_ = 1; 00077 00078 // If it hasn't been loaded yet, go ahead and do that now. 00079 if (this->handle_ == ACE_SHLIB_INVALID_HANDLE) 00080 { 00081 if (handle) 00082 this->handle_ = handle; 00083 else 00084 { 00085 /* 00086 ** Get the set of names to try loading. We need to do this to 00087 ** properly support the ability for a user to specify a simple, 00088 ** unadorned name (for example, "ACE") that will work across 00089 ** platforms. We apply platform specifics to get a name that will 00090 ** work (e.g. libACE, ACEd.dll, ACE.dll, etc.) We rely on the 00091 ** underlying dlopen() implementation to "Do The Right Thing" in 00092 ** terms of using relative paths, LD_LIBRARY_PATH, system security 00093 ** rules, etc. except when ACE_MUST_HELP_DLOPEN_SEARCH_PATH is set. 00094 ** If it is set, then ACE::ldfind() scans the configured path 00095 ** looking for a match on the name and prefix/suffix applications. 00096 ** NOTE: having ACE scan for a file and then pass a fully-qualified 00097 ** pathname to dlopen() is a potential security hole; therefore, 00098 ** do not use ACE_MUST_HELP_DLOPEN_SEARCH_PATH unless necessary 00099 ** and only after considering the risks. 00100 */ 00101 ACE_Array<ACE_TString> dll_names; 00102 dll_names.max_size (10); // Decent guess to avoid realloc later 00103 00104 #if defined (ACE_MUST_HELP_DLOPEN_SEARCH_PATH) 00105 // Find out where the library is 00106 ACE_TCHAR dll_pathname[MAXPATHLEN + 1]; 00107 00108 // Transform the pathname into the appropriate dynamic link library 00109 // by searching the ACE_LD_SEARCH_PATH. 00110 ACE::ldfind (dll_name, 00111 dll_pathname, 00112 (sizeof dll_pathname / sizeof (ACE_TCHAR))); 00113 ACE_TString dll_str (dll_pathname); 00114 dll_names.size (1); 00115 dll_names.set (dll_str, 0); 00116 #else 00117 this->get_dll_names (dll_name, dll_names); 00118 #endif 00119 00120 ACE_Array_Iterator<ACE_TString> name_iter (dll_names); 00121 ACE_TString *name = 0; 00122 while (name_iter.next (name)) 00123 { 00124 if (ACE::debug ()) 00125 ACE_DEBUG ((LM_DEBUG, 00126 ACE_LIB_TEXT ("(%P|%t) ACE_DLL_Handle::open: ") 00127 ACE_LIB_TEXT ("calling dlopen on ") 00128 ACE_LIB_TEXT ("\"%s\"\n"), name->c_str ())); 00129 00130 // The ACE_SHLIB_HANDLE object is obtained. 00131 this->handle_ = ACE_OS::dlopen (name->c_str (), 00132 open_mode); 00133 00134 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) // Good one? 00135 break; 00136 00137 // If errno is ENOENT we just skip over this one, 00138 // anything else - like an undefined symbol, for 00139 // instance must be flagged here or the next error will 00140 // mask it. 00141 // @TODO: If we've found our DLL _and_ it's 00142 // broken, should we continue at all? 00143 if (ACE::debug () && (errno != 0) && (errno != ENOENT)) 00144 ACE_ERROR ((LM_ERROR, 00145 ACE_LIB_TEXT ("(%P|%t) ACE_DLL_Handle::open: ") 00146 ACE_LIB_TEXT ("Attempt to open \'%s\' failed ") 00147 ACE_LIB_TEXT ("(%d): %s\n"), 00148 name->c_str (), 00149 errno, 00150 this->error ()->c_str ())); 00151 00152 #if defined (AIX) 00153 // AIX often puts the shared library file (most often named 00154 // shr.o) inside an archive library. If this is an archive 00155 // library name, then try appending [shr.o] and retry. 00156 if (ACE_TString::npos != name->strstr (ACE_LIB_TEXT (".a"))) 00157 { 00158 ACE_TCHAR aix_pathname[MAXPATHLEN + 1]; 00159 ACE_OS::strncpy (aix_pathname, 00160 name->c_str (), 00161 name->length ()); 00162 aix_pathname[name->length ()] = '\0'; 00163 ACE_OS::strcat (aix_pathname, ACE_LIB_TEXT ("(shr.o)")); 00164 open_mode |= RTLD_MEMBER; 00165 00166 if (ACE::debug ()) 00167 ACE_DEBUG ((LM_DEBUG, 00168 ACE_LIB_TEXT ("(%P|%t) ACE_DLL_Handle::open: ") 00169 ACE_LIB_TEXT ("calling dlopen on ") 00170 ACE_LIB_TEXT ("\"%s\"\n"), aix_pathname)); 00171 00172 this->handle_ = ACE_OS::dlopen (aix_pathname, open_mode); 00173 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00174 break; 00175 00176 // If errno is ENOENT we just skip over this one, anything 00177 // else - like an undefined symbol, for instance 00178 // must be flagged here or the next error will mask it. 00179 // 00180 // @TODO: If we've found our DLL _and_ it's broken, 00181 // should we continue at all? 00182 if (ACE::debug () && (errno != 0) && (errno != ENOENT)) 00183 ACE_ERROR ((LM_ERROR, 00184 ACE_LIB_TEXT ("(%P|%t) ACE_DLL_Handle::open: ") 00185 ACE_LIB_TEXT ("Attempt to open \'%s\' failed") 00186 ACE_LIB_TEXT (" (%d): %s\n"), 00187 name->c_str (), 00188 errno, 00189 this->error ()->c_str ())); 00190 00191 } 00192 #endif /* AIX */ 00193 00194 name_iter.advance (); 00195 } 00196 00197 if (this->handle_ == ACE_SHLIB_INVALID_HANDLE) 00198 { 00199 if (ACE::debug ()) 00200 ACE_ERROR ((LM_ERROR, 00201 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::open: ") 00202 ACE_LIB_TEXT ("Invalid handle while ") 00203 ACE_LIB_TEXT ("opening DLL \"%s\": %s\n"), 00204 this->dll_name_, 00205 this->error ()->c_str ())); 00206 00207 return -1; 00208 } 00209 } 00210 } 00211 00212 ++this->refcount_; 00213 return 0; 00214 } |
|
|
|
Return the current refcount.
Definition at line 273 of file DLL_Manager.cpp. References refcount_. Referenced by ACE_DLL_Manager::unload_policy().
00274 { 00275 return this->refcount_; 00276 } |
|
If symbol_name is in the symbol table of the DLL a pointer to the symbol_name is returned. Otherwise, returns 0. Set the ignore_errors flag to supress logging errors if symbol_name isn't found. This is nice if you just want to probe a dll to see what's available, since missing functions in that case aren't really errors. Definition at line 279 of file DLL_Manager.cpp. References ACE_ERROR, ACE_GUARD_RETURN, ACE_LIB_TEXT, ACE_SHLIB_INVALID_HANDLE, ACE_TCHAR, ACE_TRACE, ACE::debug(), ACE_OS::dlsym(), error(), ACE_Auto_Basic_Array_Ptr< X >::get(), and LM_ERROR. Referenced by ACE_DLL::symbol(), and ACE_DLL_Manager::unload_dll().
00280 { 00281 ACE_TRACE ("ACE_DLL_Handle::symbol"); 00282 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00283 00284 ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE::ldname (sym_name)); 00285 // handle_ can be invalid especially when ACE_DLL_Handle resigned ownership 00286 // BTW. Handle lifecycle management is a little crazy in ACE 00287 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00288 { 00289 #if defined (ACE_OPENVMS) 00290 void *sym = ACE::ldsymbol (this->handle_, auto_name.get ()); 00291 #else 00292 void *sym = ACE_OS::dlsym (this->handle_, auto_name.get ()); 00293 #endif 00294 00295 // Linux says that the symbol could be null and that it isn't an 00296 // error. So you should check the error message also, but since 00297 // null symbols won't do us much good anyway, let's still report 00298 // an error. 00299 if (!sym && ignore_errors != 1) 00300 { 00301 if (ACE::debug ()) 00302 ACE_ERROR ((LM_ERROR, 00303 ACE_LIB_TEXT ("(%P|%t) DLL_Handle::symbol (\"%s\") ") 00304 ACE_LIB_TEXT (" failed with \"%s\".\n"), 00305 auto_name.get (), 00306 this->error ()->c_str ())); 00307 00308 return 0; 00309 } 00310 return sym; 00311 } 00312 return 0; 00313 } |
|
Name of the shared library.
Definition at line 132 of file DLL_Manager.h. |
|
Handle to the actual library loaded by the OS.
Definition at line 135 of file DLL_Manager.h. |
|
Keeps track of whether or not open() has ever been called. This helps get around problem on Linux, and perhaps other OS's, that seg-fault if dlerror() is called before the ld library has been initialized by a call to dlopen(). Definition at line 25 of file DLL_Manager.cpp. Referenced by open(). |
|
Definition at line 129 of file DLL_Manager.h. Referenced by close(), get_handle(), open(), and refcount(). |