diff options
author | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-05-15 16:35:16 +0000 |
---|---|---|
committer | dhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795> | 2002-05-15 16:35:16 +0000 |
commit | 14bbb72565893ffad79faccdac6550e41ca89fd4 (patch) | |
tree | c92a2056a2a3f9691e61b8cacf2f3a5d3717e4cb | |
parent | 19bec382378b1ba1e336457cbf1d80296351e08c (diff) | |
download | ATCD-14bbb72565893ffad79faccdac6550e41ca89fd4.tar.gz |
Wed May 15 15:58:07 UTC 2002 Don Hinton <dhinton@ieee.org>
-rw-r--r-- | ChangeLog | 26 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-02a | 26 | ||||
-rw-r--r-- | ChangeLogs/ChangeLog-03a | 26 | ||||
-rw-r--r-- | ace/DLL.cpp | 84 | ||||
-rw-r--r-- | ace/DLL.h | 15 | ||||
-rw-r--r-- | tests/DLL_Test.cpp | 14 |
6 files changed, 157 insertions, 34 deletions
diff --git a/ChangeLog b/ChangeLog index 5cf128f4711..ce9842e9d38 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,29 @@ +Wed May 15 15:58:07 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/DLL_Test.cpp: + + Modified test to make calles to ACE_DLL::error () in order to test + changes below. + + * ace/DLL.{h,cpp}: + + Added new static flag, open_called_, to keep track of whether or not + a library function (specifically dlopen) has been called. This is + used internally to make sure that dlerror() isn't called unless the + library has been initialized with a call to dlopen first. Otherwise + it seg-faults on Linux (and perhaps others). + + Also added a last_error_ variable and save_last_error() method and + placed a call to save_last_error() after each library call. Then + changed error() so it just returns last_erro_. This solves a few + problems, since open() made calls to error() which returned the + appropriate error but cleared the value for the next call. So for + instance, when the ctor failed and tried to call error() to report + the error, it didn't return anything since open() had already called + it. Also, if open() failed, and the called tried to call error() to + find out why, they got a blank error message since error() had + already been called by open(). + Tue May 14 19:40:11 2002 Priyanka Gontla <pgontla@ece.uci.edu> * tests/Proactor_Test.cpp (initiate_write_stream): diff --git a/ChangeLogs/ChangeLog-02a b/ChangeLogs/ChangeLog-02a index 5cf128f4711..ce9842e9d38 100644 --- a/ChangeLogs/ChangeLog-02a +++ b/ChangeLogs/ChangeLog-02a @@ -1,3 +1,29 @@ +Wed May 15 15:58:07 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/DLL_Test.cpp: + + Modified test to make calles to ACE_DLL::error () in order to test + changes below. + + * ace/DLL.{h,cpp}: + + Added new static flag, open_called_, to keep track of whether or not + a library function (specifically dlopen) has been called. This is + used internally to make sure that dlerror() isn't called unless the + library has been initialized with a call to dlopen first. Otherwise + it seg-faults on Linux (and perhaps others). + + Also added a last_error_ variable and save_last_error() method and + placed a call to save_last_error() after each library call. Then + changed error() so it just returns last_erro_. This solves a few + problems, since open() made calls to error() which returned the + appropriate error but cleared the value for the next call. So for + instance, when the ctor failed and tried to call error() to report + the error, it didn't return anything since open() had already called + it. Also, if open() failed, and the called tried to call error() to + find out why, they got a blank error message since error() had + already been called by open(). + Tue May 14 19:40:11 2002 Priyanka Gontla <pgontla@ece.uci.edu> * tests/Proactor_Test.cpp (initiate_write_stream): diff --git a/ChangeLogs/ChangeLog-03a b/ChangeLogs/ChangeLog-03a index 5cf128f4711..ce9842e9d38 100644 --- a/ChangeLogs/ChangeLog-03a +++ b/ChangeLogs/ChangeLog-03a @@ -1,3 +1,29 @@ +Wed May 15 15:58:07 UTC 2002 Don Hinton <dhinton@ieee.org> + + * tests/DLL_Test.cpp: + + Modified test to make calles to ACE_DLL::error () in order to test + changes below. + + * ace/DLL.{h,cpp}: + + Added new static flag, open_called_, to keep track of whether or not + a library function (specifically dlopen) has been called. This is + used internally to make sure that dlerror() isn't called unless the + library has been initialized with a call to dlopen first. Otherwise + it seg-faults on Linux (and perhaps others). + + Also added a last_error_ variable and save_last_error() method and + placed a call to save_last_error() after each library call. Then + changed error() so it just returns last_erro_. This solves a few + problems, since open() made calls to error() which returned the + appropriate error but cleared the value for the next call. So for + instance, when the ctor failed and tried to call error() to report + the error, it didn't return anything since open() had already called + it. Also, if open() failed, and the called tried to call error() to + find out why, they got a blank error message since error() had + already been called by open(). + Tue May 14 19:40:11 2002 Priyanka Gontla <pgontla@ece.uci.edu> * tests/Proactor_Test.cpp (initiate_write_stream): diff --git a/ace/DLL.cpp b/ace/DLL.cpp index fe57c4067f0..4602382dcfe 100644 --- a/ace/DLL.cpp +++ b/ace/DLL.cpp @@ -11,9 +11,12 @@ ACE_RCSID(ace, DLL, "$Id$") // Default constructor. Also, by default, the object will be closed // before it is destroyed. +sig_atomic_t ACE_DLL::open_called_ = 0; + ACE_DLL::ACE_DLL (int close_on_destruction) : handle_ (ACE_SHLIB_INVALID_HANDLE), - close_on_destruction_ (close_on_destruction) + close_on_destruction_ (close_on_destruction), + last_error_ (0) { } @@ -24,7 +27,8 @@ ACE_DLL::ACE_DLL (const ACE_TCHAR *dll_name, int open_mode, int close_on_destruction) : handle_ (ACE_SHLIB_INVALID_HANDLE), - close_on_destruction_ (close_on_destruction) + close_on_destruction_ (close_on_destruction), + last_error_ (0) { if (this->open (dll_name, open_mode, close_on_destruction) != 0) ACE_ERROR ((LM_ERROR, @@ -40,6 +44,8 @@ ACE_DLL::~ACE_DLL (void) { // CLose the library only if it hasn't been already. this->close (); + + ACE::strdelete (this->last_error_); } // This method opens the library based on the mode specified using the @@ -58,6 +64,9 @@ ACE_DLL::open (const ACE_TCHAR *dll_filename, int open_mode, int close_on_destruction) { + // Recored that open has been called, use by error(). + this->open_called_ = 1; + // This check is necessary as the library could be opened more than // once without closing it which would cause handle memory leaks. this->close (); @@ -74,40 +83,35 @@ ACE_DLL::open (const ACE_TCHAR *dll_filename, dll_pathname, (sizeof dll_pathname / sizeof (ACE_TCHAR))); - // Check for errors - if (result != 0) - return result; - // The ACE_SHLIB_HANDLE object is obtained. this->handle_ = ACE_OS::dlopen (dll_pathname, open_mode); +#if defined (AIX) if (this->handle_ == ACE_SHLIB_INVALID_HANDLE) { -#if defined (AIX) - do + // AIX often puts the shared library file (most often named shr.o) + // inside an archive library. If this is an archive library + // name, then try appending [shr.o] and retry. + if (0 != ACE_OS_String::strstr (dll_pathname, ACE_LIB_TEXT (".a"))) { - // AIX often puts the shared library file (most often named shr.o) - // inside an archive library. If this is an archive library - // name, then try appending [shr.o] and retry. - if (0 != ACE_OS_String::strstr (dll_pathname, ACE_LIB_TEXT (".a"))) - { - ACE_OS_String::strcat (dll_pathname, ACE_LIB_TEXT ("(shr.o)")); - open_mode |= RTLD_MEMBER; - this->handle_ = ACE_OS::dlopen (dll_pathname, open_mode); - if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) - break; // end up returning 0 - } - ACE_ERROR_RETURN ((LM_ERROR, - ACE_LIB_TEXT ("%s\n"), this->error ()), - -1); + ACE_OS_String::strcat (dll_pathname, ACE_LIB_TEXT ("(shr.o)")); + open_mode |= RTLD_MEMBER; + this->handle_ = ACE_OS::dlopen (dll_pathname, open_mode); + if (this->handle_ != ACE_SHLIB_INVALID_HANDLE) + break; // end up returning 0 } - while (0); -#else + } +#endif /* AIX */ + + // Always set last error. + this->save_last_error(); + + if (this->handle_ == ACE_SHLIB_INVALID_HANDLE) + { ACE_ERROR_RETURN ((LM_ERROR, ACE_LIB_TEXT ("%s\n"), this->error ()), -1); -#endif /* AIX */ } return 0; @@ -118,7 +122,12 @@ ACE_DLL::open (const ACE_TCHAR *dll_filename, void * ACE_DLL::symbol (const ACE_TCHAR *sym_name) { - return ACE_OS::dlsym (this->handle_, sym_name); + void *sym = ACE_OS::dlsym (this->handle_, sym_name); + + // Always set last error. + this->save_last_error (); + + return sym; } // The library is closed using the ACE_SHLIB_HANDLE obejct. i.e. The @@ -137,18 +146,33 @@ ACE_DLL::close (void) this->handle_ != ACE_SHLIB_INVALID_HANDLE) { retval = ACE_OS::dlclose (this->handle_); - } + + // Always set last error. + this->save_last_error (); + } this->handle_ = ACE_SHLIB_INVALID_HANDLE; return retval; } -// This method is used on error in an library operation. +// This method is used to save the last error of a library operation. + +void +ACE_DLL::save_last_error (void) +{ + if (this->open_called_) + { + ACE::strdelete (this->last_error_); + this->last_error_ = ACE_OS::dlerror (); + } +} + +// This method is used return the last error of a library operation. ACE_TCHAR * -ACE_DLL::error (void) +ACE_DLL::error (void) const { - return ACE_OS::dlerror (); + return this->last_error_; } // Return the handle to the user either temporarily or forever, thus diff --git a/ace/DLL.h b/ace/DLL.h index 2a870fa08c1..63772cdf268 100644 --- a/ace/DLL.h +++ b/ace/DLL.h @@ -85,7 +85,7 @@ public: /// Returns a pointer to a string explaining why <symbol> or <open> /// failed. - ACE_TCHAR *error (void); + ACE_TCHAR *error (void) const; /** * Return the handle to the caller. If <become_owner> is non-0 then @@ -99,6 +99,10 @@ public: /// object will be invoked before it is destroyed. int set_handle (ACE_SHLIB_HANDLE handle, int close_on_destruction = 1); private: + /// Used internally to save the last error of a library operation so that + /// multiple subsequent calls to error() can be made safely. + void save_last_error (void); + /// This is a handle to the DLL. ACE_SHLIB_HANDLE handle_; @@ -106,6 +110,15 @@ private: /// automatically when the destructor runs. int close_on_destruction_; + /// This flag keeps track of whether the open method has ever been called on + /// any ACE_DLL object. Used by error() to decide whether or not to call + /// ACE_OS::dlerror(). On Linux, at least, calls to dlerror() prior to calling + /// dlopen() causes a seg-fault. + static sig_atomic_t open_called_; + + /// This is the last error. + ACE_TCHAR *last_error_; + // = Disallow copying and assignment since we don't handle these. ACE_UNIMPLEMENTED_FUNC (ACE_DLL (const ACE_DLL &)) ACE_UNIMPLEMENTED_FUNC (void operator= (const ACE_DLL &)) diff --git a/tests/DLL_Test.cpp b/tests/DLL_Test.cpp index 87159629128..82b22ccfb49 100644 --- a/tests/DLL_Test.cpp +++ b/tests/DLL_Test.cpp @@ -50,6 +50,10 @@ ACE_TMAIN (int, ACE_TCHAR *[]) ACE_DLL dll; + // This is just to make sure that it's safe to call error() at any time, i.e., + // it shouldn't seg-fault. + ACE_TCHAR *dll_error = dll.error (); + #if defined (__KCC) /* With KCC, turning on close-on-destruction will cause problems when libKCC tries to call dtors. */ @@ -65,9 +69,13 @@ ACE_TMAIN (int, ACE_TCHAR *[]) #endif /* __KCC */ if (retval != 0) - ACE_ERROR_RETURN ((LM_ERROR, - ACE_TEXT ("Error in DLL Open\n")), - -1); + { + dll_error = dll.error (); + ACE_ERROR_RETURN ((LM_ERROR, + ACE_TEXT ("Error in DLL Open: %s\n"), + dll_error ? dll_error : ACE_TEXT ("unknown error")), + -1); + } // Just because the ANSI C++ spec says you can no longer cast a // void* to a function pointer. Doesn't allow: |