libtool
[Top][All Lists]
Advanced

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

Re: ltdl resident modules are unloaded by lt_dlexit()


From: Ralf Wildenhues
Subject: Re: ltdl resident modules are unloaded by lt_dlexit()
Date: Mon, 4 Jan 2010 22:02:40 +0100
User-agent: Mutt/1.5.20 (2009-10-28)

Hi Bob,

* Bob Friesenhahn wrote on Tue, Dec 29, 2009 at 10:37:09PM CET:
> On Tue, 29 Dec 2009, Ralf Wildenhues wrote:
> >
> >Do you have a small reproducible example (a way to see this easily with
> >GraphicsMagick would be fine as well)?
> 
> I don't have a small reproducible example.  The situation where the
> problem occurs is with GraphicsMagick when the Jasper JPEG 2000
> library is used.  When the Jasper library is initialized (via its
> jas_init() function), it registers an atexit() handler which invokes
> its cleanup handler (jas_cleanup()).  If the Jasper library becomes
> unloaded, then the cleanup handler is still invoked via the
> registered address.  Some OS's handle this better than others.
> Microsoft Windows and FreeBSD result in a crash while Linux seems to
> remove stale atexit() handlers.
> 
> The best fix for the Jasper problem is to comment out its atexit()
> request, but there is no way to tell if a Jasper library has this
> treatment, so the safest solution is to try to never unload it.  It
> seems that invoking lt_dlexit() causes Jasper to be unloaded even if
> the module which depended on it is indicated to be "resident".

Can you try out this patch (might need to twiddle the Makefile.am change
if it conflicts) and run
  make check-local TESTSUITEFLAGS='-v -d -x -k resident'

to see whether that reproduces the problem for you?  Post all output
please.

Thanks,
Ralf

    Ensure functions from resident modules may be used in atexit handlers.
    
    * tests/resident.at (resident modules): New file, new test.
    * Makefile.am (TESTSUITE_AT): Adjust.
    Report by Bob Friesenhahn.

diff --git a/Makefile.am b/Makefile.am
index 4d727da..1524ce9 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -486,6 +486,7 @@ TESTSUITE_AT        = tests/testsuite.at \
                  tests/lt_dlopenext.at \
                  tests/ltdl-api.at \
                  tests/lalib-syntax.at \
+                 tests/resident.at \
                  tests/multiple-static-data.at \
                  tests/slist.at \
                  tests/need_lib_prefix.at \
diff --git a/tests/resident.at b/tests/resident.at
new file mode 100644
index 0000000..c2d1e6e
--- /dev/null
+++ b/tests/resident.at
@@ -0,0 +1,135 @@
+# resident.at -- test resident modules              -*- 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.
+####
+
+# Ensure resident modules are not unloaded at program exit:
+# they need to be able to invoke atexit handlers.
+
+AT_SETUP([resident modules])
+AT_KEYWORDS([libltdl])
+
+AT_DATA([main.c],
+[[#include <ltdl.h>
+#include <stdio.h>
+
+int
+main (int argc, char* argv[])
+{
+  int err = 0;
+  lt_dlhandle plugin_handle;
+  lt_dladvise advise;
+
+  if (argc < 2)
+    {
+      fprintf (stderr, "usage: %s plugin\n", argv[0]);
+      return 1;
+    }
+
+  lt_dlinit ();
+  if (lt_dladvise_init (&advise) != 0
+      || lt_dladvise_ext (&advise) != 0
+      || lt_dladvise_resident (&advise) != 0)
+    {
+      printf ("advise failure: %s\n", lt_dlerror ());
+      err = 1;
+    }
+  else
+    {
+      plugin_handle = lt_dlopenadvise (argv[1], advise);
+      if (NULL != plugin_handle)
+       {
+         int (*pf) (void);
+         printf ("plugin opened successfully!\n");
+         pf = lt_dlsym (plugin_handle, "setup_plugin");
+         if (pf)
+           pf ();
+         else
+           {
+             printf ("dlsym failure: %s\n", lt_dlerror ());
+             err = 1;
+           }
+         if (!lt_dlisresident (plugin_handle))
+           {
+             printf ("module wrongly not marked resident\n");
+             err = 1;
+           }
+         if (lt_dlclose (plugin_handle) != 0)
+           {
+             printf ("close failure (expected): %s\n", lt_dlerror ());
+           }
+         else
+           {
+             printf ("wrongly closed resident module\n");
+             err = 1;
+           }
+       }
+      else
+       {
+         printf ("plugin failed to open: %s\n", lt_dlerror ());
+         err = 1;
+       }
+      if (lt_dladvise_destroy (&advise) != 0)
+       {
+         printf ("advise destroy failure: %s\n", lt_dlerror ());
+         err = 1;
+       }
+    }
+  lt_dlexit ();
+  return err;
+}
+]])
+
+AT_DATA([plugin.c],
+[[#include <stdlib.h>
+
+void
+bye (void)
+{
+  puts ("called from atexit handler");
+}
+
+int
+setup_plugin (void)
+{
+  atexit (bye);
+}
+]])
+
+: ${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 plugin.c],
+        [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o plugin.la -rpath 
$libdir ]dnl
+        [-module -avoid-version plugin.lo], [], [ignore], [ignore])
+AT_CHECK([$LIBTOOL --mode=link $CC $CFLAGS $LDFLAGS -o main$EXEEXT 
main.$OBJEXT ]dnl
+        [-dlopen plugin.la $LIBLTDL],
+        [], [ignore], [ignore])
+LT_AT_EXEC_CHECK([./main], [], [stdout], [ignore], [./plugin.la])
+AT_CHECK([grep 'called from atexit handler' stdout], [], [ignore])
+
+AT_CLEANUP




reply via email to

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