Determine the suffix of the shared librarries for this system. This is
authorSebastian Wilhelmi <wilhelmi@ira.uka.de>
Fri, 22 Dec 2000 13:44:25 +0000 (13:44 +0000)
committerSebastian Wilhelmi <wilhelmi@src.gnome.org>
Fri, 22 Dec 2000 13:44:25 +0000 (13:44 +0000)
2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>

* configure.in: Determine the suffix of the shared librarries for
this system. This is done analogous to
ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
"sl", "dll", or (most often) "so".

* tests/Makefile.am, tests/module-test.c,
tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
Added new testcase for gmodule. This is mostly copied from
gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
some tests that verbose, not to say loquacious...)

* gmodule.c: Make g_module_open more tolerant wrt to the module
name. First it tries to open the module as named, if that fails,
it checks, whether it is a libtool archive and parses it, if that
fails it appends the systems shared library suffix
(i.e. ".so") (if not already found) and tries again and if that
fails it tries to append the ".la" libtool suffix (if not already
found) and parses it.

* gmodule.c: Lock recursive mutex during most module functions for
safety.

* gmodule-dl.c: Return an error from _g_module_symbol only, if
dlerror says so. All other functions return an error as well, if
dlerror returns NULL.

* testgmodule.c: Thanks to the above change the #ifdefs have
vanished.

* glib/glib-sections.txt: Added G_MODULE_SUFFIX.

* glib/tmpl/modules.sgml: Updated.

21 files changed:
ChangeLog
ChangeLog.pre-2-0
ChangeLog.pre-2-10
ChangeLog.pre-2-12
ChangeLog.pre-2-2
ChangeLog.pre-2-4
ChangeLog.pre-2-6
ChangeLog.pre-2-8
configure.in
docs/reference/ChangeLog
docs/reference/glib/glib-sections.txt
docs/reference/glib/tmpl/modules.sgml
gmodule/ChangeLog
gmodule/gmodule-dl.c
gmodule/gmodule.c
gmodule/testgmodule.c
tests/.cvsignore
tests/Makefile.am
tests/libmoduletestplugin_a.c [new file with mode: 0644]
tests/libmoduletestplugin_b.c [new file with mode: 0644]
tests/module-test.c [new file with mode: 0644]

index 05e2205..3e2ce78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 05e2205..3e2ce78 100644 (file)
@@ -1,3 +1,16 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * configure.in: Determine the suffix of the shared librarries for
+       this system. This is done analogous to
+       ltconfig.sh. G_MODULE_SUFFIX in glibconfig.h is set to either
+       "sl", "dll", or (most often) "so".
+
+       * tests/Makefile.am, tests/module-test.c,
+       tests/libmoduletestplugin_a.c, tests/libmoduletestplugin_b.c:
+       Added new testcase for gmodule. This is mostly copied from
+       gmodule/testgmodule.c, but unlike that is is quiet. (Why BTW are
+       some tests that verbose, not to say loquacious...)
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more
index 0eec822..b0174ee 100644 (file)
@@ -680,6 +680,21 @@ dnl *** done, have e got an implementation?
 if test -z "$G_MODULE_IMPL"; then
        G_MODULE_IMPL=0
 fi
+
+AC_MSG_CHECKING(for the suffix of shared libraries)
+case "$host_os" in
+  hpux9* | hpux10* | hpux11*)  # taken from ltconfig
+    glib_gmodule_suffix='sl'
+    ;;
+  cygwin* | mingw*)
+    glib_gmodule_suffix='dll'
+    ;;
+  *)
+    glib_gmodule_suffix='so'    
+    ;;
+esac
+AC_MSG_RESULT(.$glib_gmodule_suffix)
 AC_SUBST(G_MODULE_IMPL)
 AC_SUBST(G_MODULE_LIBS)
 AC_SUBST(G_MODULE_LIBS_EXTRA)
@@ -1499,6 +1514,8 @@ _______EOF
 
        cat >>$outfile <<_______EOF
 
