mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-02-09 12:25:48 +01:00
[typelib] Clean up dlopen handling
It's was busted that g_typelib_new_* does the dlopen() since that caused g-ir-compiler to load the modules even though it wasn't going to do anything with them. Instead, change things so that g_module_symbol does the dlopen on-demand. Remove the extra dlopen(NULL) inside girepository.c, we had another already in gtypelib.c. Thanks to Owen Taylor for suggesting this approach.
This commit is contained in:
parent
90de854ee5
commit
1735ebde9a
@ -363,9 +363,6 @@ register_internal (GIRepository *repository,
|
|||||||
g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
|
g_hash_table_insert (repository->priv->typelibs, key, (void *)typelib);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typelib->modules == NULL)
|
|
||||||
typelib->modules = g_list_append(typelib->modules, g_module_open (NULL, 0));
|
|
||||||
|
|
||||||
return namespace;
|
return namespace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
169
gtypelib.c
169
gtypelib.c
@ -1946,86 +1946,99 @@ g_typelib_error_quark (void)
|
|||||||
return quark;
|
return quark;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void
|
static void
|
||||||
_g_typelib_init (GTypelib *typelib)
|
_g_typelib_do_dlopen (GTypelib *typelib)
|
||||||
{
|
{
|
||||||
Header *header;
|
Header *header;
|
||||||
|
const char *shlib_str;
|
||||||
|
|
||||||
header = (Header *) typelib->data;
|
header = (Header *) typelib->data;
|
||||||
|
/* note that NULL shlib means to open the main app, which is allowed */
|
||||||
if (header->shared_library)
|
if (header->shared_library)
|
||||||
|
shlib_str = g_typelib_get_string (typelib, header->shared_library);
|
||||||
|
else
|
||||||
|
shlib_str = NULL;
|
||||||
|
|
||||||
|
if (shlib_str != NULL && shlib_str[0] != '\0')
|
||||||
{
|
{
|
||||||
const gchar *shlib_str;
|
gchar **shlibs;
|
||||||
GModule *app_module = NULL;
|
gint i;
|
||||||
|
|
||||||
shlib_str = g_typelib_get_string (typelib, header->shared_library);
|
/* shared-library is a comma-separated list of libraries */
|
||||||
/* note that NULL shlib means to open the main app, which is allowed */
|
shlibs = g_strsplit (shlib_str, ",", 0);
|
||||||
|
|
||||||
if (shlib_str != NULL)
|
/* We load all passed libs unconditionally as if the same library is loaded
|
||||||
|
* again with dlopen(), the same file handle will be returned. See bug:
|
||||||
|
* http://bugzilla.gnome.org/show_bug.cgi?id=555294
|
||||||
|
*/
|
||||||
|
for (i = 0; shlibs[i]; i++)
|
||||||
{
|
{
|
||||||
gchar **shlibs;
|
GModule *module;
|
||||||
gint i;
|
|
||||||
|
|
||||||
/* shared-library is a comma-separated list of libraries */
|
/* Glade's autoconnect feature and OpenGL's extension mechanism
|
||||||
shlibs = g_strsplit (shlib_str, ",", 0);
|
* as used by Clutter rely on dlopen(NULL) to work as a means of
|
||||||
|
* accessing the app's symbols. This keeps us from using
|
||||||
/* We load all passed libs unconditionally as if the same library is loaded
|
* G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
|
||||||
* again with dlopen(), the same file handle will be returned. See bug:
|
* in general libraries are not expecting multiple copies of
|
||||||
* http://bugzilla.gnome.org/show_bug.cgi?id=555294
|
* themselves and are not expecting to be unloaded. So we just
|
||||||
|
* load modules globally for now.
|
||||||
*/
|
*/
|
||||||
for (i = 0; shlibs[i]; i++)
|
|
||||||
|
module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
|
||||||
|
|
||||||
|
if (module == NULL)
|
||||||
{
|
{
|
||||||
GModule *module;
|
GString *shlib_full = g_string_new (shlibs[i]);
|
||||||
|
|
||||||
/* Glade's autoconnect feature and OpenGL's extension mechanism
|
/* Prefix with "lib", try both .la and .so */
|
||||||
* as used by Clutter rely on dlopen(NULL) to work as a means of
|
if (!g_str_has_prefix (shlib_full->str, "lib"))
|
||||||
* accessing the app's symbols. This keeps us from using
|
g_string_prepend (shlib_full, "lib");
|
||||||
* G_MODULE_BIND_LOCAL. BIND_LOCAL may have other issues as well;
|
g_string_append (shlib_full, ".la");
|
||||||
* in general libraries are not expecting multiple copies of
|
module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
|
||||||
* themselves and are not expecting to be unloaded. So we just
|
if (module == NULL)
|
||||||
* load modules globally for now.
|
|
||||||
*/
|
|
||||||
|
|
||||||
module = g_module_open (shlibs[i], G_MODULE_BIND_LAZY);
|
|
||||||
|
|
||||||
if (module == NULL)
|
|
||||||
{
|
|
||||||
GString *shlib_full = g_string_new (shlibs[i]);
|
|
||||||
|
|
||||||
/* Prefix with "lib", try both .la and .so */
|
|
||||||
if (!g_str_has_prefix (shlib_full->str, "lib"))
|
|
||||||
g_string_prepend (shlib_full, "lib");
|
|
||||||
g_string_append (shlib_full, ".la");
|
|
||||||
module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
|
|
||||||
if (module == NULL)
|
|
||||||
{
|
|
||||||
g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
|
|
||||||
module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
|
|
||||||
}
|
|
||||||
|
|
||||||
g_string_free (shlib_full, TRUE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (module == NULL)
|
|
||||||
{
|
{
|
||||||
g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
|
g_string_overwrite (shlib_full, strlen (shlib_full->str)-2, SHLIB_SUFFIX);
|
||||||
shlibs[i], g_module_error ());
|
module = g_module_open (shlib_full->str, G_MODULE_BIND_LAZY);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
typelib->modules = g_list_append (typelib->modules, module);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
g_strfreev (shlibs);
|
g_string_free (shlib_full, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* we should make sure the app_module in the end of list so that
|
if (module == NULL)
|
||||||
* it's last symbol source when loading any symbols from modules.
|
{
|
||||||
* See comments in g_typelib_symbol */
|
g_warning ("Failed to load shared library '%s' referenced by the typelib: %s",
|
||||||
app_module = g_module_open (NULL, G_MODULE_BIND_LAZY);
|
shlibs[i], g_module_error ());
|
||||||
if (app_module)
|
}
|
||||||
typelib->modules = g_list_append (typelib->modules, app_module);
|
else
|
||||||
|
{
|
||||||
|
typelib->modules = g_list_append (typelib->modules, module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (shlibs);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* If there's no shared-library entry for this module, assume that
|
||||||
|
* the module is for the application. Some of the hand-written .gir files
|
||||||
|
* in gobject-introspection don't have shared-library entries, but no one
|
||||||
|
* is really going to be calling g_module_symbol on them either.
|
||||||
|
*/
|
||||||
|
GModule *module = g_module_open (NULL, 0);
|
||||||
|
if (module == NULL)
|
||||||
|
g_warning ("gtypelib.c: Failed to g_module_open (NULL): %s", g_module_error ());
|
||||||
|
else
|
||||||
|
typelib->modules = g_list_prepend (typelib->modules, module);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void
|
||||||
|
_g_typelib_ensure_open (GTypelib *typelib)
|
||||||
|
{
|
||||||
|
if (typelib->open_attempted)
|
||||||
|
return;
|
||||||
|
typelib->open_attempted = TRUE;
|
||||||
|
_g_typelib_do_dlopen (typelib);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2049,7 +2062,7 @@ g_typelib_new_from_memory (guchar *memory, gsize len)
|
|||||||
meta->len = len;
|
meta->len = len;
|
||||||
meta->owns_memory = TRUE;
|
meta->owns_memory = TRUE;
|
||||||
meta->modules = NULL;
|
meta->modules = NULL;
|
||||||
_g_typelib_init (meta);
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2072,7 +2085,7 @@ g_typelib_new_from_const_memory (const guchar *memory, gsize len)
|
|||||||
meta->len = len;
|
meta->len = len;
|
||||||
meta->owns_memory = FALSE;
|
meta->owns_memory = FALSE;
|
||||||
meta->modules = NULL;
|
meta->modules = NULL;
|
||||||
_g_typelib_init (meta);
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2094,7 +2107,7 @@ g_typelib_new_from_mapped_file (GMappedFile *mfile)
|
|||||||
meta->owns_memory = FALSE;
|
meta->owns_memory = FALSE;
|
||||||
meta->data = (guchar *) g_mapped_file_get_contents (mfile);
|
meta->data = (guchar *) g_mapped_file_get_contents (mfile);
|
||||||
meta->len = g_mapped_file_get_length (mfile);
|
meta->len = g_mapped_file_get_length (mfile);
|
||||||
_g_typelib_init (meta);
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2140,21 +2153,19 @@ gboolean
|
|||||||
g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
|
g_typelib_symbol (GTypelib *typelib, const char *symbol_name, gpointer *symbol)
|
||||||
{
|
{
|
||||||
GList *l;
|
GList *l;
|
||||||
|
|
||||||
|
_g_typelib_ensure_open (typelib);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We want to be able to add symbols to an app or an auxiliary
|
* The reason for having multiple modules dates from gir-repository
|
||||||
* library to fill in gaps in an introspected library. However,
|
* when it was desired to inject code (accessors, etc.) into an
|
||||||
* normally we would only look for symbols in the main library
|
* existing library. In that situation, the first module listed
|
||||||
* (the first items in typelib->modules).
|
* will be the custom one, which overrides the main one. A bit
|
||||||
*
|
* inefficient, but the problem will go away when gir-repository
|
||||||
* A more elaborate solution is probably possible, but as a
|
* does.
|
||||||
* simple approach for now, if we fail to find a symbol we look
|
*
|
||||||
* for it in the global module (the last item in type->modules).
|
* For modules with no shared library, we dlopen'd the current
|
||||||
*
|
* process above.
|
||||||
* This would not be very efficient if it happened often, since
|
|
||||||
* we always do the failed lookup above first, but very few
|
|
||||||
* symbols should be outside of the main libraries in
|
|
||||||
* typelib->modules so it doesn't matter.
|
|
||||||
*/
|
*/
|
||||||
for (l = typelib->modules; l; l = l->next)
|
for (l = typelib->modules; l; l = l->next)
|
||||||
{
|
{
|
||||||
|
@ -1021,6 +1021,7 @@ struct _GTypelib {
|
|||||||
gboolean owns_memory;
|
gboolean owns_memory;
|
||||||
GMappedFile *mfile;
|
GMappedFile *mfile;
|
||||||
GList *modules;
|
GList *modules;
|
||||||
|
gboolean open_attempted;
|
||||||
};
|
};
|
||||||
|
|
||||||
DirEntry *g_typelib_get_dir_entry (GTypelib *typelib,
|
DirEntry *g_typelib_get_dir_entry (GTypelib *typelib,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user