#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 238 of file DLL_Manager.cpp. References ACE_DEBUG, ACE_ERROR, ACE_GUARD_RETURN, ACE_SHLIB_HANDLE, ACE_SHLIB_INVALID_HANDLE, ACE_TEXT, ACE_TRACE, ACE::debug(), ACE_OS::dlclose(), handle_, 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().
00239 { 00240 ACE_TRACE ("ACE_DLL_Handle::close"); 00241 00242 int retval = 0; 00243 ACE_SHLIB_HANDLE h = ACE_SHLIB_INVALID_HANDLE; 00244 00245 // Only hold the lock until it comes time to dlclose() the DLL. Closing 00246 // the DLL can cause further shutdowns as DLLs and their dependents are 00247 // unloaded. 00248 { 00249 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00250 00251 // Since we don't actually unload the dll as soon as the refcount 00252 // reaches zero, we need to make sure we don't decrement it below 00253 // zero. 00254 if (this->refcount_ > 0) 00255 --this->refcount_; 00256 else 00257 this->refcount_ = 0; 00258 00259 if (ACE::debug ()) 00260 ACE_DEBUG ((LM_DEBUG, 00261 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ") 00262 ACE_TEXT ("%s (handle=%d, refcount=%d)\n"), 00263 this->dll_name_, 00264 this->handle_, 00265 this->refcount_)); 00266 00267 if (this->refcount_ == 0 && 00268 this->handle_ != ACE_SHLIB_INVALID_HANDLE && 00269 unload == 1) 00270 { 00271 if (ACE::debug ()) 00272 ACE_DEBUG ((LM_DEBUG, 00273 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close: ") 00274 ACE_TEXT ("Unloading %s (handle=%d)\n"), 00275 this->dll_name_, 00276 this->handle_)); 00277 00278 // First remove any associated Framework Components. 00279 ACE_Framework_Repository *frPtr= ACE_Framework_Repository::instance (); 00280 if (frPtr) 00281 { 00282 frPtr->remove_dll_components (this->dll_name_); 00283 } 00284 00285 h = this->handle_; 00286 this->handle_ = ACE_SHLIB_INVALID_HANDLE; 00287 } 00288 } // Release lock_ here 00289 00290 if (h != ACE_SHLIB_INVALID_HANDLE) 00291 { 00292 retval = ACE_OS::dlclose (h); 00293 00294 if (retval != 0 && ACE::debug ()) 00295 ACE_ERROR ((LM_ERROR, 00296 ACE_TEXT ("ACE (%P|%t) DLL_Handle::close - ") 00297 ACE_TEXT ("Failed with: \"%s\".\n"), 00298 this->error ()->c_str ())); 00299 } 00300 00301 return retval; 00302 } |
|
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 385 of file DLL_Manager.cpp. References ACE_TCHAR, ACE_TEXT, ACE_TRACE, ACE_TString, and ACE_OS::dlerror(). Referenced by open(), and symbol().
00386 { 00387 ACE_TRACE ("ACE_DLL_Handle::error"); 00388 const ACE_TCHAR *error = ACE_OS::dlerror (); 00389 auto_ptr<ACE_TString> str 00390 (new ACE_TString (error ? error : ACE_TEXT ("no error"))); 00391 return str; 00392 } |
|
Definition at line 395 of file DLL_Manager.cpp. References ACE_DIRECTORY_SEPARATOR_CHAR, ACE_DLL_PREFIX, ACE_DLL_SUFFIX, ACE_TCHAR, ACE_TEXT, 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(), and ACE_String_Base< CHAR >::substr(). Referenced by open().
00397 { 00398 // Build the array of DLL names to try on this platform by applying the 00399 // proper prefixes and/or suffixes to the specified dll_name. 00400 ACE_TString base (dll_name); 00401 ACE_TString base_dir, base_file, base_suffix; 00402 00403 // 1. Separate the dll_name into the dir part and the file part. We 00404 // only decorate the file part to determine the names to try loading. 00405 ACE_TString::size_type pos = base.rfind (ACE_DIRECTORY_SEPARATOR_CHAR); 00406 if (pos != ACE_TString::npos) 00407 { 00408 base_dir = base.substr (0, pos + 1); 00409 base_file = base.substr (pos + 1); 00410 } 00411 else 00412 base_file = base; 00413 00414 // 2. Locate the file suffix, if there is one. Move the '.' and the 00415 // suffix to base_suffix. 00416 if ((pos = base_file.rfind (ACE_TEXT ('.'))) != ACE_TString::npos) 00417 { 00418 base_suffix = base_file.substr (pos); 00419 base_file = base_file.substr (0, pos); 00420 } 00421 00422 // 3. Build the combinations to try for this platform. 00423 // Try these combinations: 00424 // - name with decorator and platform's suffix appended (if not supplied) 00425 // - name with platform's suffix appended (if not supplied) 00426 // - name with platform's dll prefix (if it has one) and suffix 00427 // - name with platform's dll prefix, decorator, and suffix. 00428 // - name as originally given 00429 // We first try to find the file using the decorator so that when a 00430 // filename with and without decorator is used, we get the file with 00431 // the same decorator as the ACE dll has and then as last resort 00432 // the one without. For example with msvc, the debug build has a "d" 00433 // decorator, but the release build has none and we really want to get 00434 // the debug version of the library in a debug application instead 00435 // of the release one. 00436 // So we need room for 5 entries in try_names. 00437 try_names.size (0); 00438 if ((try_names.max_size () - try_names.size ()) < 5) 00439 try_names.max_size (try_names.max_size () + 5); 00440 #if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) 00441 ACE_TString decorator (ACE_LD_DECORATOR_STR); 00442 #endif 00443 ACE_TString suffix (ACE_DLL_SUFFIX); 00444 ACE_TString prefix (ACE_DLL_PREFIX); 00445 00446 for (size_t i = 0; i < 5 && try_names.size () < try_names.max_size (); ++i) 00447 { 00448 ACE_TString try_this; 00449 size_t j = try_names.size (); 00450 switch (i) 00451 { 00452 case 0: // Name + decorator + suffix 00453 case 1: // Name + suffix 00454 case 2: // Prefix + name + decorator + suffix 00455 case 3: // Prefix + name + suffix 00456 if ( 00457 base_suffix.length () > 0 00458 #if !(defined(ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK)) 00459 || (i == 1 || i == 3) // No decorator desired; skip 00460 #endif 00461 ) 00462 break; 00463 try_this = base_dir; 00464 if (i > 1) 00465 try_this += prefix; 00466 try_this += base_file; 00467 if (base_suffix.length () > 0) 00468 try_this += base_suffix; 00469 else 00470 { 00471 #if defined (ACE_WIN32) && defined (ACE_LD_DECORATOR_STR) && !defined (ACE_DISABLE_DEBUG_DLL_CHECK) 00472 try_this += decorator; 00473 #endif 00474 try_this += suffix; 00475 } 00476 break; 00477 case 4: 00478 try_this = dll_name; 00479 break; 00480 } 00481 00482 if (try_this.length ()) 00483 { 00484 try_names.size (j + 1); 00485 try_names.set (try_this, j); 00486 } 00487 } 00488 return; 00489 } |
|
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 348 of file DLL_Manager.cpp. References ACE_DEBUG, ACE_ERROR, ACE_GUARD_RETURN, ACE_SHLIB_HANDLE, ACE_SHLIB_INVALID_HANDLE, ACE_TEXT, ACE_TRACE, ACE::debug(), handle_, LM_DEBUG, LM_ERROR, and refcount_. Referenced by ACE_DLL::get_handle().
00349 { 00350 ACE_TRACE ("ACE_DLL_Handle::get_handle"); 00351 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00352 00353 if (this->refcount_ == 0 && become_owner != 0) 00354 { 00355 if (ACE::debug ()) 00356 ACE_ERROR ((LM_ERROR, 00357 ACE_TEXT ("ACE (%P|%t) DLL_Handle::get_handle: ") 00358 ACE_TEXT ("cannot become owner, refcount == 0.\n"))); 00359 00360 return ACE_SHLIB_INVALID_HANDLE; 00361 } 00362 00363 ACE_SHLIB_HANDLE handle = this->handle_; 00364 00365 if (become_owner != 0) 00366 { 00367 if (--this->refcount_ == 0) 00368 this->handle_ = ACE_SHLIB_INVALID_HANDLE; 00369 } 00370 00371 if (ACE::debug ()) 00372 ACE_DEBUG ((LM_DEBUG, 00373 ACE_TEXT ("ACE (%P|%t) ACE_DLL_Handle::get_handle: ") 00374 ACE_TEXT ("post call: handle %s, refcount %d\n"), 00375 this->handle_ == ACE_SHLIB_INVALID_HANDLE ? 00376 ACE_TEXT ("invalid") : ACE_TEXT ("valid"), 00377 this->refcount_)); 00378 00379 return handle; 00380 } |
|
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_SHLIB_HANDLE, ACE_SHLIB_INVALID_HANDLE, ACE_TCHAR, ACE_TEXT, ACE_TRACE, ACE_TString, ACE_Array_Iterator< T >::advance(), ACE_String_Base< CHAR >::c_str(), ACE::debug(), ACE_OS::dlopen(), error(), get_dll_names(), handle_, 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_TEXT ("(%P|%t) DLL_Handle::open: error, ") 00065 ACE_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 // The ACE_SHLIB_HANDLE object is obtained. 00125 this->handle_ = ACE_OS::dlopen (name->c_str (), 00126 open_mode); 00127 00128 if (ACE::debug ()) 00129 { 00130 ACE_DEBUG ((LM_DEBUG, 00131 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ") 00132 ACE_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"), 00133 name->c_str (), 00134 open_mode, 00135 ((this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00136 ? ACE_TEXT ("succeeded") 00137 : ACE_TEXT ("failed")), 00138 this->error()->c_str())); 00139 } 00140 00141 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) // Good one? 00142 break; 00143 00144 // If errno is ENOENT we just skip over this one, 00145 // anything else - like an undefined symbol, for 00146 // instance must be flagged here or the next error will 00147 // mask it. 00148 // @TODO: If we've found our DLL _and_ it's 00149 // broken, should we continue at all? 00150 if ((errno != 0) && (errno != ENOENT) && ACE::debug ()) 00151 ACE_ERROR ((LM_ERROR, 00152 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ") 00153 ACE_TEXT ("(\'%s\') failed, errno=") 00154 ACE_TEXT ("%d: %s\n"), 00155 name->c_str (), 00156 errno, 00157 this->error ()->c_str ())); 00158 00159 #if defined (AIX) 00160 // AIX often puts the shared library file (most often named 00161 // shr.o) inside an archive library. If this is an archive 00162 // library name, then try appending [shr.o] and retry. 00163 if (ACE_TString::npos != name->strstr (ACE_TEXT (".a"))) 00164 { 00165 ACE_TCHAR aix_pathname[MAXPATHLEN + 1]; 00166 ACE_OS::strncpy (aix_pathname, 00167 name->c_str (), 00168 name->length ()); 00169 aix_pathname[name->length ()] = '\0'; 00170 ACE_OS::strcat (aix_pathname, ACE_TEXT ("(shr.o)")); 00171 open_mode |= RTLD_MEMBER; 00172 00173 if (ACE::debug ()) 00174 { 00175 ACE_DEBUG ((LM_DEBUG, 00176 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ") 00177 ACE_TEXT ("(\"%s\", 0x%x) -> %s: %s\n"), 00178 aix_pathname, 00179 open_mode, 00180 ACE_TEXT ((this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00181 ? "succeeded" 00182 : "failed"), 00183 this->error()->c_str())); 00184 } 00185 00186 this->handle_ = ACE_OS::dlopen (aix_pathname, open_mode); 00187 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00188 break; 00189 00190 // If errno is ENOENT we just skip over this one, anything 00191 // else - like an undefined symbol, for instance 00192 // must be flagged here or the next error will mask it. 00193 // 00194 // @TODO: If we've found our DLL _and_ it's broken, 00195 // should we continue at all? 00196 if (ACE::debug () && (errno != 0) && (errno != ENOENT)) 00197 ACE_ERROR ((LM_ERROR, 00198 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open ") 00199 ACE_TEXT ("(\'%s\') failed, errno=") 00200 ACE_TEXT ("%d: %s\n"), 00201 name->c_str (), 00202 errno, 00203 this->error ()->c_str ())); 00204 00205 } 00206 #endif /* AIX */ 00207 00208 name_iter.advance (); 00209 } 00210 00211 if (this->handle_ == ACE_SHLIB_INVALID_HANDLE) 00212 { 00213 if (ACE::debug ()) 00214 ACE_ERROR ((LM_ERROR, 00215 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open (\"%s\"): ") 00216 ACE_TEXT ("Invalid handle error: %s\n"), 00217 this->dll_name_, 00218 this->error ()->c_str ())); 00219 00220 return -1; 00221 } 00222 } 00223 } 00224 00225 ++this->refcount_; 00226 00227 if (ACE::debug ()) 00228 ACE_DEBUG ((LM_DEBUG, 00229 ACE_TEXT ("ACE (%P|%t) DLL_Handle::open - %s (%d), refcount=%d\n"), 00230 this->dll_name_, 00231 this->handle_, 00232 this->refcount_)); 00233 return 0; 00234 } |
|
|
|
Return the current refcount.
Definition at line 305 of file DLL_Manager.cpp. References refcount_. Referenced by ACE_DLL_Manager::unload_policy().
00306 { 00307 return this->refcount_; 00308 } |
|
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 311 of file DLL_Manager.cpp. References ACE_ERROR, ACE_GUARD_RETURN, ACE_SHLIB_INVALID_HANDLE, ACE_TCHAR, ACE_TEXT, ACE_TRACE, ACE::debug(), ACE_OS::dlsym(), error(), ACE_Auto_Basic_Array_Ptr< X >::get(), handle_, and LM_ERROR. Referenced by ACE_DLL::symbol(), and ACE_DLL_Manager::unload_dll().
00312 { 00313 ACE_TRACE ("ACE_DLL_Handle::symbol"); 00314 ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0)); 00315 00316 ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE::ldname (sym_name)); 00317 // handle_ can be invalid especially when ACE_DLL_Handle resigned ownership 00318 // BTW. Handle lifecycle management is a little crazy in ACE 00319 if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) 00320 { 00321 #if defined (ACE_OPENVMS) 00322 void *sym = ACE::ldsymbol (this->handle_, auto_name.get ()); 00323 #else 00324 void *sym = ACE_OS::dlsym (this->handle_, auto_name.get ()); 00325 #endif 00326 00327 // Linux says that the symbol could be null and that it isn't an 00328 // error. So you should check the error message also, but since 00329 // null symbols won't do us much good anyway, let's still report 00330 // an error. 00331 if (!sym && ignore_errors != 1) 00332 { 00333 if (ACE::debug ()) 00334 ACE_ERROR ((LM_ERROR, 00335 ACE_TEXT ("ACE (%P|%t) DLL_Handle::symbol (\"%s\") ") 00336 ACE_TEXT (" failed with \"%s\".\n"), 00337 auto_name.get (), 00338 this->error ()->c_str ())); 00339 00340 return 0; 00341 } 00342 return sym; 00343 } 00344 return 0; 00345 } |
|
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. Referenced by close(), get_handle(), open(), and symbol(). |
|
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(). |