+#define G_MODULE_SUFFIX "$g_module_suffix"
+
 G_END_DECLS
 
 #endif /* GLIBCONFIG_H */
@@ -1709,6 +1726,8 @@ g_mutex_sizeof="$glib_cv_sizeof_gmutex"
 g_system_thread_sizeof="$glib_cv_sizeof_system_thread"
 g_mutex_contents="$glib_cv_byte_contents_gmutex"
 
+g_module_suffix="$glib_gmodule_suffix"
+
 case $host in
   *-*-beos*)
     glib_os="#define G_OS_BEOS"
index c24794f..92634cf 100644 (file)
@@ -1,3 +1,9 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * glib/glib-sections.txt: Added G_MODULE_SUFFIX.
+
+       * glib/tmpl/modules.sgml: Updated.
+
 2000-12-19  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
 
        * glib/glib-sections.txt: Added g_rand_boolean and
index 034086c..3eb8f11 100644 (file)
@@ -1094,6 +1094,7 @@ g_module_error
 <SUBSECTION>
 GModuleCheckInit
 GModuleUnload
+G_MODULE_SUFFIX
 G_MODULE_EXPORT
 G_MODULE_IMPORT
 </SECTION>
index 9e33e67..0719be6 100644 (file)
@@ -91,8 +91,20 @@ prefix and suffix. This should be freed when no longer needed.
 
 <!-- ##### FUNCTION g_module_open ##### -->
 <para>
-Opens a module.
-If the module has already been opened, its reference count is incremented.
+Opens a module. If the module has already been opened, its reference
+count is incremented. 
+</para>
+
+<para>
+First of all g_module_open() tries to open @file_name as a module. If
+that fails and @file_name has the ".la"-suffix (and is a libtool
+archive) it tries to open the corresponding module. If that fails and
+it doesn't have the proper module suffix for that plaform
+(#G_MODULE_SUFFIX,) this suffix will be appended and the coresponding
+module will be opended. If that fails and @file_name doesn't have the
+".la"-suffix, this suffix is appended and g_module_open() tries to
+open the corresponding module. If eventually that fails as well, NULL
+is returned.
 </para>
 
 @file_name: the name of the file containing the module.
@@ -183,6 +195,15 @@ It is passed the #GModule structure.
 @module: the module about to be unloaded.
 
 
+<!-- ##### MACRO G_MODULE_SUFFIX ##### -->
+<para>
+Expands to the proper shared library suffix for the current platform
+without the leading dot. For the most Unices and Linux this is "so",
+for some HPUX versions this is "sl" and for Windows this is "dll".
+</para>
+
+
+
 <!-- ##### MACRO G_MODULE_EXPORT ##### -->
 <para>
 Used to declare functions exported by modules.
index 3ffd54e..364f251 100644 (file)
@@ -1,3 +1,23 @@
+2000-12-22  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>
+
+       * gmodule.c: Make g_module_open more tolerant wrt to the module
+       name. First it tries to open the module as named, if that fails,
+       it checks, whether it is a libtool archive and parses it, if that
+       fails it appends the systems shared library suffix
+       (i.e. ".so") (if not already found) and tries again and if that
+       fails it tries to append the ".la" libtool suffix (if not already
+       found) and parses it.
+
+       * gmodule.c: Lock recursive mutex during most module functions for
+       safety.
+
+       * gmodule-dl.c: Return an error from _g_module_symbol only, if
+       dlerror says so. All other functions return an error as well, if
+       dlerror returns NULL.
+
+       * testgmodule.c: Thanks to the above change the #ifdefs have
+       vanished.
+
 2000-10-15  Raja R Harinath  <harinath@cs.umn.edu>
 
        * Makefile.am (BUILT_EXTRA_DIST): New variable.
index 7b4b7c1..9df56d4 100644 (file)
 
 /* --- functions --- */
 static gchar*
-fetch_dlerror (void)
+fetch_dlerror (gboolean replace_null)
 {
   gchar *msg = dlerror ();
 
-  /* make sure we always return an error message != NULL */
+  /* make sure we always return an error message != NULL, if
+   * expected to do so. */
 
-  return msg ? msg : "unknown dl-error";
+  if (!msg && replace_null)
+    return "unknown dl-error";
+
+  return msg;
 }
 
 static gpointer
@@ -88,7 +92,7 @@ _g_module_open (const gchar *file_name,
   
   handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
   if (!handle)
-    g_module_set_error (fetch_dlerror ());
+    g_module_set_error (fetch_dlerror (TRUE));
   
   return handle;
 }
@@ -104,7 +108,7 @@ _g_module_self (void)
   
   handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
   if (!handle)
-    g_module_set_error (fetch_dlerror ());
+    g_module_set_error (fetch_dlerror (TRUE));
   
   return handle;
 }
