#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(). |
1.3.6