libtool
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Unhelpful error message in libltdl


From: Ralf Wildenhues
Subject: Re: Unhelpful error message in libltdl
Date: Thu, 6 Mar 2008 22:22:05 +0100
User-agent: Mutt/1.5.17+20080114 (2008-01-14)

Hello John,

* John Bytheway wrote on Tue, Jan 29, 2008 at 10:54:05PM CET:
> I've been using libtool and libltdl to load libraries at runtime in a  
> project I'm working on, and encountered circumstances where the error  
> messages are less helpful than they might be.
>
> Looking at CVS HEAD, The problem is in find_module.  It calls  
> tryall_dlopen_module in one of two "normal" ways first, and if they  
> fail, tries another way on the off chance it was moved to another  
> directory.  If the first attempt fails due, e.g., to an undefined  
> symbol, then the second attempt leaves the error message saying "file  
> not found".  It would be more helpful to have the message about the  
> undefined symbol.
>
> A similar problem exists in lt_dlopenadvise, and mimicking the solution  
> from that seems like the best answer.  I've made my best shot at this,  
> and a diff on CVS HEAD is attached.  I've run the tests with this change  
> and everything seems OK.

Thanks for the bug report and patch.  I've given your bug description a
shot at a test that exposes this issue, but have so far failed.  Below
is where I'm at, patch against current HEAD.  Can you point me to how
your setup is different?  Specifically, how do you get a failure of
dlopen due to an undefined symbol on GNU/Linux when RTLD_NOW is not set?

If you would like to work on the patch, after you've bootstrapped and
built CVS HEAD, you can run the test with something like 
  make check-local TESTSUITEFLAGS='-v -d -x -k lt_dlopen'

and in order to see more of what's going on, before that you should
  make clean libtool libltdl/libltdlc.la CPPFLAGS=-DLT_DEBUG_LOADERS

Ideally, the other places where file_not_found should each be exposed in
testsuite tests as well.

Cheers,
Ralf

2008-03-06  John Bytheway  <address@hidden>  (tiny change)
            Ralf Wildenhues  <address@hidden>

        * libltdl/ltdl.c (find_module): If we found FILENAME, but
        open failed for a different reason, stop searching and
        provide a helpful error message.
        * tests/lt_dlopen.at (lt_dlopen error messages): New test.
        * Makefile.am: Adjust.

Index: Makefile.am
===================================================================
RCS file: /cvsroot/libtool/libtool/Makefile.am,v
retrieving revision 1.230
diff -u -r1.230 Makefile.am
--- Makefile.am 4 Mar 2008 21:25:48 -0000       1.230
+++ Makefile.am 6 Mar 2008 21:21:29 -0000
@@ -451,6 +451,7 @@
                  tests/destdir.at \
                  tests/old-m4-iface.at \
                  tests/am-subdir.at \
+                 tests/lt_dlopen.at \
                  tests/lt_dlexit.at \
                  tests/lt_dladvise.at \
                  tests/need_lib_prefix.at \
Index: libltdl/ltdl.c
===================================================================
RCS file: /cvsroot/libtool/libtool/libltdl/ltdl.c,v
retrieving revision 1.265
diff -u -r1.265 ltdl.c
--- libltdl/ltdl.c      5 Sep 2007 14:48:54 -0000       1.265
+++ libltdl/ltdl.c      6 Mar 2008 21:20:39 -0000
@@ -539,6 +539,13 @@
          if (tryall_dlopen_module (handle, (const char *) 0,
                                    libdir, dlname, advise) == 0)
            return 0;
+
+         /* If we found FILENAME, stop searching -- whether we were able to
+            load the file as a module or not.  If the file exists but loading
+            failed, it is better to return an error message here than to
+            report FILE_NOT_FOUND when the alternative below fails.  */
+         if (!file_not_found())
+           return 1;
        }
 
       /* try to open the not-installed module */
@@ -547,6 +554,11 @@
          if (tryall_dlopen_module (handle, dir, objdir,
                                    dlname, advise) == 0)
            return 0;
+
+         /* As before, if the file was found but loading failed, return now
+            with the current error message.  */
+         if (!file_not_found())
+           return 1;
        }
 
       /* maybe it was moved to another directory */