@@ -121,7 +125,7 @@ _g_module_close (gpointer handle,
   if (is_unref)
     {
       if (dlclose (handle) != 0)
-       g_module_set_error (fetch_dlerror ());
+       g_module_set_error (fetch_dlerror (TRUE));
     }
 }
 
@@ -133,7 +137,7 @@ _g_module_symbol (gpointer     handle,
   
   p = dlsym (handle, symbol_name);
   if (!p)
-    g_module_set_error (fetch_dlerror ());
+    g_module_set_error (fetch_dlerror (FALSE));
   
   return p;
 }
index b437046..d3aefcf 100644 (file)
  * MT safe
  */
 
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
 #include       "gmodule.h"
 #include       "gmoduleconf.h"
 #include       <errno.h>
 #include       <string.h>
-
+#include       <sys/types.h>
+#include       <sys/stat.h>
+#include       <fcntl.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
 
 /* We maintain a list of modules, so we can reference count them.
  * That's needed because some platforms don't support refernce counts on
@@ -71,7 +79,6 @@ static inline GModule*        g_module_find_by_name   (const gchar    *name);
 
 
 /* --- variables --- */
-G_LOCK_DEFINE_STATIC (GModule);
 const char           *g_log_domain_gmodule = "GModule";
 static GModule      *modules = NULL;
 static GModule      *main_module = NULL;
@@ -85,7 +92,6 @@ g_module_find_by_handle (gpointer handle)
   GModule *module;
   GModule *retval = NULL;
   
-  G_LOCK (GModule);
   if (main_module && main_module->handle == handle)
     retval = main_module;
   else
@@ -95,7 +101,6 @@ g_module_find_by_handle (gpointer handle)
          retval = module;
          break;
        }
-  G_UNLOCK (GModule);
 
   return retval;
 }
@@ -106,14 +111,12 @@ g_module_find_by_name (const gchar *name)
   GModule *module;
   GModule *retval = NULL;
   
-  G_LOCK (GModule);
   for (module = modules; module; module = module->next)
     if (strcmp (name, module->file_name) == 0)
        {
          retval = module;
          break;
        }
-  G_UNLOCK (GModule);
 
   return retval;
 }
@@ -177,6 +180,103 @@ g_module_supported (void)
   return TRUE;
 }
 
