Hello Kurt, first off, thanks for the bug report and patches, and sorry for the long delay.
* Kurt Roeckx wrote on Fri, Jan 02, 2009 at 12:10:38PM CET: > > There was an error report on the Debian bug tracking system > that lt_dlopenext() sets an error on succesful loading the library > if no extention was given. See: > http://bugs.debian.org/510006 > > Here are the patches I've made for both the 1.5 and 2.2 branch. Before I get to the patches, I would like to have a reproducible test case. Here's the code I gather from the references (patch against git master). I've redone the build commands the way I think they are correct (those mentioned in the Autobook are pretty bogus). Can you be bothered to amend the test so that it exposes the bug? Thanks. In a configured build tree, you can run the test with make check-local TESTSUITEFLAGS="-v -d -x -k lt_dlopenext" > PS: Can somebody fix the example in autobook? Good idea. Let's write a patch for that when we've sorted this out here, and send it to Gary. Cheers, Ralf New test for lt_dlopenext error message. * tests/lt_dlopenext.at (lt_dlopenext error messages): New file, with new test. * Makefile.am: Update. Report against Debian from Kaiwang Chen via Kurt Roeckx. diff --git a/Makefile.am b/Makefile.am index 3714519..7982025 100644 --- a/Makefile.am +++ b/Makefile.am @@ -478,6 +478,7 @@ TESTSUITE_AT = tests/testsuite.at \ tests/lt_dlexit.at \ tests/lt_dladvise.at \ tests/lt_dlopen.at \ + tests/lt_dlopenext.at \ tests/ltdl-api.at \ tests/need_lib_prefix.at \ tests/standalone.at \ diff --git a/tests/lt_dlopenext.at b/tests/lt_dlopenext.at new file mode 100644 index 0000000..505621f --- /dev/null +++ b/tests/lt_dlopenext.at @@ -0,0 +1,193 @@ +# lt_dlopenext.at -- test libltdl functionality -*- Autotest -*- +# +# Copyright (C) 2009 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_dlopenext error messages]) +AT_KEYWORDS([libltdl]) + +# This code is copied from the Autobook: +# <http://sources.redhat.com/autobook/autobook/autobook_169.html> +# so if it needs changes, be sure to notify the Autobook authors +# about them. + +AT_DATA([simple-module.c], +[[ +#include <stdio.h> + +int +run (const char *argument) +{ + printf ("Hello, %s!\n", argument); + return 0; +} +]]) + +AT_DATA([ltdl-loader.c], +[[ +#include <stdio.h> +#include <stdlib.h> +#ifndef EXIT_FAILURE +# define EXIT_FAILURE 1 +# define EXIT_SUCCESS 0 +#endif + +#include <limits.h> +#ifndef PATH_MAX +# define PATH_MAX 255 +#endif + +#include <string.h> +#include <ltdl.h> + +#ifndef MODULE_PATH_ENV +# define MODULE_PATH_ENV "MODULE_PATH" +#endif + +typedef int entrypoint (const char *argument); + +/* Save and return a copy of the dlerror() error message, + since the next API call may overwrite the original. */ +static char *dlerrordup (char *errormsg); + +int +main (int argc, const char *argv[]) +{ + char *errormsg = NULL; + lt_dlhandle module = NULL; + entrypoint *run = NULL; + int errors = 0; + + if (argc != 3) + { + fprintf (stderr, "USAGE: main MODULENAME ARGUMENT\n"); + exit (EXIT_FAILURE); + } + + /* Initialise libltdl. */ + errors = lt_dlinit (); + + /* Set the module search path. */ + if (!errors) + { + const char *path = getenv (MODULE_PATH_ENV); + + if (path != NULL) + errors = lt_dlsetsearchpath (path); + } + + /* Load the module. */ + if (!errors) + module = lt_dlopenext (argv[1]); + + /* Find the entry point. */ + if (module) + { + run = (entrypoint *) lt_dlsym (module, "run"); + + /* In principle, run might legitimately be NULL, so + I don't use run == NULL as an error indicator + in general. */ + errormsg = dlerrordup (errormsg); + if (errormsg != NULL) + { + errors = lt_dlclose (module); + module = NULL; + } + } + else + errors = 1; + + /* Call the entry point function. */ + if (!errors) + { + int result = (*run) (argv[2]); + if (result < 0) + errormsg = strdup ("module entry point execution failed"); + else + printf ("\t=> %d\n", result); + } + + /* Unload the module, now that we are done with it. */ + if (!errors) + errors = lt_dlclose (module); + + if (errors) + { + /* Diagnose the encountered error. */ + errormsg = dlerrordup (errormsg); + + if (!errormsg) + { + fprintf (stderr, "%s: dlerror() failed.\n", argv[0]); + return EXIT_FAILURE; + } + } + + /* Finished with ltdl now. */ + if (!errors) + if (lt_dlexit () != 0) + errormsg = dlerrordup (errormsg); + + if (errormsg) + { + fprintf (stderr, "%s: %s.\n", argv[0], errormsg); + free (errormsg); + exit (EXIT_FAILURE); + } + + return EXIT_SUCCESS; +} + +/* Be careful to save a copy of the error message, + since the next API call may overwrite the original. */ +static char * +dlerrordup (char *errormsg) +{ + char *error = (char *) lt_dlerror (); + if (error && !errormsg) + errormsg = strdup (error); + return errormsg; +} +]]) + +: ${LTDLINCL="-I$abs_top_srcdir/libltdl"} +: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"} + +CPPFLAGS="$LTDLINCL $CPPFLAGS" +LDFLAGS="$LDFLAGS -no-undefined" +inst=`pwd`/inst +libdir=$inst/lib + +AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c simple-module.c], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o simple-module.la ]dnl + [simple-module.lo -rpath $libdir -module -avoid-version], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c ltdl-loader.c], + [], [ignore], [ignore]) +AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o ltdl-loader$EXEEXT ]dnl + [ltdl-loader.$OBJEXT -dlopen self $LIBLTDL], + [], [ignore], [ignore]) +LT_AT_EXEC_CHECK([./ltdl-loader], [], [stdout], [ignore], + [simple-module World]) +AT_CHECK([grep "Hello, World" stdout], [], [ignore]) + +AT_CLEANUP