--- /dev/null   2008-03-02 10:33:19.200041011 +0100
+++ tests/lt_dlopen.at  2008-03-06 22:20:19.000000000 +0100
@@ -0,0 +1,148 @@
+# lt_dlopen.at -- test libltdl functionality                -*- Autotest -*-
+#
+#   Copyright (C) 2008 Free Software Foundation, Inc.
+#   Written by Ralf Wildenhues, 2008
+#
+#   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_dlopen error messages])
+AT_KEYWORDS([libltdl])
+
+# lt_dlopen should fail with a helpful error message if
+# the module was found but failed to load, say, due to unresolved symbols.
+
+AT_DATA([main.c],
+[[#include <ltdl.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+  lt_dlhandle handle;
+  int errors = 0;
+
+  LTDL_SET_PRELOADED_SYMBOLS();
+
+  if (lt_dlinit() != 0)
+    {
+      fprintf (stderr, "error during initialization: %s\n", lt_dlerror());
+      return 1;
+    }
+
+  if (!(handle = lt_dlopen ("libmod1.la")))
+    {
+      fprintf (stderr, "error during lt_dlopen: %s\n", lt_dlerror ());
+      errors = 1;
+    }
+  else
+    {
+      int res, (*pg) (void);
+
+      pg = (int (*) (void)) lt_dlsym (handle, "g");
+      if (!pg)
+       {
+         fprintf (stderr, "error during lt_dlsym: %s\n", lt_dlerror ());
+         errors = 1;
+       }
+      else
+       {
+         res = pg ();
+         if (res != 3)
+           {
+             fprintf (stderr, "g returned %d\n", res);
+             errors = 1;
+           }
+       }
+
+      if (lt_dlclose (handle))
+       {
+         fprintf (stderr, "error during lt_dlclose: %s\n", lt_dlerror ());
+         errors = 1;
+       }
+    }
+
+  if (lt_dlexit () != 0)
+    {
+      fprintf (stderr, "error during exit: %s\n", lt_dlerror ());
+      errors = 1;
+    }
+
+  return errors;
+}
+]])
+
+AT_DATA([mod1.c],
+[[#ifdef __cplusplus
+extern "C" {
+#endif
+extern int i, h (void);
+int j = 1;
+int g (void)
+{
+  return h () + i + j;
+}
+#ifdef __cplusplus
+}
+#endif
+]])
+
+AT_DATA([dep.c],
+[[#ifdef __cplusplus
+extern "C" {
+#endif
+int i = 1;
+int f (void)
+{
+  return i;
+}
+#ifdef __cplusplus
+}
+#endif
+]])
+
+: ${LTDLINCL="-I$abs_top_srcdir/libltdl"}
+: ${LIBLTDL="$abs_builddir/../libltdl/libltdlc.la"}
+
+CPPFLAGS="$CPPFLAGS $LTDLINCL"
+LDFLAGS="$LDFLAGS -no-undefined"
+instdir=`pwd`/inst
+libdir=$instdir/lib
+mkdir mod lib inst inst/bin inst/lib
+
+$CC $CPPFLAGS $CFLAGS -c main.c
+for file in mod1.c dep.c; do
+  $LIBTOOL --mode=compile $CC $CPPFLAGS $CFLAGS -c $file
+done
+
+# TODO: do this for versioned libs as well!
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o lib/libdepend.la \
+          dep.lo -rpath $libdir -avoid-version], [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC -module -shared $CFLAGS $LDFLAGS -o 
mod/libmod1.la \
+          mod1.lo lib/libdepend.la -rpath $libdir -avoid-version],
+         [], [ignore], [ignore])
+
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main main.$OBJEXT \
+         -dlopen mod/libmod1.la $LIBLTDL], [], [ignore], [ignore])
+
+#mv lib lib-moved
+export LTDL_LIBRARY_PATH=`pwd`/mod2
+LT_AT_NOINST_EXEC_CHECK([./main], [-dlopen mod/libmod1.la])
+
+AT_CLEANUP




reply via email to

[Prev in Thread] Current Thread [Next in Thread]