+static gchar*
+parse_libtool_archive (const gchar* libtool_name)
+{
+  const gint TOKEN_DLNAME = G_TOKEN_LAST + 1;
+  const gint TOKEN_INSTALLED = G_TOKEN_LAST + 2;
+  const gint TOKEN_LIBDIR = G_TOKEN_LAST + 3;
+  gchar *lt_dlname = NULL;
+  gboolean lt_installed = TRUE;
+  gchar *lt_libdir = NULL;
+  gchar *name;
+  GTokenType token;
+  GScanner *scanner;
+  
+  int fd = open (libtool_name, O_RDONLY, 0);
+  if (fd < 0)
+    {
+      g_module_set_error ("couldn't open libtool archive");   
+      return NULL;
+    }
+  /* search libtool's dlname specification  */
+  scanner = g_scanner_new (NULL);
+  g_scanner_input_file (scanner, fd);
+  scanner->config->symbol_2_token = TRUE;
+  g_scanner_scope_add_symbol (scanner, 0, "dlname", 
+                             GUINT_TO_POINTER (TOKEN_DLNAME));
+  g_scanner_scope_add_symbol (scanner, 0, "installed", 
+                             GUINT_TO_POINTER (TOKEN_INSTALLED));
+  g_scanner_scope_add_symbol (scanner, 0, "libdir", 
+                             GUINT_TO_POINTER (TOKEN_LIBDIR));
+  while (!g_scanner_eof (scanner))
+    {
+      token = g_scanner_get_next_token (scanner);
+      if (token == TOKEN_DLNAME || token == TOKEN_INSTALLED || 
+         token == TOKEN_LIBDIR)
+       {
+         if (g_scanner_get_next_token (scanner) != '=' ||
+             g_scanner_get_next_token (scanner) != 
+             (token == TOKEN_INSTALLED ? 
+              G_TOKEN_IDENTIFIER : G_TOKEN_STRING))
+           {
+             g_module_set_error ("libtool archive has unknown format"); 
+
+             g_free (lt_dlname);
+             g_free (lt_libdir);
+             g_scanner_destroy (scanner);
+             close (fd);
+
+             return NULL;
+           }
+         else
+           {
+             if (token == TOKEN_DLNAME)
+               {
+                 g_free (lt_dlname);
+                 lt_dlname = g_strdup (scanner->value.v_string);
+               }
+             else if (token == TOKEN_INSTALLED)
+               lt_installed = 
+                 strcmp (scanner->value.v_identifier, "yes") == 0;
+             else /* token == TOKEN_LIBDIR */
+               {
+                 g_free (lt_libdir);
+                 lt_libdir = g_strdup (scanner->value.v_string);
+               }
+           }
+       }      
+    }
+
+  if (!lt_installed)
+    {
+      gchar *dir = g_path_get_dirname (libtool_name);
+      g_free (lt_libdir);
+      lt_libdir = g_strconcat (dir, G_DIR_SEPARATOR_S ".libs", NULL);
+    }
+
+  name = g_module_build_path (lt_libdir, lt_dlname);
+  
+  g_free (lt_dlname);
+  g_free (lt_libdir);
+  g_scanner_destroy (scanner);
+  close (fd);
+
+  return name;
+}
+
+static inline gboolean
+g_str_check_suffix (const gchar* string, const gchar* suffix)
+{
+  guint string_len = strlen (string);
+  guint suffix_len = strlen (suffix);
+
+  return string_len >= suffix_len && 
+    strcmp (string + string_len - suffix_len, suffix) == 0;
+}
+
+static GStaticRecMutex g_module_global_lock = G_STATIC_REC_MUTEX_INIT;
+
 GModule*
 g_module_open (const gchar    *file_name,
               GModuleFlags    flags)
