Avoid false positives, in which an actual library is found in the default search path whose name matches the 'magic' value used in the test, to exercise custom loader. This false positive causes test failure.
* tests/dlloader-api.at: Check value of libtool variable shlibpath_var, and define macro LT_MODULE_PATH_VAR. (main.c): Ensure declaration of putenv. (main.c:main): If LT_MODULE_PATH_VAR is defined, set the variable it names to empty. Signed-off-by: Charles Wilson <...> --- On cygwin, the dlloader-api test fails. Reported here: http://lists.gnu.org/archive/html/bug-libtool/2010-06/msg00045.html And followed up in this subthread: http://lists.gnu.org/archive/html/bug-libtool/2010-06/msg00077.html There was additional discussion and analysis here: http://lists.gnu.org/archive/html/libtool-patches/2010-06/msg00081.html > Unfortunately, this doesn't magically assist solving my problem with > 71. dlloader-api.at:23: FAILED (dlloader-api.at:422) > but that's not a reason to object to the patch. and the ensuing thread, ending here: http://lists.gnu.org/archive/html/libtool-patches/2010-06/msg00095.html > However, the real issue isn't the exe magic, it's the fact that the test > makes assumptions about what files ARE or ARE NOT in the > LT_MODULE_PATH_VAR. We *hope* that there is no "last" or "first" or > "module" or "no_module" anywhere in there. This patch takes the approach that we should not make any assumptions about files in $LD_LIBRARY_PATH or $PATH -- especially when the name of the "library" we're attempting to lt_dlopen is not uglified: "last" is a quite command /usr/bin/ command. On cygwin, the library search path for libs to dlopen includes $PATH; since /usr/bin is in $PATH, /usr/bin/last is found, and we attempt to open it. (The cygwin auto-recognize-.exe behavior discussed in some of the links above is a red herring; yes, it makes a difference here, but the problem is actually more general). Anyway, attempting to dlopen this object /usr/bin/last could either succeed or fail (it fails on cygwin) -- but in either case, we would NOT in fact be testing the custom loader at the end of the loader chain in this test (also named "last"). When we fail (as on cygwin), NO further attempt is made -- either to search in additional directories in the library search path, or to attempt to dlopen the bare name "last" without prefixing any components of the library search path. We just report failure to the (in-library) caller, and go to the next registered loader. Since, in this test, we're talking about the "last" loader, this is our last chance, and we report failure to the client application. (However, the same probably can be observed with the "first" loader; but the details are slightly different). Usually this is the correct decision; the mistake, in this case, was in allowing elements NOT under our control (e.g. contents of system directories) to violate the constraints of the test. To enforce these constraints -- no possible loadable item shall match the (base)name of the item we use to test the custom loader -- this patch sets the library search path to empty. It is not clear to me whether this would break some platforms, if: we need to dlopen a module, say "foo.so" foo.so depends on some installed shared library, somewher in the (system) library search path. Say, /lib/libc.so if we unset the library search path, will the platform still be able to dlopen foo.so? Even though one of foo.so's dependencies, libc.so, can no longer be found via searching the (now empty) library search path? An alternate "solution" would be to uglify the name: rather than trying to load a "library" named "last", instead load one named "libtool_test_suite_custom_dlloader_last". There PROBABLY would never be an ACTUAL loadable object with that name in $PATH or $LD_LIBRARY_PATH... Tested on cygwin, mingw, linux, and works. But, given the issues raised above...comments? discussion? Additional testing on esoteric platforms? OK to push? NOTE: From the autoconf manual: Posix prefers `setenv' to `putenv'; among other things, `putenv' is not required of all Posix implementations, but `setenv' is. Unfortunately, MinGW and MSVC do not provide setenv but DO provide _putenv. Unless we want to extend the test using a custom setenv implementation in terms of putenv for these two platforms, (as done in the cwrapper code), and otherwise use setenv...this seems simpler. But if we really CAN'T rely on putenv's presence... Maybe uglification is the better way to go for this issue. -- Chuck tests/dlloader-api.at | 24 ++++++++++++++++++++++++ 1 files changed, 24 insertions(+), 0 deletions(-) diff --git a/tests/dlloader-api.at b/tests/dlloader-api.at index 37c8984..cd66b22 100644 --- a/tests/dlloader-api.at +++ b/tests/dlloader-api.at @@ -29,6 +29,18 @@ AT_DATA([main.c], #include <stdlib.h> #include <string.h> +#if defined(__STRICT_ANSI__) +# if defined(__MINGW32__) +int _putenv (const char *); +# elif defined(__CYGWIN__) +int putenv (char *); +# endif +#endif + +#if defined(__MINGW32__) || defined(_MSC_VER) +# define putenv _putenv +#endif + static int first_init (lt_user_data data) { @@ -175,6 +187,14 @@ main (int argc, char* argv[]) const char *last_ctx = "last_ctx"; const lt_dlvtable *finder; +#ifdef LT_MODULE_PATH_VAR + static char path_var[] = LT_MODULE_PATH_VAR "="; + if (putenv (path_var) != 0) + { + printf ("putenv(\"%s\") failed\n"); + } +#endif + LTDL_SET_PRELOADED_SYMBOLS (); if (lt_dlinit ()) @@ -402,6 +422,10 @@ AT_CHECK([case $LIBLTDL in #( esac], [], [ignore]) CPPFLAGS="$LTDLINCL $CPPFLAGS" +eval `$LIBTOOL --config | grep 'shlibpath_var='` +if test -n "$shlibpath_var"; then + CPPFLAGS="$CPPFLAGS -DLT_MODULE_PATH_VAR=\"$shlibpath_var\"" +fi AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c module.c], [], [ignore], [ignore]) -- 1.7.0.4