From 57a7a2b0100589ec6018b23aef935dc10d7923ce Mon Sep 17 00:00:00 2001 From: Sebastian Wilhelmi Date: Fri, 22 Dec 2000 13:44:25 +0000 Subject: [PATCH] Determine the suffix of the shared librarries for this system. This is 2000-12-22 Sebastian Wilhelmi * 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. --- ChangeLog | 13 +++ ChangeLog.pre-2-0 | 13 +++ ChangeLog.pre-2-10 | 13 +++ ChangeLog.pre-2-12 | 13 +++ ChangeLog.pre-2-2 | 13 +++ ChangeLog.pre-2-4 | 13 +++ ChangeLog.pre-2-6 | 13 +++ ChangeLog.pre-2-8 | 13 +++ configure.in | 19 ++++ docs/reference/ChangeLog | 6 ++ docs/reference/glib/glib-sections.txt | 1 + docs/reference/glib/tmpl/modules.sgml | 25 ++++- gmodule/ChangeLog | 20 ++++ gmodule/gmodule-dl.c | 18 ++-- gmodule/gmodule.c | 171 ++++++++++++++++++++++++++--- gmodule/testgmodule.c | 13 +-- tests/.cvsignore | 3 + tests/Makefile.am | 18 ++++ tests/libmoduletestplugin_a.c | 68 ++++++++++++ tests/libmoduletestplugin_b.c | 67 ++++++++++++ tests/module-test.c | 198 ++++++++++++++++++++++++++++++++++ 21 files changed, 695 insertions(+), 36 deletions(-) create mode 100644 tests/libmoduletestplugin_a.c create mode 100644 tests/libmoduletestplugin_b.c create mode 100644 tests/module-test.c diff --git a/ChangeLog b/ChangeLog index 05e2205..3e2ce78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-0 b/ChangeLog.pre-2-0 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-0 +++ b/ChangeLog.pre-2-0 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-10 b/ChangeLog.pre-2-10 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-10 +++ b/ChangeLog.pre-2-10 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-12 b/ChangeLog.pre-2-12 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-12 +++ b/ChangeLog.pre-2-12 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-2 b/ChangeLog.pre-2-2 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-2 +++ b/ChangeLog.pre-2-2 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-4 b/ChangeLog.pre-2-4 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-4 +++ b/ChangeLog.pre-2-4 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-6 b/ChangeLog.pre-2-6 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-6 +++ b/ChangeLog.pre-2-6 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/ChangeLog.pre-2-8 b/ChangeLog.pre-2-8 index 05e2205..3e2ce78 100644 --- a/ChangeLog.pre-2-8 +++ b/ChangeLog.pre-2-8 @@ -1,3 +1,16 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * grand.c: Updated G_RAND_DOUBLE_TRANSFORM to be more diff --git a/configure.in b/configure.in index 0eec822..b0174ee 100644 --- a/configure.in +++ b/configure.in @@ -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" diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index c24794f..92634cf 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,9 @@ +2000-12-22 Sebastian Wilhelmi + + * glib/glib-sections.txt: Added G_MODULE_SUFFIX. + + * glib/tmpl/modules.sgml: Updated. + 2000-12-19 Sebastian Wilhelmi * glib/glib-sections.txt: Added g_rand_boolean and diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt index 034086c..3eb8f11 100644 --- a/docs/reference/glib/glib-sections.txt +++ b/docs/reference/glib/glib-sections.txt @@ -1094,6 +1094,7 @@ g_module_error GModuleCheckInit GModuleUnload +G_MODULE_SUFFIX G_MODULE_EXPORT G_MODULE_IMPORT diff --git a/docs/reference/glib/tmpl/modules.sgml b/docs/reference/glib/tmpl/modules.sgml index 9e33e67..0719be6 100644 --- a/docs/reference/glib/tmpl/modules.sgml +++ b/docs/reference/glib/tmpl/modules.sgml @@ -91,8 +91,20 @@ prefix and suffix. This should be freed when no longer needed. -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. + + + +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. @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. + + +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". + + + + Used to declare functions exported by modules. diff --git a/gmodule/ChangeLog b/gmodule/ChangeLog index 3ffd54e..364f251 100644 --- a/gmodule/ChangeLog +++ b/gmodule/ChangeLog @@ -1,3 +1,23 @@ +2000-12-22 Sebastian Wilhelmi + + * 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 * Makefile.am (BUILT_EXTRA_DIST): New variable. diff --git a/gmodule/gmodule-dl.c b/gmodule/gmodule-dl.c index 7b4b7c1..9df56d4 100644 --- a/gmodule/gmodule-dl.c +++ b/gmodule/gmodule-dl.c @@ -71,13 +71,17 @@ /* --- 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; } diff --git a/gmodule/gmodule.c b/gmodule/gmodule.c index b437046..d3aefcf 100644 --- a/gmodule/gmodule.c +++ b/gmodule/gmodule.c @@ -28,11 +28,19 @@ * MT safe */ +#ifdef HAVE_CONFIG_H +# include +#endif #include "gmodule.h" #include "gmoduleconf.h" #include #include - +#include +#include +#include +#ifdef HAVE_UNISTD_H +# include +#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* diff --git a/gmodule/testgmodule.c b/gmodule/testgmodule.c index db21375..17257e3 100644 --- a/gmodule/testgmodule.c +++ b/gmodule/testgmodule.c @@ -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 diff --git a/tests/.cvsignore b/tests/.cvsignore index 4f67021..9256a23 100644 --- a/tests/.cvsignore +++ b/tests/.cvsignore @@ -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 diff --git a/tests/Makefile.am b/tests/Makefile.am index ce1a108..f96efba 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -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 index 0000000..33d0635 --- /dev/null +++ b/tests/libmoduletestplugin_a.c @@ -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 +#include + +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 index 0000000..a9df3dd --- /dev/null +++ b/tests/libmoduletestplugin_b.c @@ -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 + +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 index 0000000..c83dfb2 --- /dev/null +++ b/tests/module-test.c @@ -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 + +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; +} -- 2.7.4