@@ -186,9 +286,9 @@ g_module_open (const gchar    *file_name,
   
   SUPPORT_OR_RETURN (NULL);
   
+  g_static_rec_mutex_lock (&g_module_global_lock);
   if (!file_name)
     {      
-      G_LOCK (GModule);
       if (!main_module)
        {
          handle = _g_module_self ();
@@ -203,8 +303,8 @@ g_module_open (const gchar    *file_name,
              main_module->next = NULL;
            }
        }
-      G_UNLOCK (GModule);
 
+      g_static_rec_mutex_unlock (&g_module_global_lock);
       return main_module;
     }
   
@@ -214,11 +314,46 @@ g_module_open (const gchar    *file_name,
     {
       module->ref_count++;
       
+      g_static_rec_mutex_unlock (&g_module_global_lock);
       return module;
     }
   
-  /* open the module */
+  /* First we try to open the module as provided */
   handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
+
+  /* If not found, we check, if it is a libtool archive */
+  if (!handle && g_str_check_suffix (file_name, ".la"))
+    {
+      gchar *name = parse_libtool_archive (file_name);
+      if (name)
+       {
+         handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+         g_free (name);
+       }
+    }
+
+  /* If still not found, we check, if it is a library name without suffix */
+  if (!handle && !g_str_check_suffix (file_name, "." G_MODULE_SUFFIX))
+    {
+      gchar *name = g_strconcat (file_name, "." G_MODULE_SUFFIX, NULL);
+      handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+      g_free (name);
+    }
+
+  /* If still not found, we check, if it is a libtool archive name
+   * without suffix */
+  if (!handle && !g_str_check_suffix (file_name, ".la"))
+    {
+      gchar *la_name = g_strconcat (file_name, ".la", NULL);
+      gchar *name = parse_libtool_archive (la_name);
+      if (name)
+       {
+         handle = _g_module_open (name, (flags & G_MODULE_BIND_LAZY) != 0);
+         g_free (name);
+       }
+      g_free (la_name);
+    }
+
   if (handle)
     {
       gchar *saved_error;
@@ -233,6 +368,7 @@ g_module_open (const gchar    *file_name,
          module->ref_count++;
          g_module_set_error (NULL);
          
+         g_static_rec_mutex_unlock (&g_module_global_lock);
          return module;
        }
       
@@ -245,10 +381,8 @@ g_module_open (const gchar    *file_name,
       module->ref_count = 1;
       module->is_resident = FALSE;
       module->unload = NULL;
-      G_LOCK (GModule);
       module->next = modules;
       modules = module;
-      G_UNLOCK (GModule);
       
       /* check initialization */
       if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
@@ -273,7 +407,8 @@ g_module_open (const gchar    *file_name,
 
       g_free (saved_error);
     }
-  
+
+  g_static_rec_mutex_unlock (&g_module_global_lock);
   return module;
 }
 
@@ -285,6 +420,8 @@ g_module_close (GModule            *module)
   g_return_val_if_fail (module != NULL, FALSE);
   g_return_val_if_fail (module->ref_count > 0, FALSE);
   
+  g_static_rec_mutex_lock (&g_module_global_lock);
+
   module->ref_count--;
   
   if (!module->ref_count && !module->is_resident && module->unload)
@@ -303,7 +440,6 @@ g_module_close (GModule            *module)
       
       last = NULL;
       
-      G_LOCK (GModule);
       node = modules;
       while (node)
        {
@@ -319,7 +455,6 @@ g_module_close (GModule            *module)
          node = last->next;
        }
       module->next = NULL;
-      G_UNLOCK (GModule);
       
       _g_module_close (module->handle, FALSE);
       g_free (module->file_name);
@@ -327,6 +462,7 @@ g_module_close (GModule            *module)
       g_free (module);
     }
   
+  g_static_rec_mutex_unlock (&g_module_global_lock);
   return g_module_error() == NULL;
 }
 
@@ -359,6 +495,8 @@ g_module_symbol (GModule    *module,
   g_return_val_if_fail (symbol_name != NULL, FALSE);
   g_return_val_if_fail (symbol != NULL, FALSE);
   
+  g_static_rec_mutex_lock (&g_module_global_lock);
+
 #ifdef G_MODULE_NEED_USCORE
   {
     gchar *name;
@@ -380,11 +518,10 @@ g_module_symbol (GModule  *module,
       g_module_set_error (error);
       g_free (error);
       *symbol = NULL;
-
-      return FALSE;
     }
   
-  return TRUE;
+  g_static_rec_mutex_unlock (&g_module_global_lock);
+  return !module_error;
 }
 
 gchar*
index db21375..17257e3 100644 (file)
@@ -54,16 +54,9 @@ main (int   arg,
   string = g_get_current_dir ();
   g_print ("testgmodule (%s):\n", string);
 
-#if (G_MODULE_IMPL == G_MODULE_IMPL_WIN32)
-  plugin_a = g_strconcat (string, "\\libgplugin_a.dll", NULL);
-  plugin_b = g_strconcat (string, "\\libgplugin_b.dll", NULL);
-#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
-  plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.sl", NULL);
-  plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.sl", NULL);
-#else /* neither DLD nor WIN32 */
-  plugin_a = g_strconcat (string, "/.libs/", "libgplugin_a.so", NULL);
-  plugin_b = g_strconcat (string, "/.libs/", "libgplugin_b.so", NULL);
-#endif
+  plugin_a = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_a", NULL);
+  plugin_b = g_strconcat (string, G_DIR_SEPARATOR_S "libgplugin_b", NULL);
+
   g_free (string);
 
   /* module handles
index 4f67021..9256a23 100644 (file)
@@ -6,6 +6,8 @@ Makefile.in
 makefile.msc
 makefile.mingw
 _libs
+libmoduletestplugin_a.la
+libmoduletestplugin_b.la
 array-test
 date-test
 dirname-test
@@ -13,6 +15,7 @@ hash-test
 list-test
 mainloop-test
 markup-test
+module-test
 node-test
 queue-test
 rand-test
index ce1a108..f96efba 100644 (file)
@@ -20,6 +20,7 @@ test_programs = \
        hash-test       \
        list-test       \
        mainloop-test   \
+       module-test     \
        node-test       \
        queue-test      \
        rand-test       \
@@ -45,6 +46,7 @@ TESTS_ENVIRONMENT = srcdir=$(srcdir)
 
 progs_LDADD = $(EFENCE) $(top_builddir)/libglib-1.3.la $(EFENCE)
 thread_LDADD = $(progs_LDADD) $(top_builddir)/gthread/libgthread-1.3.la @G_THREAD_LIBS@
+module_LDADD = $(progs_LDADD) $(top_builddir)/gmodule/libgmodule-1.3.la @G_MODULE_LIBS@
 
 array_test_LDADD = $(progs_LDADD)
 date_test_LDADD = $(progs_LDADD)
@@ -54,6 +56,8 @@ hash_test_LDADD = $(progs_LDADD)
 list_test_LDADD = $(progs_LDADD)
 mainloop_test_LDADD = $(thread_LDADD)
 markup_test_LDADD = $(progs_LDADD)
+module_test_LDADD = $(module_LDADD)
+module_test_LDFLAGS = @G_MODULE_LDFLAGS@
 node_test_LDADD = $(progs_LDADD)
 queue_test_LDADD = $(progs_LDADD)
 rand_test_LDADD = $(progs_LDADD)
@@ -68,6 +72,20 @@ threadpool_test_LDADD = $(thread_LDADD)
 tree_test_LDADD = $(progs_LDADD)
 type_test_LDADD = $(progs_LDADD)
 
+lib_LTLIBRARIES = libmoduletestplugin_a.la libmoduletestplugin_b.la
+
+# Prevent those libs from being installed
+install-libLTLIBRARIES:
+       :
+
+libmoduletestplugin_a_la_SOURCES = libmoduletestplugin_a.c
+libmoduletestplugin_a_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module
+libmoduletestplugin_a_la_LIBADD = @G_MODULE_LIBS@ 
+
+libmoduletestplugin_b_la_SOURCES = libmoduletestplugin_b.c
+libmoduletestplugin_b_la_LDFLAGS = @G_MODULE_LDFLAGS@ -avoid-version -module
+libmoduletestplugin_b_la_LIBADD = @G_MODULE_LIBS@  
+
 makefile.msc: $(top_builddir)/config.status $(top_srcdir)/tests/makefile.msc.in
        cd $(top_builddir) && CONFIG_FILES=tests/$@ CONFIG_HEADERS= $(SHELL) ./config.status
 
diff --git a/tests/libmoduletestplugin_a.c b/tests/libmoduletestplugin_a.c
new file mode 100644 (file)
index 0000000..33d0635
--- /dev/null
@@ -0,0 +1,68 @@
+/* libgplugin_a.c - test plugin for testgmodule
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include       <gmodule.h>
+#include       <stdlib.h>
+
+G_MODULE_EXPORT gchar* gplugin_a_state;
+
+G_MODULE_EXPORT void
+gplugin_a_func (void)
+{
+  gplugin_a_state = "Hello world";
+}
+
+G_MODULE_EXPORT void
+gplugin_clash_func (void)
+{
+  gplugin_a_state = "plugin clash";
+}
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+  gplugin_a_state = "global clash";
+}
+
+G_MODULE_EXPORT void
+gplugin_say_boo_func (void)
+{
+  gplugin_a_state = "BOOH";
+}
+
+G_MODULE_EXPORT void
+gplugin_a_module_func (GModule *module)
+{
+  void (*f) (void) = NULL;
+
+  if (!g_module_symbol (module, "gplugin_say_boo_func", (gpointer) &f))
+    {
+      g_print ("error: %s\n", g_module_error ());
+      exit (1);
+    }
+
+  f ();
+}
diff --git a/tests/libmoduletestplugin_b.c b/tests/libmoduletestplugin_b.c
new file mode 100644 (file)
index 0000000..a9df3dd
--- /dev/null
@@ -0,0 +1,67 @@
+/* libgplugin_b.c - test plugin for testgmodule
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include        <gmodule.h>
+
+G_MODULE_EXPORT gchar* gplugin_b_state;
+
+G_MODULE_EXPORT const gchar*
+g_module_check_init (GModule *module)
+{
+  gplugin_b_state = "check-init";
+
+  return NULL;
+}
+
+G_MODULE_EXPORT void
+g_module_unload (GModule *module)
+{
+  gplugin_b_state = "unloaded";
+}
+
+G_MODULE_EXPORT void
+gplugin_b_func (void)
+{
+  gplugin_b_state = "Hello world";
+}
+
+G_MODULE_EXPORT void
+gplugin_clash_func (void)
+{
+  gplugin_b_state = "plugin clash";
+}
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+  gplugin_b_state = "global clash";
+}
+
+G_MODULE_EXPORT void
+gplugin_say_boo_func (void)
+{
+  gplugin_b_state = "BOOH";
+}
diff --git a/tests/module-test.c b/tests/module-test.c
new file mode 100644 (file)
index 0000000..c83dfb2
--- /dev/null
@@ -0,0 +1,198 @@
+/* module-test.c - test program for GMODULE
+ * Copyright (C) 1998 Tim Janik
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GLib Team and others 1997-2000.  See the AUTHORS
+ * file for a list of people on the GLib Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GLib at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#include <gmodule.h>
+
+gchar* global_state;
+
+G_MODULE_EXPORT void
+g_clash_func (void)
+{
+  global_state = "global clash";
+}
+
+typedef        void (*SimpleFunc) (void);
+typedef        void (*GModuleFunc) (GModule *);
+
+static gchar **gplugin_a_state;
+static gchar **gplugin_b_state;
+
+static void
+compare (const gchar *desc, const gchar *expected, const gchar *found)
+{
+  if (!expected && !found)
+    return;
+  
+  if (expected && found && strcmp (expected, found) == 0)
+    return;
+    
+  g_error ("error: %s state should have been \"%s\", but is \"%s\"",
+          desc, expected ? expected : "NULL", found ? found : "NULL");
+}
+
+static void 
+test_states (const gchar *global, const gchar *gplugin_a, 
+            const gchar *gplugin_b)
+{      
+  compare ("global", global, global_state);
+  compare ("Plugin A", gplugin_a, *gplugin_a_state);
+  compare ("Plugin B", gplugin_b, *gplugin_b_state);
+  
+  global_state = *gplugin_a_state = *gplugin_b_state = NULL;
+}
+static SimpleFunc plugin_clash_func = NULL;
+
+int
+main (int   arg,
+      char *argv[])
+{
+  GModule *module_self, *module_a, *module_b;
+  gchar *dir;
+  gchar *plugin_a, *plugin_b;
+  SimpleFunc f_a, f_b, f_self;
+  GModuleFunc gmod_f;
+
+  if (!g_module_supported ())
+    return 0;
+
+  dir = g_get_current_dir ();
+
+  plugin_a = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_a", 
+                         NULL);
+  plugin_b = g_strconcat (dir, G_DIR_SEPARATOR_S "libmoduletestplugin_b", 
+                         NULL);
+
+  g_free (dir);
+
+  /* module handles */
+  
+  module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
+  if (!module_self)
+    g_error ("error: %s", g_module_error ());
+
+  if (!g_module_symbol (module_self, "g_module_close", (gpointer) &f_self))
+    g_error ("error: %s", g_module_error ());
+
+  module_a = g_module_open (plugin_a, G_MODULE_BIND_LAZY);
+  if (!module_a)
+    g_error ("error: %s", g_module_error ());
+
+  module_b = g_module_open (plugin_b, G_MODULE_BIND_LAZY);
+  if (!module_b)
+    g_error ("error: %s", g_module_error ());
+
+  /* get plugin state vars */
+
+  if (!g_module_symbol (module_a, "gplugin_a_state", 
+                       (gpointer) &gplugin_a_state))
+    g_error ("error: %s", g_module_error ());
+  
+  if (!g_module_symbol (module_b, "gplugin_b_state", 
+                       (gpointer) &gplugin_b_state))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, "check-init");
+  
+  /* get plugin specific symbols and call them
+   */
+  if (!g_module_symbol (module_a, "gplugin_a_func", (gpointer) &f_a))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+  if (!g_module_symbol (module_b, "gplugin_b_func", (gpointer) &f_b))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+  f_a ();
+  test_states (NULL, "Hello world", NULL);
+  
+  f_b ();
+  test_states (NULL, NULL, "Hello world");
+  
+  /* get and call globally clashing functions
+   */
+  if (!g_module_symbol (module_self, "g_clash_func", (gpointer) &f_self))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+
+  if (!g_module_symbol (module_a, "g_clash_func", (gpointer) &f_a))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+  if (!g_module_symbol (module_b, "g_clash_func", (gpointer) &f_b))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+  f_self ();
+  test_states ("global clash", NULL, NULL);
+  
+  f_a ();
+  test_states (NULL, "global clash", NULL);
+
+  f_b ();
+  test_states (NULL, NULL, "global clash");
+
+  /* get and call clashing plugin functions  */
+
+  if (!g_module_symbol (module_a, "gplugin_clash_func", (gpointer) &f_a))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+
+  if (!g_module_symbol (module_b, "gplugin_clash_func", (gpointer) &f_b))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+
+  plugin_clash_func = f_a;
+  plugin_clash_func ();
+  test_states (NULL, "plugin clash", NULL);
+
+  plugin_clash_func = f_b;
+  plugin_clash_func ();
+  test_states (NULL, NULL, "plugin clash");
+
+  /* call gmodule function from A  */
+
+  if (!g_module_symbol (module_a, "gplugin_a_module_func", (gpointer) &gmod_f))
+    g_error ("error: %s", g_module_error ());
+  test_states (NULL, NULL, NULL);
+
+  gmod_f (module_b);
+  test_states (NULL, NULL, "BOOH");
+  gmod_f (module_a);
+  test_states (NULL, "BOOH", NULL);
+
+  /* unload plugins  */
+
+  if (!g_module_close (module_a))
+    g_error ("error: %s", g_module_error ());
+
+  if (!g_module_close (module_b))
+    g_error ("error: %s", g_module_error ());
+  return 0;
+}