Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

DLL_Manager.cpp

Go to the documentation of this file.
00001 #include "ace_pch.h"
00002 // DLL_Manager.cpp
00003 // $Id: DLL_Manager.cpp,v 1.1.1.1.2.2 2003/04/01 21:52:59 jones_s Exp $
00004 
00005 #include "ace/DLL_Manager.h"
00006 
00007 #include "ace/Log_Msg.h"
00008 #include "ace/ACE.h"
00009 #include "ace/Framework_Component.h"
00010 
00011 #include "ace/OS.h"
00012 #include "ace/Lib_Find.h"
00013 #include "ace/Object_Manager.h"
00014 
00015 ACE_RCSID(ace, DLL, "$Id: DLL_Manager.cpp,v 1.1.1.1.2.2 2003/04/01 21:52:59 jones_s Exp $")
00016 
00017 /******************************************************************/
00018 
00019 sig_atomic_t ACE_DLL_Handle::open_called_ = 0;
00020 
00021 ACE_DLL_Handle::ACE_DLL_Handle (void)
00022   : refcount_ (0),
00023     dll_name_ (0),
00024     handle_ (ACE_SHLIB_INVALID_HANDLE)
00025 {
00026   ACE_TRACE ("ACE_DLL_Handle::ACE_DLL_Handle");
00027 }
00028 
00029 ACE_DLL_Handle::~ACE_DLL_Handle (void)
00030 {
00031   ACE_TRACE ("ACE_DLL_Handle::~ACE_DLL_Handle");
00032   this->close (1);
00033   delete[] this->dll_name_;
00034 }
00035 
00036 const ACE_TCHAR  *
00037 ACE_DLL_Handle::dll_name (void) const
00038 {
00039   ACE_TRACE ("ACE_DLL_Handle::dll_name");
00040   return this->dll_name_;
00041 }
00042 
00043 int
00044 ACE_DLL_Handle::open (const ACE_TCHAR *dll_name,
00045                       int open_mode,
00046                       ACE_SHLIB_HANDLE handle)
00047 {
00048   ACE_TRACE ("ACE_DLL_Handle::open");
00049   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00050 
00051   //ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("dll_name: %s; open_mode: %d \n"),
00052   //            dll_name,
00053   //            open_mode));
00054 
00055   if (this->dll_name_)
00056     {
00057       // Once dll_name_ has been set, it can't be changed..
00058       if (ACE_OS_String::strcmp (this->dll_name_, dll_name) != 0)
00059         ACE_ERROR_RETURN ((LM_ERROR,
00060                            ACE_LIB_TEXT ("ACE_DLL_Handle::open: error, ")
00061                            ACE_LIB_TEXT ("tried to reopen %s with name %s\n"),
00062                            this->dll_name_, dll_name),
00063                           -1);
00064     }
00065   else
00066     this->dll_name_ = ACE::strnew (dll_name);
00067 
00068   if (!this->open_called_)
00069     this->open_called_ = 1;
00070 
00071   // If it hasn't been loaded yet, go ahead and do that now.
00072   if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
00073     {
00074       if (handle)
00075         this->handle_ = handle;
00076       else
00077         {
00078           if (ACE::debug ())
00079             ACE_DEBUG ((LM_DEBUG, ACE_LIB_TEXT ("ACE_DLL_Handle::open: calling dlopen on ")
00080                         ACE_LIB_TEXT ("\"%s\"\n"), dll_name));
00081           // Find out where the library is
00082           ACE_TCHAR dll_pathname[MAXPATHLEN + 1];
00083 
00084           // Transform the pathname into the appropriate dynamic link library
00085           // by searching the ACE_LD_SEARCH_PATH.
00086           ACE_Lib_Find::ldfind (dll_name,
00087                                 dll_pathname,
00088                                 (sizeof dll_pathname / sizeof (ACE_TCHAR)));
00089 
00090           // The ACE_SHLIB_HANDLE object is obtained.
00091           this->handle_ = ACE_OS::dlopen (dll_pathname,
00092                                           open_mode);
00093 
00094 #if defined (AIX)
00095           if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
00096             {
00097               // AIX often puts the shared library file (most often named shr.o)
00098               // inside an archive library. If this is an archive library
00099               // name, then try appending [shr.o] and retry.
00100               if (0 != ACE_OS_String::strstr (dll_pathname, ACE_LIB_TEXT (".a")))
00101                 {
00102                   ACE_OS_String::strcat (dll_pathname, ACE_LIB_TEXT ("(shr.o)"));
00103                   open_mode |= RTLD_MEMBER;
00104                   this->handle_ = ACE_OS::dlopen (dll_pathname, open_mode);
00105                 }
00106             }
00107 #endif /* AIX */
00108 
00109           if (this->handle_ == ACE_SHLIB_INVALID_HANDLE)
00110             {
00111               ACE_ERROR_RETURN ((LM_ERROR,
00112                                  ACE_LIB_TEXT ("ACE_DLL_Manager_Ex::open: Invalid handle: %s\n"),
00113                                  this->error ()->c_str ()),
00114                                 -1);
00115             }
00116         }
00117     }
00118 
00119   ++this->refcount_;
00120   return 0;
00121 }
00122 
00123 int
00124 ACE_DLL_Handle::close (int unload)
00125 {
00126   ACE_TRACE ("ACE_DLL_Handle::close");
00127   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00128 
00129   int retval = 0;
00130 
00131   // Since we don't actually unload the dll as soon as the refcount
00132   // reaches zero, we need to make sure we don't decrement it below
00133   // zero.
00134   if (this->refcount_ > 0)
00135     --this->refcount_;
00136   else
00137     this->refcount_ = 0;
00138 
00139   if (this->refcount_ == 0 &&
00140       this->handle_ != ACE_SHLIB_INVALID_HANDLE &&
00141       unload == 1)
00142     {
00143       if (ACE::debug ())
00144         ACE_DEBUG ((LM_DEBUG,
00145                     ACE_LIB_TEXT ("ACE_DLL_Handle::close: unloading %s\n"),
00146                     this->dll_name_));
00147 
00148       ACE_Framework_Repository* frPtr= ACE_Framework_Repository::instance ();
00149       
00150       if (frPtr)
00151       {
00152          frPtr->remove_dll_components (this->dll_name_);
00153       }
00154       
00155       retval = ACE_OS::dlclose (this->handle_);
00156       this->handle_ = ACE_SHLIB_INVALID_HANDLE;
00157     }
00158 
00159   if (retval != 0)
00160     ACE_ERROR_RETURN ((LM_ERROR,
00161                        ACE_LIB_TEXT ("ACE_DLL_Handle::close error: \"%s\"."),
00162                        this->error ()->c_str ()),
00163                       retval);
00164   return retval;
00165 }
00166 
00167 sig_atomic_t
00168 ACE_DLL_Handle::refcount (void) const
00169 {
00170   return this->refcount_;
00171 }
00172 
00173 void *
00174 ACE_DLL_Handle::symbol (const ACE_TCHAR *sym_name, int ignore_errors)
00175 {
00176   ACE_TRACE ("ACE_DLL_Handle::symbol");
00177   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00178 
00179   ACE_Auto_Array_Ptr <ACE_TCHAR> auto_name (ACE_Lib_Find::ldname (sym_name));
00180 
00181   void *sym =  ACE_OS::dlsym (this->handle_, auto_name.get ());
00182 
00183   // Linux says that the symbol could be null and that it isn't an error.
00184   // So you should check the error message also, but since null symbols
00185   // won't do us much good anyway, let's still report an error.
00186   if (!sym && ignore_errors != 1)
00187     ACE_ERROR_RETURN ((LM_ERROR,
00188                        ACE_LIB_TEXT ("ACE_DLL_Handle::symbol (\"%s\") \"%s\"."),
00189                        auto_name.get (), this->error ()->c_str ()),
00190                       0);
00191 
00192   return sym;
00193 }
00194 
00195 ACE_SHLIB_HANDLE
00196 ACE_DLL_Handle::get_handle (int become_owner)
00197 {
00198   ACE_TRACE ("ACE_DLL_Handle::get_handle");
00199   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00200 
00201   ACE_SHLIB_HANDLE handle = ACE_SHLIB_INVALID_HANDLE;
00202 
00203   if (this->refcount_ == 0 && become_owner != 0)
00204     ACE_ERROR_RETURN ((LM_ERROR,
00205                        ACE_LIB_TEXT ("ACE_DLL_Handle::get_handle: ")
00206                        ACE_LIB_TEXT ("cannot become owner, refcount == 0.\n")),
00207                       ACE_SHLIB_INVALID_HANDLE);
00208   else if (become_owner != 0)
00209     {
00210       handle = this->handle_;
00211       if (--this->refcount_ == 0)
00212         this->handle_ = ACE_SHLIB_INVALID_HANDLE;
00213     }
00214 
00215   ACE_DEBUG ((LM_DEBUG,
00216               ACE_LIB_TEXT ("ACE_DLL_Handle::get_handle: ")
00217               ACE_LIB_TEXT ("handle %s, refcount %d\n"),
00218               this->handle_ == ACE_SHLIB_INVALID_HANDLE ?
00219                 ACE_LIB_TEXT ("invalid") : ACE_LIB_TEXT ("valid"),
00220               this->refcount_));
00221 
00222   return handle;
00223 }
00224 
00225 // This method is used return the last error of a library operation.
00226 
00227 auto_ptr <ACE_TString>
00228 ACE_DLL_Handle::error (void)
00229 {
00230   ACE_TRACE ("ACE_DLL_Handle::error");
00231   const ACE_TCHAR *error = ACE_OS::dlerror ();
00232   auto_ptr<ACE_TString> str
00233     (new ACE_TString (error ? error : ACE_LIB_TEXT ("no error")));
00234   return str;
00235 }
00236 
00237 /******************************************************************/
00238 
00239 // Pointer to the Singleton instance.
00240 ACE_DLL_Manager *ACE_DLL_Manager::instance_ = 0;
00241 
00242 
00243 ACE_DLL_Manager *
00244 ACE_DLL_Manager::instance (int size)
00245 {
00246   ACE_TRACE ("ACE_DLL_Manager::instance");
00247 
00248   if (ACE_DLL_Manager::instance_ == 0)
00249     {
00250       // Perform Double-Checked Locking Optimization.
00251       ACE_MT (ACE_GUARD_RETURN (ACE_Recursive_Thread_Mutex, ace_mon,
00252                                 *ACE_Static_Object_Lock::instance (), 0));
00253       if (ACE_DLL_Manager::instance_ == 0)
00254         {
00255           ACE_NEW_RETURN (ACE_DLL_Manager::instance_,
00256                           ACE_DLL_Manager (size),
00257                           0);
00258         }
00259     }
00260 
00261   return ACE_DLL_Manager::instance_;
00262 }
00263 
00264 void
00265 ACE_DLL_Manager::close_singleton (void)
00266 {
00267   ACE_TRACE ("ACE_DLL_Manager::close_singleton");
00268 
00269   ACE_MT (ACE_GUARD (ACE_Recursive_Thread_Mutex, ace_mon,
00270                      *ACE_Static_Object_Lock::instance ()));
00271 
00272   delete ACE_DLL_Manager::instance_;
00273   ACE_DLL_Manager::instance_ = 0;
00274 }
00275 
00276 ACE_DLL_Manager::ACE_DLL_Manager (int size)
00277   : handle_vector_ (0),
00278     current_size_ (0),
00279     total_size_ (0),
00280     unload_policy_ (ACE_DLL_UNLOAD_POLICY_PER_DLL)
00281 {
00282   ACE_TRACE ("ACE_DLL_Manager::ACE_DLL_Manager");
00283 
00284   if (this->open (size) != 0)
00285     ACE_ERROR ((LM_ERROR,
00286                 ACE_LIB_TEXT ("ACE_DLL_Manager ctor failed to allocate ")
00287                 ACE_LIB_TEXT ("handle_vector_.\n")));
00288 }
00289 
00290 ACE_DLL_Manager::~ACE_DLL_Manager (void)
00291 {
00292   ACE_TRACE ("ACE_DLL_Manager::~ACE_DLL_Manager");
00293 
00294   if (this->close () != 0)
00295     ACE_ERROR ((LM_ERROR,
00296                 ACE_LIB_TEXT ("ACE_DLL_Manager dtor failed to close ")
00297                 ACE_LIB_TEXT ("properly.\n")));
00298 }
00299 
00300 ACE_DLL_Handle *
00301 ACE_DLL_Manager::open_dll (const ACE_TCHAR *dll_name,
00302                            int open_mode,
00303                            ACE_SHLIB_HANDLE handle)
00304 {
00305   ACE_TRACE ("ACE_DLL_Manager::open_dll");
00306   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00307 
00308   ACE_DLL_Handle *dll_handle = this->find_dll (dll_name);
00309   if (!dll_handle)
00310     {
00311       if (this->current_size_ < this->total_size_)
00312         {
00313           ACE_NEW_RETURN (dll_handle,
00314                           ACE_DLL_Handle,
00315                           0);
00316 
00317           this->handle_vector_[this->current_size_] = dll_handle;
00318           this->current_size_++;
00319         }
00320     }
00321 
00322   if (dll_handle)
00323     {
00324       if (dll_handle->open (dll_name, open_mode, handle) != 0)
00325         {
00326           // Don't worry about freeing the memory right now, since
00327           // the handle_vector_ will be cleaned up automatically later.
00328           ACE_ERROR_RETURN ((LM_ERROR,
00329                              ACE_LIB_TEXT ("ACE_DLL_Manager::open_dll: Could not ")
00330                              ACE_LIB_TEXT ("open dll.\n")),
00331                             0);
00332         }
00333     }
00334   return dll_handle;
00335 }
00336 
00337 int
00338 ACE_DLL_Manager::close_dll (const ACE_TCHAR *dll_name)
00339 {
00340   ACE_TRACE ("ACE_DLL_Manager::close_dll");
00341   ACE_MT (ACE_GUARD_RETURN (ACE_Thread_Mutex, ace_mon, this->lock_, 0));
00342 
00343   ACE_DLL_Handle *handle = this->find_dll (dll_name);
00344   if (handle)
00345     {
00346       return this->unload_dll (handle, 0);
00347     }
00348 
00349   return -1;
00350 }
00351 
00352 u_long
00353 ACE_DLL_Manager::unload_policy (void) const
00354 {
00355   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00356   return this->unload_policy_;
00357 }
00358 
00359 void
00360 ACE_DLL_Manager::unload_policy (u_long unload_policy)
00361 {
00362   ACE_TRACE ("ACE_DLL_Manager::unload_policy");
00363   ACE_MT (ACE_GUARD (ACE_Thread_Mutex, ace_mon, this->lock_));
00364 
00365   u_long old_policy = this->unload_policy_;
00366   this->unload_policy_ = unload_policy;
00367 
00368   // If going from LAZY to EAGER or from PER_DLL to PER_PROCESS|EAGER,
00369   // call close(1) on all the ACE_DLL_Handle objects with refcount == 0
00370   // which will force those that are still loaded to be unloaded.
00371   if (this->handle_vector_)
00372     if (( ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00373           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) ) ||
00374         ( ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_LAZY) &&
00375           ACE_BIT_ENABLED (old_policy, ACE_DLL_UNLOAD_POLICY_PER_DLL) &&
00376           ACE_BIT_DISABLED (this->unload_policy_, ACE_DLL_UNLOAD_POLICY_PER_DLL) ))
00377       {
00378         for (int i = this->current_size_ - 1; i >= 0; i--)
00379           {
00380             if (this->handle_vector_[i] &&
00381                 this->handle_vector_[i]->refcount () == 0)
00382               this->handle_vector_[i]->close (1);
00383           }
00384       }
00385 }
00386 
00387 int
00388 ACE_DLL_Manager::open (int size)
00389 {
00390   ACE_TRACE ("ACE_DLL_Manager::open");
00391 
00392   ACE_DLL_Handle **temp;
00393 
00394   ACE_NEW_RETURN (temp,
00395                   ACE_DLL_Handle *[size],
00396                   -1);
00397 
00398   this->handle_vector_ = temp;
00399   this->total_size_ = size;
00400   return 0;
00401 }
00402 
00403 int
00404 ACE_DLL_Manager::close (void)
00405 {
00406   ACE_TRACE ("ACE_DLL_Manager::close");
00407 
00408   int force_close = 1;
00409 
00410   if (this->handle_vector_ != 0)
00411     {
00412       // Delete components in reverse order.
00413       for (int i = this->current_size_ - 1; i >= 0; i--)
00414         {
00415           if (this->handle_vector_[i])
00416             {
00417               ACE_DLL_Handle *s = ACE_const_cast (ACE_DLL_Handle *,
00418                                                   this->handle_vector_[i]);
00419               this->handle_vector_[i] = 0;
00420               this->unload_dll (s, force_close);
00421               delete s;
00422             }
00423         }
00424 
00425       delete [] this->handle_vector_;
00426       this->handle_vector_ = 0;
00427       this->current_size_ = 0;
00428     }
00429   return 0;
00430 }
00431 
00432 ACE_DLL_Handle *
00433 ACE_DLL_Manager::find_dll (const ACE_TCHAR *dll_name) const
00434 {
00435   ACE_TRACE ("ACE_DLL_Manager::find_dll");
00436 
00437   int i;
00438   for (i = 0; i < this->current_size_; i++)
00439     if (this->handle_vector_[i] &&
00440         ACE_OS_String::strcmp (this->handle_vector_[i]->dll_name (), dll_name) == 0)
00441       {
00442         return this->handle_vector_[i];
00443       }
00444 
00445   return 0;
00446 }
00447 
00448 int
00449 ACE_DLL_Manager::unload_dll (ACE_DLL_Handle *dll_handle, int force_unload)
00450 {
00451   ACE_TRACE ("ACE_DLL_Manager::unload_dll");
00452 
00453   if (dll_handle)
00454     {
00455       int unload = force_unload;
00456       if (unload == 0)
00457         {
00458           // apply strategy
00459           if (ACE_BIT_DISABLED (this->unload_policy_,
00460                                 ACE_DLL_UNLOAD_POLICY_PER_DLL))
00461             {
00462               unload = ACE_BIT_DISABLED (this->unload_policy_,
00463                                          ACE_DLL_UNLOAD_POLICY_LAZY);
00464             }
00465           else
00466             {
00467               // Declare the type of the symbol:
00468               typedef int (*dll_unload_policy)(void);
00469               dll_unload_policy the_policy = 0;
00470               void *unload_policy_ptr =
00471                 dll_handle->symbol (ACE_TEXT ("_get_dll_unload_policy"), 1);
00472               ptrdiff_t temp_p =
00473                 ACE_reinterpret_cast (ptrdiff_t, unload_policy_ptr);
00474               the_policy =
00475                 ACE_reinterpret_cast (dll_unload_policy, temp_p);
00476               if (the_policy != 0)
00477                 unload = ACE_BIT_DISABLED (the_policy (),
00478                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00479               else
00480                 unload = ACE_BIT_DISABLED (this->unload_policy_,
00481                                            ACE_DLL_UNLOAD_POLICY_LAZY);
00482             }
00483         }
00484 
00485       if (dll_handle->close (unload) != 0)
00486         ACE_ERROR_RETURN ((LM_ERROR,
00487                            ACE_LIB_TEXT ("ACE_DLL_Manager::unload error.\n")),
00488                           -1);
00489     }
00490   else
00491     ACE_ERROR_RETURN ((LM_ERROR,
00492                        ACE_LIB_TEXT ("ACE_DLL_Manager::unload_dll called with ")
00493                        ACE_LIB_TEXT ("null pointer.\n")),
00494                       -1);
00495 
00496   return 0;
00497 }

Generated on Mon Jun 16 11:19:37 2003 for ACE by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002