DLL_Manager.cpp

Go to the documentation of this file.
00001 // $Id: DLL_Manager.cpp 80826 2008-03-04 14:51:23Z wotte $
00002 
00003 #include "ace/DLL_Manager.h"
00004 
00005 #include "ace/Log_Msg.h"
00006 #include "ace/ACE.h"
00007 #include "ace/Framework_Component.h"
00008 
00009 #include "ace/Lib_Find.h"
00010 #include "ace/Object_Manager.h"
00011 #include "ace/SString.h"
00012 #include "ace/Recursive_Thread_Mutex.h"
00013 #include "ace/Guard_T.h"
00014 #include "ace/OS_NS_dlfcn.h"
00015 #include "ace/OS_NS_string.h"
00016 
00017 ACE_RCSID (ace,
00018            DLL_Manager,
00019            "DLL_Manager.cpp,v 4.23 2003/11/05 23:30:46 shuston Exp")
00020 
00021 /******************************************************************/
00022 
00023   ACE_BEGIN_VERSIONED_NAMESPACE_DECL
00024 
00025 sig_atomic_t ACE_DLL_Handle::open_called_ = 0;
00026 
00027 ACE_DLL_Handle::ACE_DLL_Handle (void)
00028   : refcount_ (0),
00029     dll_name_ (0),
00030     handle_ (ACE_SHLIB_INVALID_HANDLE)
00031 {
00032   ACE_TRACE ("ACE_DLL_Handle::ACE_DLL_Handle");
00033 }
00034 
00035 ACE_DLL_Handle::~ACE_DLL_Handle (void)
00036 {
00037   ACE_TRACE ("ACE_DLL_Handle::~ACE_DLL_Handle");
00038   this->close (1);
00039   delete[] this->dll_name_;
00040 }
00041 
00042 const ACE_TCHAR  *
00043 ACE_DLL_Handle::dll_name (void) const
00044 {
00045   ACE_TRACE ("ACE_DLL_Handle::dll_name");
00046   return this->dll_name_;
00047 }
00048 
00049 int
00050 ACE_DLL_Handle::open (const ACE_TCHAR *dll_name,
00051                       int open_mode,
00052                       ACE_SHLIB_HANDLE handle)
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 }
00235 
00236 
00237 int
00238 ACE_DLL_Handle::close (int unload)
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 }
00303 
00304 sig_atomic_t
00305 ACE_DLL_Handle::refcount (void) const
00306 {
00307   return this->refcount_;
00308 }
00309 
00310 void *
00311 ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, int ignore_errors)
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 }
00346 
00347 ACE_SHLIB_HANDLE
00348 ACE_DLL_Handle::get_handle (int become_owner)
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 }
00381 
00382 // This method is used return the last error of a library operation.
00383 
00384 auto_ptr <ACE_TString>
00385 ACE_DLL_Handle::error (void)
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 }
00393 
00394 void
00395 ACE_DLL_Handle::get_dll_names (const ACE_TCHAR *dll_name,
00396                                ACE_Array<ACE_TString> &try_names)
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 }
00490 
00491 /******************************************************************/
00492 
00493 // Pointer to the Singleton instance.
00494 ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
00495 
00496 
00497 ACE_DLL_Manager *
00498 ACE_DLL_Manager::instance (int size)
00499 {
00500   ACE_TRACE ("ACE_DLL_Manager::instance");
00501 
00502   if (ACE_DLL_Manager::instance_ == 0)
00503     {
00504       // Perform Double-Checked Locking Optimization.
00505       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00506                                 *ACE_Static_Object_Lock::instance (), 0));
00507       if (ACE_DLL_Manager::instance_ == 0)
00508         {
00509           ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
00510                           ACE_DLL_Manager (size),
00511                           0);
00512         }
00513     }
00514 
00515   return ACE_DLL_Manager::instance_;
00516 }
00517 
00518 void
00519 ACE_DLL_Manager::close_singleton (void)
00520 {
00521   ACE_TRACE ("ACE_DLL_Manager::close_singleton");
00522 
00523   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00524                      *ACE_Static_Object_Lock::instance ()));
00525 
00526   delete ACE_DLL_Manager::instance_;
00527   ACE_DLL_Manager::instance_ = 0;
00528 }
00529 
00530 ACE_DLL_Manager::ACE_DLL_Manager (int size)
00531   : handle_vector_ (0),
00532     current_size_ (0),
00533     total_size_ (0),
00534     unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
00535 {
00536   ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
00537 
00538   if (this->open (size) != 0 && ACE::debug ())
00539     ACE_ERROR ((LM_ERROR,
00540                 ACE_TEXT ("ACE_DLL_Manager ctor failed to allocate ")
00541                 ACE_TEXT ("handle_vector_.\n")));
00542 }
00543 
00544 ACE_DLL_Manager::~ACE_DLL_Manager (void)
00545 {
00546   ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
00547 
00548   if (this->close () != 0 && ACE::debug ())
00549     ACE_ERROR ((LM_ERROR,
00550                 ACE_TEXT ("ACE_DLL_Manager dtor failed to close ")
00551                 ACE_TEXT ("properly.\n")));
00552 }
00553 
00554 ACE_DLL_Handle *
00555 ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
00556                            int open_mode,
00557                            ACE_SHLIB_HANDLE handle)
00558 {
00559   ACE_TRACE ("ACE_DLL_Manager::open_dll");
00560 
00561   ACE_DLL_Handle *temp_handle = 0;
00562   ACE_DLL_Handle *dll_handle = 0;
00563   {
00564     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00565     dll_handle = this->find_dll (dll_name);
00566     if (!dll_handle)
00567       {
00568         if (this->current_size_ < this->total_size_)
00569           {
00570             ACE_NEW_RETURN (temp_handle,
00571                             ACE_DLL_Handle,
00572                             0);
00573 
00574             dll_handle = temp_handle;
00575           }
00576       }
00577   }
00578 
00579   if (dll_handle)
00580     {
00581       if (dll_handle->open (dll_name, open_mode, handle) != 0)
00582         {
00583           // Error while opening dll. Free temp handle
00584           if (ACE::debug ())
00585             ACE_ERROR ((LM_ERROR,
00586                         ACE_TEXT ("ACE_DLL_Manager::open_dll: Could not ")
00587                         ACE_TEXT ("open dll %s.\n"),
00588                         dll_name));
00589 
00590           delete temp_handle;
00591           return 0;
00592         }
00593 
00594       // Add the handle to the vector only if the dll is successfully
00595       // opened.
00596       if (temp_handle != 0)
00597         {
00598           ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00599           this->handle_vector_[this->current_size_] = dll_handle;
00600           ++this->current_size_;
00601         }
00602     }
00603 
00604   return dll_handle;
00605 }
00606 
00607 int
00608 ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
00609 {
00610   ACE_TRACE ("ACE_DLL_Manager::close_dll");
00611   ACE_DLL_Handle *handle = 0;
00612 
00613   {
00614     ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00615     handle = this->find_dll (dll_name);
00616   }
00617 
00618   if (handle)
00619     {
00620       return this->unload_dll (handle, 0);
00621     }
00622 
00623   return -1;
00624 }
00625 
00626 u_long
00627 ACE_DLL_Manager::unload_policy (void) const
00628 {
00629   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00630   return this->unload_policy_;
00631 }
00632 
00633 void
00634 ACE_DLL_Manager::unload_policy (u_long unload_policy)
00635 {
00636   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00637   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
00638 
00639   u_long old_policy = this->unload_policy_;
00640   this->unload_policy_ = unload_policy;
00641 
00642   // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER,
00643   // call close(1) on all the ACE_DLL_Handle objects with refcount == 0
00644   // which will force those that are still loaded to be unloaded.
00645   if (this->handle_vector_)
00646     if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00647           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) ||
00648         ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00649           ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) &&
00650           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) ))
00651       {
00652         for (int i = this->current_size_ - 1; i >= 0; i--)
00653           {
00654             if (this->handle_vector_[i] &&
00655                 this->handle_vector_[i]->refcount () == 0)
00656               this->handle_vector_[i]->close (1);
00657           }
00658       }
00659 }
00660 
00661 int
00662 ACE_DLL_Manager::open (int size)
00663 {
00664   ACE_TRACE ("ACE_DLL_Manager::open");
00665 
00666   ACE_DLL_Handle **temp = 0;
00667 
00668   ACE_NEW_RETURN (temp,
00669                   ACE_DLL_Handle *[size],
00670                   -1);
00671 
00672   this->handle_vector_ = temp;
00673   this->total_size_ = size;
00674   return 0;
00675 }
00676 
00677 int
00678 ACE_DLL_Manager::close (void)
00679 {
00680   ACE_TRACE ("ACE_DLL_Manager::close");
00681 
00682   int force_close = 1;
00683 
00684   if (this->handle_vector_ != 0)
00685     {
00686       // Delete components in reverse order.
00687       for (int i = this->current_size_ - 1; i >= 0; i--)
00688         {
00689           if (this->handle_vector_[i])
00690             {
00691               ACE_DLL_Handle *s =
00692                 const_cast<ACE_DLL_Handle *> (this->handle_vector_[i]);
00693               this->handle_vector_[i] = 0;
00694               this->unload_dll (s, force_close);
00695               delete s;
00696             }
00697         }
00698 
00699       delete [] this->handle_vector_;
00700       this->handle_vector_ = 0;
00701       this->current_size_ = 0;
00702     }
00703   return 0;
00704 }
00705 
00706 ACE_DLL_Handle *
00707 ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
00708 {
00709   ACE_TRACE ("ACE_DLL_Manager::find_dll");
00710 
00711   for (int i = 0; i < this->current_size_; i++)
00712     if (this->handle_vector_[i] &&
00713         ACE_OS::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
00714       {
00715         return this->handle_vector_[i];
00716       }
00717 
00718   return 0;
00719 }
00720 
00721 int
00722 ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
00723 {
00724   ACE_TRACE ("ACE_DLL_Manager::unload_dll");
00725 
00726   if (dll_handle)
00727     {
00728       int unload = force_unload;
00729       if (unload == 0)
00730         {
00731           // apply strategy
00732           if (ACE_BIT_DISABLED (this->unload_policy_,
00733                                 ACE_DLL_UNLOAD_POLICY_PER_DLL))
00734             {
00735               unload = ACE_BIT_DISABLED (this->unload_policy_,
00736                                          ACE_DLL_UNLOAD_POLICY_LAZY);
00737             }
00738           else
00739             {
00740               // Declare the type of the symbol:
00741               typedef int (*dll_unload_policy)(void);
00742 
00743               void * const unload_policy_ptr =
00744                 dll_handle->symbol (ACE_TEXT ("_get_dll_unload_policy"), 1);
00745 #if defined (ACE_OPENVMS) && (!defined (__INITIAL_POINTER_SIZE) || (__INITIAL_POINTER_SIZE < 64))
00746               int const temp_p =
00747                 reinterpret_cast<int> (unload_policy_ptr);
00748 #else
00749               intptr_t const temp_p =
00750                 reinterpret_cast<intptr_t> (unload_policy_ptr);
00751 #endif
00752 
00753               dll_unload_policy const the_policy =
00754                 reinterpret_cast<dll_unload_policy> (temp_p);
00755 
00756               if (the_policy != 0)
00757                 unload = ACE_BIT_DISABLED (the_policy (),
00758                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00759               else
00760                 unload = ACE_BIT_DISABLED (this->unload_policy_,
00761                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00762             }
00763         }
00764 
00765       if (dll_handle->close (unload) != 0)
00766         {
00767           if (ACE::debug ())
00768             ACE_ERROR ((LM_ERROR,
00769                         ACE_TEXT ("ACE_DLL_Manager::unload error.\n")));
00770 
00771           return -1;
00772         }
00773     }
00774   else
00775     {
00776       if (ACE::debug ())
00777         ACE_ERROR ((LM_ERROR,
00778                     ACE_TEXT ("ACE_DLL_Manager::unload_dll called with ")
00779                     ACE_TEXT ("null pointer.\n")));
00780 
00781       return -1;
00782     }
00783 
00784   return 0;
00785 }
00786 
00787 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Tue Feb 2 17:18:39 2010 for ACE by  doxygen 1.4.7