DLL_Manager.cpp

Go to the documentation of this file.
00001 // DLL_Manager.cpp,v 4.45 2006/06/20 12:40:38 jwillemsen Exp
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_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 }
00215 
00216 int
00217 ACE_DLL_Handle::close (int unload)
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 }
00271 
00272 sig_atomic_t
00273 ACE_DLL_Handle::refcount (void) const
00274 {
00275   return this->refcount_;
00276 }
00277 
00278 void *
00279 ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, int ignore_errors)
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 }
00314 
00315 ACE_SHLIB_HANDLE
00316 ACE_DLL_Handle::get_handle (int become_owner)
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 }
00351 
00352 // This method is used return the last error of a library operation.
00353 
00354 auto_ptr <ACE_TString>
00355 ACE_DLL_Handle::error (void)
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 }
00363 
00364 void
00365 ACE_DLL_Handle::get_dll_names (const ACE_TCHAR *dll_name,
00366                                ACE_Array<ACE_TString> &try_names)
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 }
00460 
00461 /******************************************************************/
00462 
00463 // Pointer to the Singleton instance.
00464 ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
00465 
00466 
00467 ACE_DLL_Manager *
00468 ACE_DLL_Manager::instance (int size)
00469 {
00470   ACE_TRACE ("ACE_DLL_Manager::instance");
00471 
00472   if (ACE_DLL_Manager::instance_ == 0)
00473     {
00474       // Perform Double-Checked Locking Optimization.
00475       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00476                                 *ACE_Static_Object_Lock::instance (), 0));
00477       if (ACE_DLL_Manager::instance_ == 0)
00478         {
00479           ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
00480                           ACE_DLL_Manager (size),
00481                           0);
00482         }
00483     }
00484 
00485   return ACE_DLL_Manager::instance_;
00486 }
00487 
00488 void
00489 ACE_DLL_Manager::close_singleton (void)
00490 {
00491   ACE_TRACE ("ACE_DLL_Manager::close_singleton");
00492 
00493   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00494                      *ACE_Static_Object_Lock::instance ()));
00495 
00496   delete ACE_DLL_Manager::instance_;
00497   ACE_DLL_Manager::instance_ = 0;
00498 }
00499 
00500 ACE_DLL_Manager::ACE_DLL_Manager (int size)
00501   : handle_vector_ (0),
00502     current_size_ (0),
00503     total_size_ (0),
00504     unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
00505 {
00506   ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
00507 
00508   if (this->open (size) != 0 && ACE::debug ())
00509     ACE_ERROR ((LM_ERROR,
00510                 ACE_LIB_TEXT ("ACE_DLL_Manager ctor failed to allocate ")
00511                 ACE_LIB_TEXT ("handle_vector_.\n")));
00512 }
00513 
00514 ACE_DLL_Manager::~ACE_DLL_Manager (void)
00515 {
00516   ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
00517 
00518   if (this->close () != 0 && ACE::debug ())
00519     ACE_ERROR ((LM_ERROR,
00520                 ACE_LIB_TEXT ("ACE_DLL_Manager dtor failed to close ")
00521                 ACE_LIB_TEXT ("properly.\n")));
00522 }
00523 
00524 ACE_DLL_Handle *
00525 ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
00526                            int open_mode,
00527                            ACE_SHLIB_HANDLE handle)
00528 {
00529   ACE_TRACE ("ACE_DLL_Manager::open_dll");
00530   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00531 
00532   ACE_DLL_Handle *temp_handle = 0;
00533   ACE_DLL_Handle *dll_handle = this->find_dll (dll_name);
00534   if (!dll_handle)
00535     {
00536       if (this->current_size_ < this->total_size_)
00537         {
00538           ACE_NEW_RETURN (temp_handle,
00539                           ACE_DLL_Handle,
00540                           0);
00541 
00542           dll_handle = temp_handle;
00543         }
00544     }
00545 
00546   if (dll_handle)
00547     {
00548       if (dll_handle->open (dll_name, open_mode, handle) != 0)
00549         {
00550           // Error while openind dll. Free temp handle
00551           if (ACE::debug ())
00552             ACE_ERROR ((LM_ERROR,
00553                         ACE_LIB_TEXT ("ACE_DLL_Manager::open_dll: Could not ")
00554                         ACE_LIB_TEXT ("open dll %s.\n"),
00555                         dll_name));
00556 
00557           delete temp_handle;
00558           return 0;
00559         }
00560       
00561       // Add the handle to the vector only if the dll is successfully
00562       // opened.
00563       if (temp_handle != NULL)
00564         {
00565           this->handle_vector_[this->current_size_] = dll_handle;
00566           this->current_size_++;
00567         }
00568     }
00569 
00570   return dll_handle;
00571 }
00572 
00573 int
00574 ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
00575 {
00576   ACE_TRACE ("ACE_DLL_Manager::close_dll");
00577   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00578 
00579   ACE_DLL_Handle *handle = this->find_dll (dll_name);
00580   if (handle)
00581     {
00582       return this->unload_dll (handle, 0);
00583     }
00584 
00585   return -1;
00586 }
00587 
00588 u_long
00589 ACE_DLL_Manager::unload_policy (void) const
00590 {
00591   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00592   return this->unload_policy_;
00593 }
00594 
00595 void
00596 ACE_DLL_Manager::unload_policy (u_long unload_policy)
00597 {
00598   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00599   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
00600 
00601   u_long old_policy = this->unload_policy_;
00602   this->unload_policy_ = unload_policy;
00603 
00604   // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER,
00605   // call close(1) on all the ACE_DLL_Handle objects with refcount == 0
00606   // which will force those that are still loaded to be unloaded.
00607   if (this->handle_vector_)
00608     if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00609           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) ||
00610         ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00611           ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) &&
00612           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) ))
00613       {
00614         for (int i = this->current_size_ - 1; i >= 0; i--)
00615           {
00616             if (this->handle_vector_[i] &&
00617                 this->handle_vector_[i]->refcount () == 0)
00618               this->handle_vector_[i]->close (1);
00619           }
00620       }
00621 }
00622 
00623 int
00624 ACE_DLL_Manager::open (int size)
00625 {
00626   ACE_TRACE ("ACE_DLL_Manager::open");
00627 
00628   ACE_DLL_Handle **temp = 0;
00629 
00630   ACE_NEW_RETURN (temp,
00631                   ACE_DLL_Handle *[size],
00632                   -1);
00633 
00634   this->handle_vector_ = temp;
00635   this->total_size_ = size;
00636   return 0;
00637 }
00638 
00639 int
00640 ACE_DLL_Manager::close (void)
00641 {
00642   ACE_TRACE ("ACE_DLL_Manager::close");
00643 
00644   int force_close = 1;
00645 
00646   if (this->handle_vector_ != 0)
00647     {
00648       // Delete components in reverse order.
00649       for (int i = this->current_size_ - 1; i >= 0; i--)
00650         {
00651           if (this->handle_vector_[i])
00652             {
00653               ACE_DLL_Handle *s =
00654                 const_cast<ACE_DLL_Handle *> (this->handle_vector_[i]);
00655               this->handle_vector_[i] = 0;
00656               this->unload_dll (s, force_close);
00657               delete s;
00658             }
00659         }
00660 
00661       delete [] this->handle_vector_;
00662       this->handle_vector_ = 0;
00663       this->current_size_ = 0;
00664     }
00665   return 0;
00666 }
00667 
00668 ACE_DLL_Handle *
00669 ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
00670 {
00671   ACE_TRACE ("ACE_DLL_Manager::find_dll");
00672 
00673   int i;
00674   for (i = 0; i < this->current_size_; i++)
00675     if (this->handle_vector_[i] &&
00676         ACE_OS::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
00677       {
00678         return this->handle_vector_[i];
00679       }
00680 
00681   return 0;
00682 }
00683 
00684 int
00685 ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
00686 {
00687   ACE_TRACE ("ACE_DLL_Manager::unload_dll");
00688 
00689   if (dll_handle)
00690     {
00691       int unload = force_unload;
00692       if (unload == 0)
00693         {
00694           // apply strategy
00695           if (ACE_BIT_DISABLED (this->unload_policy_,
00696                                 ACE_DLL_UNLOAD_POLICY_PER_DLL))
00697             {
00698               unload = ACE_BIT_DISABLED (this->unload_policy_,
00699                                          ACE_DLL_UNLOAD_POLICY_LAZY);
00700             }
00701           else
00702             {
00703               // Declare the type of the symbol:
00704               typedef int (*dll_unload_policy)(void);
00705               dll_unload_policy the_policy = 0;
00706               void *unload_policy_ptr =
00707                 dll_handle->symbol (ACE_LIB_TEXT ("_get_dll_unload_policy"), 1);
00708               ptrdiff_t temp_p =
00709                 reinterpret_cast<ptrdiff_t> (unload_policy_ptr);
00710               the_policy =
00711                 reinterpret_cast<dll_unload_policy> (temp_p);
00712               if (the_policy != 0)
00713                 unload = ACE_BIT_DISABLED (the_policy (),
00714                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00715               else
00716                 unload = ACE_BIT_DISABLED (this->unload_policy_,
00717                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00718             }
00719         }
00720 
00721       if (dll_handle->close (unload) != 0)
00722         {
00723           if (ACE::debug ())
00724             ACE_ERROR ((LM_ERROR,
00725                         ACE_LIB_TEXT ("ACE_DLL_Manager::unload error.\n")));
00726 
00727           return -1;
00728         }
00729     }
00730   else
00731     {
00732       if (ACE::debug ())
00733         ACE_ERROR ((LM_ERROR, 
00734                     ACE_LIB_TEXT ("ACE_DLL_Manager::unload_dll called with ")
00735                     ACE_LIB_TEXT ("null pointer.\n")));
00736 
00737       return -1;
00738     }
00739 
00740   return 0;
00741 }
00742 
00743 ACE_END_VERSIONED_NAMESPACE_DECL

Generated on Thu Nov 9 09:41:50 2006 for ACE by doxygen 1.3.6