00001 #include "ace_pch.h"
00002
00003
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
00052
00053
00054
00055 if (this->dll_name_)
00056 {
00057
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
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
00082 ACE_TCHAR dll_pathname[MAXPATHLEN + 1];
00083
00084
00085
00086 ACE_Lib_Find::ldfind (dll_name,
00087 dll_pathname,
00088 (sizeof dll_pathname / sizeof (ACE_TCHAR)));
00089
00090
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
00098
00099
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
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
00132
00133
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
00184
00185
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
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
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
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
00327
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
00369
00370
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
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
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
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 }