Hi,

Well, this is what I ended up with, it does not change the currently documented saving of error messages until lt_dlerror() is called, it copies the error message to ensure that we don't return garbage when lt_dlerror is called. I think I also got all the places where we were setting file not found.

Still, I am not overjoyed with this.

Peter
>From 40202fade8f55891b5f4acfee54eba02636b91e8 Mon Sep 17 00:00:00 2001
From: Peter O'Gorman <pe...@pogma.com>
Date: Thu, 17 Jun 2010 12:42:28 -0500
Subject: [PATCH] Improve libltdl error messages.

* libltdl/lt_error.c: Add new functions to copy error messages
and keep them until lt_dlerror() is called.
* libltdl/libltdl/lt__private.h: Prototypes for new functions,
new macros.
* libltdl/ltdl.c: Use new macros and functions.
* libltdl/loaders/preopen.c: Likewise.
* tests/lt_dlerror.at: New test.
* Makefile.am: Add new test.
* tests/lt_dlopen.at: Make it pass.
---
 ChangeLog                     |   13 ++++
 Makefile.am                   |    1 +
 libltdl/libltdl/lt__private.h |   14 +++-
 libltdl/loaders/preopen.c     |   10 ++-
 libltdl/lt_error.c            |   44 +++++++++++++-
 libltdl/ltdl.c                |  141 ++++++++++++++++++++++++++---------------
 tests/lt_dlerror.at           |   88 +++++++++++++++++++++++++
 tests/lt_dlopen.at            |    7 +--
 8 files changed, 253 insertions(+), 65 deletions(-)
 create mode 100644 tests/lt_dlerror.at

diff --git a/ChangeLog b/ChangeLog
index a5676ef..c6f0179 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2010-06-17  Peter O'Gorman  <pe...@pogma.com>
+
+	Improve libltdl error messages.
+	* libltdl/lt_error.c: Add new functions to copy error messages
+	and keep them until lt_dlerror() is called.
+	* libltdl/libltdl/lt__private.h: Prototypes for new functions,
+	new macros.
+	* libltdl/ltdl.c: Use new macros and functions.
+	* libltdl/loaders/preopen.c: Likewise.
+	* tests/lt_dlerror.at: New test.
+	* Makefile.am: Add new test.
+	* tests/lt_dlopen.at: Make it pass.
+
 2010-06-16  Ralf Wildenhues  <ralf.wildenh...@gmx.de>
 
 	Optimize func_ltwrapper_scriptname to assume a cwrapper.
diff --git a/Makefile.am b/Makefile.am
index d0688ee..40fce35 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -488,6 +488,7 @@ TESTSUITE_AT	= tests/testsuite.at \
 		  tests/lt_dlopen.at \
 		  tests/lt_dlopen_a.at \
 		  tests/lt_dlopenext.at \
+		  tests/lt_dlerror.at \
 		  tests/ltdl-libdir.at \
 		  tests/ltdl-api.at \
 		  tests/dlloader-api.at \
diff --git a/libltdl/libltdl/lt__private.h b/libltdl/libltdl/lt__private.h
index f4c4a3d..dc043cc 100644
--- a/libltdl/libltdl/lt__private.h
+++ b/libltdl/libltdl/lt__private.h
@@ -137,13 +137,19 @@ struct lt__advise {
 #define LT__STRERROR(name)	lt__error_string(LT_CONC(LT_ERROR_,name))
 
 #define LT__GETERROR(lvalue)	      (lvalue) = lt__get_last_error()
-#define LT__SETERRORSTR(errormsg)     lt__set_last_error(errormsg)
-#define LT__SETERROR(errorcode)	      LT__SETERRORSTR(LT__STRERROR(errorcode))
+#define LT__SETERRORSTR(errormsg)     lt__set_last_error(errormsg, 0)
+#define LT__SETERROR(errorcode)       if (0 == lt__get_last_error()) \
+					LT__SETERRORSTR(LT__STRERROR(errorcode))
+#define LT__ENTER_PUBLIC_FUNC(x)      lt__enter_err()
+#define LT__PUBLIC_FUNC_RETURN(x)     lt__keep_error(); return x;
+#define LT__FORCEERROR(errorstr)      LT__SETERRORSTR(errorstr)
 
 LT_SCOPE const char *lt__error_string	(int errorcode);
 LT_SCOPE const char *lt__get_last_error	(void);
-LT_SCOPE const char *lt__set_last_error	(const char *errormsg);
-
+LT_SCOPE const char *lt__set_last_error	(const char *errormsg, int mustfree);
+LT_SCOPE void        lt__keep_error     (void);
+LT_SCOPE void        lt__enter_err      (void);
+LT_SCOPE const char *lt__dlerror        (void);
 LT_END_C_DECLS
 
 #endif /*!defined(LT__PRIVATE_H)*/
diff --git a/libltdl/loaders/preopen.c b/libltdl/loaders/preopen.c
index 7149287..8b14121 100644
--- a/libltdl/loaders/preopen.c
+++ b/libltdl/loaders/preopen.c
@@ -186,7 +186,6 @@ vm_open (lt_user_data LT__UNUSED loader_data, const char *filename,
     }
 
   LT__SETERROR (FILE_NOT_FOUND);
-
  done:
   return module;
 }
@@ -292,8 +291,9 @@ add_symlist (const lt_dlsymlist *symlist)
 int
 lt_dlpreload_default (const lt_dlsymlist *preloaded)
 {
+  LT__ENTER_PUBLIC_FUNC ();
   default_preloaded_symbols = preloaded;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 
@@ -303,6 +303,7 @@ int
 lt_dlpreload (const lt_dlsymlist *preloaded)
 {
   int errors = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   if (preloaded)
     {
@@ -318,7 +319,7 @@ lt_dlpreload (const lt_dlsymlist *preloaded)
 	}
     }
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 
@@ -331,6 +332,7 @@ lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
   symlist_chain *list;
   int		 errors = 0;
   int		 found  = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   /* For each symlist in the chain...  */
   for (list = preloaded_symlists; list; list = list->next)
@@ -371,5 +373,5 @@ lt_dlpreload_open (const char *originator, lt_dlpreload_callback_func *func)
       ++errors;
     }
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
diff --git a/libltdl/lt_error.c b/libltdl/lt_error.c
index d7af36d..f79d5e6 100644
--- a/libltdl/lt_error.c
+++ b/libltdl/lt_error.c
@@ -32,6 +32,9 @@ or obtained by writing to the Free Software Foundation, Inc.,
 #include "lt_error.h"
 
 static const char	*last_error	= 0;
+static const char	*kept_error	= 0;
+static int		returned_dlerror= 0;
+static int		free_saved_error = 0;
 static const char	error_strings[LT_ERROR_MAX][LT_ERROR_LEN_MAX + 1] =
   {
 #define LT_ERROR(name, diagnostic)	diagnostic,
@@ -104,7 +107,46 @@ lt__get_last_error (void)
 }
 
 const char *
-lt__set_last_error (const char *errormsg)
+lt__set_last_error (const char *errormsg, int mustfree)
 {
+  free_saved_error = mustfree;
   return last_error = errormsg;
 }
+
+void lt__keep_error (void)
+{
+  if (last_error)
+    {
+      FREE (kept_error);
+      if (free_saved_error)
+        kept_error = last_error;
+      else
+        kept_error = lt__strdup(last_error);
+      returned_dlerror = 0;
+    }
+    free_saved_error = 0;
+}
+
+void lt__enter_err (void)
+{
+  lt__set_last_error (0, 0);
+  if (returned_dlerror)
+    {
+      FREE (kept_error);
+      returned_dlerror = 0;
+    }
+}
+
+const char* lt__dlerror (void)
+{
+  if (returned_dlerror)
+    {
+      FREE(kept_error);
+      returned_dlerror = 0;
+    }
+  else
+    {
+      returned_dlerror = 1;
+    }
+  return kept_error;
+}
diff --git a/libltdl/ltdl.c b/libltdl/ltdl.c
index 1213f0d..1b13e8c 100644
--- a/libltdl/ltdl.c
+++ b/libltdl/ltdl.c
@@ -216,6 +216,8 @@ int
 lt_dlinit (void)
 {
   int	errors	= 0;
+  const char* saved_error = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   /* Initialize only at first call. */
   if (++initialized == 1)
@@ -232,6 +234,7 @@ lt_dlinit (void)
       /* Now open all the preloaded module loaders, so the application
 	 can use _them_ to lt_dlopen its own modules.  */
 #ifdef HAVE_LIBDLLOADER
+      LT__GETERROR(saved_error);
       if (!errors)
 	{
 	  errors += lt_dlpreload (preloaded_symbols);
@@ -241,6 +244,7 @@ lt_dlinit (void)
 	{
 	  errors += lt_dlpreload_open (LT_STR(LTDLOPEN), loader_init_callback);
 	}
+      LT__FORCEERROR(saved_error);
 #endif /* HAVE_LIBDLLOADER */
     }
 
@@ -248,7 +252,7 @@ lt_dlinit (void)
   lt_dlloader_dump();
 #endif
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 int
@@ -258,6 +262,7 @@ lt_dlexit (void)
   lt_dlloader *loader   = 0;
   lt_dlhandle  handle   = handles;
   int	       errors   = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   if (!initialized)
     {
@@ -347,7 +352,7 @@ lt_dlexit (void)
     }
 
  done:
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 
@@ -359,7 +364,6 @@ tryall_dlopen (lt_dlhandle *phandle, const char *filename,
 	       lt_dladvise advise, const lt_dlvtable *vtable)
 {
   lt_dlhandle	handle		= handles;
-  const char *	saved_error	= 0;
   int		errors		= 0;
 
 #ifdef LT_DEBUG_LOADERS
@@ -368,7 +372,6 @@ tryall_dlopen (lt_dlhandle *phandle, const char *filename,
 	   vtable ? vtable->name : "(ALL)");
 #endif
 
-  LT__GETERROR (saved_error);
 
   /* check whether the module was already opened */
   for (;handle; handle = handle->next)
@@ -465,8 +468,6 @@ tryall_dlopen (lt_dlhandle *phandle, const char *filename,
     handle->vtable = loader_vtable;
   }
 
-  LT__SETERRORSTR (saved_error);
-
  done:
   return errors;
 }
@@ -526,6 +527,7 @@ find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
 	     const char *dlname,  const char *old_name, int installed,
 	     lt_dladvise advise)
 {
+  const char* saved_error = 0;
   /* Try to open the old library first; if it was dlpreopened,
      we want the preopened version of it, even if a dlopenable
      module is available.  */
@@ -538,6 +540,9 @@ find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
   /* Try to open the dynamic library.  */
   if (dlname)
     {
+      /* Reset any FILE_NOT_FOUND error from the preopen loader */
+      lt__set_last_error (0, 0);
+
       /* try to open the installed module */
       if (installed && libdir)
 	{
@@ -556,9 +561,18 @@ find_module (lt_dlhandle *handle, const char *dir, const char *libdir,
 
       /* maybe it was moved to another directory */
       {
+	  /* If the module wasn't moved and loading above failed for
+	     some other reason, this would reset the error message, not
+	     really a good thing. So we save and restore it. */
+	  char *saved_error = lt__strdup(lt__get_last_error());
+
 	  if (dir && (tryall_dlopen_module (handle, (const char *) 0,
 					    dir, dlname, advise) == 0))
-	    return 0;
+	    {
+	      FREE(saved_error);
+	      return 0;
+	    }
+	  lt__set_last_error (saved_error, 1);
       }
     }
 
@@ -844,8 +858,13 @@ load_deplibs (lt_dlhandle handle, char *deplibs)
 	  if (strncmp(p, "-L", 2) == 0 || strncmp(p, "-R", 2) == 0)
 	    {
 	      char save = *end;
+	      const char* saved_error = 0;
+	      int r;
 	      *end = 0; /* set a temporary string terminator */
-	      if (lt_dladdsearchdir(p+2))
+	      LT__GETERROR(saved_error);
+	      r = lt_dladdsearchdir(p+2);
+	      LT__FORCEERROR(saved_error);
+	      if (r)
 		{
 		  goto cleanup;
 		}
@@ -1142,7 +1161,6 @@ static int
 try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
 	    lt_dladvise advise)
 {
-  const char *	saved_error	= 0;
   char *	archive_name	= 0;
   char *	canonical	= 0;
   char *	base_name	= 0;
@@ -1161,7 +1179,6 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
 	   ext ? ext : "(null)");
 #endif
 
-  LT__GETERROR (saved_error);
 
   /* dlopen self? */
   if (!filename)
@@ -1306,6 +1323,9 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
       goto cleanup;
     }
 
+  /* Reset any errors set by the preopen loaded */
+  lt__set_last_error (0, 0);
+
   /* Check whether we are opening a libtool module (.la extension).  */
   if (ext && streq (ext, archive_ext))
     {
@@ -1368,6 +1388,9 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
 	  goto cleanup;
 	}
 
+      /* We found a file, reset any FILE_NOT_FOUND error */
+      lt__set_last_error (0, 0);
+
       /* read the .la file */
       if (parse_dotla_file(file, &dlname, &libdir, &deplibs,
 	    &old_name, &installed) != 0)
@@ -1480,7 +1503,6 @@ try_dlopen (lt_dlhandle *phandle, const char *filename, const char *ext,
       handles		= *phandle;
     }
 
-  LT__SETERRORSTR (saved_error);
 
  cleanup:
   FREE (dir);
@@ -1540,56 +1562,63 @@ int
 lt_dladvise_init (lt_dladvise *padvise)
 {
   lt_dladvise advise = (lt_dladvise) lt__zalloc (sizeof (struct lt__advise));
+  LT__ENTER_PUBLIC_FUNC ();
   *padvise = advise;
-  return (advise ? 0 : 1);
+  LT__PUBLIC_FUNC_RETURN ((advise ? 0 : 1));
 }
 
 int
 lt_dladvise_destroy (lt_dladvise *padvise)
 {
+  LT__ENTER_PUBLIC_FUNC ();
   if (padvise)
     FREE(*padvise);
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 int
 lt_dladvise_ext (lt_dladvise *padvise)
 {
   assert (padvise && *padvise);
+  LT__ENTER_PUBLIC_FUNC ();
   (*padvise)->try_ext = 1;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 int
 lt_dladvise_resident (lt_dladvise *padvise)
 {
   assert (padvise && *padvise);
+  LT__ENTER_PUBLIC_FUNC ();
   (*padvise)->is_resident = 1;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 int
 lt_dladvise_local (lt_dladvise *padvise)
 {
   assert (padvise && *padvise);
+  LT__ENTER_PUBLIC_FUNC ();
   (*padvise)->is_symlocal = 1;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 int
 lt_dladvise_global (lt_dladvise *padvise)
 {
   assert (padvise && *padvise);
+  LT__ENTER_PUBLIC_FUNC ();
   (*padvise)->is_symglobal = 1;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 int
 lt_dladvise_preload (lt_dladvise *padvise)
 {
   assert (padvise && *padvise);
+  LT__ENTER_PUBLIC_FUNC ();
   (*padvise)->try_preload_only = 1;
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 /* Libtool-1.5.x interface for loading a new module named FILENAME.  */
@@ -1609,11 +1638,14 @@ lt_dlopenext (const char *filename)
 {
   lt_dlhandle	handle	= 0;
   lt_dladvise	advise;
+  const char* saved_error = 0;
 
   if (!lt_dladvise_init (&advise) && !lt_dladvise_ext (&advise))
     handle = lt_dlopenadvise (filename, advise);
 
+  LT__GETERROR(saved_error);
   lt_dladvise_destroy (&advise);
+  LT__FORCEERROR(saved_error);
   return handle;
 }
 
@@ -1623,15 +1655,13 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
 {
   lt_dlhandle	handle	= 0;
   int		errors	= 0;
-  const char *	saved_error	= 0;
-
-  LT__GETERROR (saved_error);
+  LT__ENTER_PUBLIC_FUNC ();
 
   /* Can't have symbols hidden and visible at the same time!  */
   if (advise && advise->is_symlocal && advise->is_symglobal)
     {
       LT__SETERROR (CONFLICTING_FLAGS);
-      return 0;
+      LT__PUBLIC_FUNC_RETURN (0);
     }
 
   if (!filename
@@ -1642,9 +1672,11 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
       /* Just incase we missed a code path in try_dlopen() that reports
 	 an error, but forgot to reset handle... */
       if (try_dlopen (&handle, filename, NULL, advise) != 0)
-	return 0;
+	{
+	  LT__PUBLIC_FUNC_RETURN (0);
+	}
 
-      return handle;
+      LT__PUBLIC_FUNC_RETURN (handle);
     }
   else if (filename && *filename)
     {
@@ -1658,24 +1690,27 @@ lt_dlopenadvise (const char *filename, lt_dladvise advise)
 	 report FILE_NOT_FOUND when the alternatives (foo.so etc) are not
 	 in the module search path.  */
       if (handle || ((errors > 0) && !file_not_found ()))
-	return handle;
+	{
+	  LT__PUBLIC_FUNC_RETURN (handle);
+	}
 
 #if defined(LT_MODULE_EXT)
       /* Try appending SHLIB_EXT.   */
-      LT__SETERRORSTR (saved_error);
       errors = try_dlopen (&handle, filename, shlib_ext, advise);
 
       /* As before, if the file was found but loading failed, return now
 	 with the current error message.  */
       if (handle || ((errors > 0) && !file_not_found ()))
-	return handle;
+	{
+	  LT__PUBLIC_FUNC_RETURN (handle);
+	}
 #endif
     }
 
   /* Still here?  Then we really did fail to locate any of the file
      names we tried.  */
   LT__SETERROR (FILE_NOT_FOUND);
-  return 0;
+  LT__PUBLIC_FUNC_RETURN (0);
 }
 
 
@@ -1869,6 +1904,7 @@ lt_dlforeachfile (const char *search_path,
 {
   int is_done = 0;
   file_worker_func **fpptr = &func;
+  LT__ENTER_PUBLIC_FUNC ();
 
   if (search_path)
     {
@@ -1904,7 +1940,7 @@ lt_dlforeachfile (const char *search_path,
 #endif
     }
 
-  return is_done;
+  LT__PUBLIC_FUNC_RETURN (is_done);
 }
 
 int
@@ -1912,6 +1948,7 @@ lt_dlclose (lt_dlhandle handle)
 {
   lt_dlhandle cur, last;
   int errors = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   /* check whether the handle is valid */
   last = cur = handles;
@@ -1968,7 +2005,7 @@ lt_dlclose (lt_dlhandle handle)
     }
 
  done:
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 void *
@@ -1981,10 +2018,12 @@ lt_dlsym (lt_dlhandle place, const char *symbol)
   lt_user_data data;
   lt_dlhandle handle;
 
+  LT__ENTER_PUBLIC_FUNC ();
+
   if (!place)
     {
       LT__SETERROR (INVALID_HANDLE);
-      return 0;
+      LT__PUBLIC_FUNC_RETURN (0);
     }
 
   handle = place;
@@ -1992,7 +2031,7 @@ lt_dlsym (lt_dlhandle place, const char *symbol)
   if (!symbol)
     {
       LT__SETERROR (SYMBOL_NOT_FOUND);
-      return 0;
+      LT__PUBLIC_FUNC_RETURN (0);
     }
 
   lensym = LT_STRLEN (symbol) + LT_STRLEN (handle->vtable->sym_prefix)
@@ -2008,16 +2047,13 @@ lt_dlsym (lt_dlhandle place, const char *symbol)
       if (!sym)
 	{
 	  LT__SETERROR (BUFFER_OVERFLOW);
-	  return 0;
+	  LT__PUBLIC_FUNC_RETURN (0);
 	}
     }
 
   data = handle->vtable->dlloader_data;
   if (handle->info.name)
     {
-      const char *saved_error;
-
-      LT__GETERROR (saved_error);
 
       /* this is a libtool module */
       if (handle->vtable->sym_prefix)
@@ -2041,9 +2077,8 @@ lt_dlsym (lt_dlhandle place, const char *symbol)
 	    {
 	      FREE (sym);
 	    }
-	  return address;
+	  LT__PUBLIC_FUNC_RETURN (address);
 	}
-      LT__SETERRORSTR (saved_error);
     }
 
   /* otherwise try "symbol" */
@@ -2057,24 +2092,23 @@ lt_dlsym (lt_dlhandle place, const char *symbol)
       strcpy(sym, symbol);
     }
 
+  /* Reset the dlerror() string, so that errors returned are for the
+   * symbol without the foo_LTX_ prefix */
+  lt__set_last_error (0, 0);
+
   address = handle->vtable->find_sym (data, handle->module, sym);
   if (sym != lsym)
     {
       FREE (sym);
     }
 
-  return address;
+  LT__PUBLIC_FUNC_RETURN (address);
 }
 
 const char *
 lt_dlerror (void)
 {
-  const char *error;
-
-  LT__GETERROR (error);
-  LT__SETERRORSTR (0);
-
-  return error;
+  return lt__dlerror();
 }
 
 static int
@@ -2151,19 +2185,22 @@ lt_dladdsearchdir (const char *search_dir)
 {
   int errors = 0;
 
+  LT__ENTER_PUBLIC_FUNC ();
+
   if (search_dir && *search_dir)
     {
       if (lt_dlpath_insertdir (&user_search_path, 0, search_dir) != 0)
 	++errors;
     }
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 int
 lt_dlinsertsearchdir (const char *before, const char *search_dir)
 {
   int errors = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   if (before)
     {
@@ -2171,7 +2208,7 @@ lt_dlinsertsearchdir (const char *before, const char *search_dir)
 	  || (before >= user_search_path + LT_STRLEN (user_search_path)))
 	{
 	  LT__SETERROR (INVALID_POSITION);
-	  return 1;
+	  LT__PUBLIC_FUNC_RETURN (1);
 	}
     }
 
@@ -2184,35 +2221,37 @@ lt_dlinsertsearchdir (const char *before, const char *search_dir)
 	}
     }
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 int
 lt_dlsetsearchpath (const char *search_path)
 {
   int   errors	    = 0;
+  LT__ENTER_PUBLIC_FUNC ();
 
   FREE (user_search_path);
 
   if (!search_path || !LT_STRLEN (search_path))
     {
-      return errors;
+      LT__PUBLIC_FUNC_RETURN (errors);
     }
 
   if (canonicalize_path (search_path, &user_search_path) != 0)
     ++errors;
 
-  return errors;
+  LT__PUBLIC_FUNC_RETURN (errors);
 }
 
 const char *
 lt_dlgetsearchpath (void)
 {
   const char *saved_path;
+  LT__ENTER_PUBLIC_FUNC ();
 
   saved_path = user_search_path;
 
-  return saved_path;
+  LT__PUBLIC_FUNC_RETURN (saved_path);
 }
 
 int
diff --git a/tests/lt_dlerror.at b/tests/lt_dlerror.at
new file mode 100644
index 0000000..afe10a8
--- /dev/null
+++ b/tests/lt_dlerror.at
@@ -0,0 +1,88 @@
+# lt_dlerror.at -- test lt_dlerror functionality                -*- Autotest -*-
+#
+#   Copyright (C) 2010 Free Software Foundation, Inc.
+#   This file is part of GNU Libtool.
+#
+# GNU Libtool is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 2 of
+# the License, or (at your option) any later version.
+#
+# GNU Libtool is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Libtool; see the file COPYING.  If not, a copy
+# can be downloaded from  http://www.gnu.org/licenses/gpl.html,
+# or obtained by writing to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+####
+
+AT_SETUP([lt_dlerror api])
+AT_KEYWORDS([libltdl])
+
+AT_DATA([main.c],
+[[#include <ltdl.h>
+#include <stdio.h>
+
+#define OOPS(x) do { if ((x)) {\
+   fprintf(stderr,"OOPS: %s %d %s\n",__FILE__, __LINE__, #x); \
+   exit(1);}} while (0)
+
+int
+main (int argc, char* argv[])
+{
+  int err = 0;
+  int *fooptr = NULL;
+  lt_dlhandle plugin_handle;
+  err = lt_dlinit ();
+  OOPS(!err && lt_dlerror());
+  plugin_handle = lt_dlopenext ("No-such-module.la");
+  OOPS(plugin_handle);
+  plugin_handle = lt_dlopenext ("./good-plugin.la");
+  OOPS(!plugin_handle);
+  OOPS(NULL == lt_dlerror());
+  err = lt_dlclose (plugin_handle);
+  OOPS(err);
+  plugin_handle = lt_dlopenext ("No-such-module.la");
+  OOPS(!lt_dlerror());
+  OOPS(lt_dlerror());
+  plugin_handle = lt_dlopenext ("./good-plugin.la");
+  fooptr = (int*)lt_dlsym(plugin_handle, "bar");
+  OOPS(fooptr);
+  fooptr = (int*)lt_dlsym(plugin_handle, "foo");
+  OOPS(!fooptr);
+  OOPS(!lt_dlerror());
+  OOPS(lt_dlerror());
+  err = lt_dlexit ();
+  OOPS(err);
+  return 0;
+}
+]])
+
+AT_DATA([good-plugin.c],
+[[int foo = 1;
+]])
+
+: ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
+: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
+
+CPPFLAGS="$LTDLINCL $CPPFLAGS"
+inst=`pwd`/inst
+libdir=$inst/lib
+
+AT_CHECK([$CC $CPPFLAGS $CFLAGS -c main.c], [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c good-plugin.c],
+	   [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o good-plugin.la -rpath $libdir ]dnl
+	 [-module -avoid-version good-plugin.lo], [], [ignore], [ignore])
+
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT main.$OBJEXT ]dnl
+	 [-dlopen good-plugin.la $LIBLTDL],
+	 [], [ignore], [ignore])
+
+LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [])
+
+AT_CLEANUP
diff --git a/tests/lt_dlopen.at b/tests/lt_dlopen.at
index 0aae2f8..e5c042d 100644
--- a/tests/lt_dlopen.at
+++ b/tests/lt_dlopen.at
@@ -23,9 +23,6 @@
 AT_SETUP([lt_dlopen error messages])
 AT_KEYWORDS([libltdl])
 
-# The bug is not fixed:
-AT_XFAIL_IF([:])
-
 # This test only works if the system allows undefined symbols.
 eval `$LIBTOOL --config | grep '^allow_undefined_flag='`
 AT_CHECK([test unsupported != "$allow_undefined_flag" || exit 77])
@@ -55,7 +52,7 @@ main (int argc, char* argv[])
     }
   else
     {
-      printf ("plugin failed to open: %s\n", lt_dlerror());
+      fprintf (stderr, "plugin failed to open: %s\n", lt_dlerror());
       err = 1;
     }
   lt_dlexit ();
@@ -98,6 +95,6 @@ AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT main.$OBJEXT
 
 LT_AT_EXEC_CHECK([./main], [], [ignore], [ignore], [./good-plugin.la])
 LT_AT_EXEC_CHECK([./main], [1], [ignore], [stderr], [./missing-symbol-plugin.la])
-AT_CHECK([grep 'missing symbol' stderr], [], [ignore])
+AT_CHECK([[grep '[Ss]ymbol' stderr]], [], [ignore])
 
 AT_CLEANUP
-- 
1.7.0.1

Reply via email to