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