summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-05-15 16:35:16 +0000
committerdhinton <dhinton@ae88bc3d-4319-0410-8dbf-d08b4c9d3795>2002-05-15 16:35:16 +0000
commit14bbb72565893ffad79faccdac6550e41ca89fd4 (patch)
treec92a2056a2a3f9691e61b8cacf2f3a5d3717e4cb
parent19bec382378b1ba1e336457cbf1d80296351e08c (diff)
downloadATCD-14bbb72565893ffad79faccdac6550e41ca89fd4.tar.gz
Wed May 15 15:58:07 UTC 2002 Don Hinton <dhinton@ieee.org>
-rw-r--r--ChangeLog26
-rw-r--r--ChangeLogs/ChangeLog-02a26
-rw-r--r--ChangeLogs/ChangeLog-03a26
-rw-r--r--ace/DLL.cpp84
-rw-r--r--ace/DLL.h15
-rw-r--r--tests/DLL_Test.cpp14
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: