mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-06-02 02:40:07 +02:00
giomodule: When loading GIO_EXTRA_MODULES skip duplicates
* Load modules from paths listed in GIO_EXTRA_MODULES environment variable first. * Ignore duplicate modules based on module basename. * Add the concept of GIOModuleScope which allows other callers to skip duplicate loaded modules, or block specific modules based on basename. * Document behavior. https://bugzilla.gnome.org/show_bug.cgi?id=656914
This commit is contained in:
parent
78ec02647e
commit
d789e78dff
@ -1427,8 +1427,13 @@ g_desktop_app_info_lookup_get_type
|
|||||||
<TITLE>GIOModule</TITLE>
|
<TITLE>GIOModule</TITLE>
|
||||||
GIOModule
|
GIOModule
|
||||||
g_io_module_new
|
g_io_module_new
|
||||||
|
g_io_module_scope_block
|
||||||
|
g_io_module_scope_free
|
||||||
|
g_io_module_scope_new
|
||||||
g_io_modules_load_all_in_directory
|
g_io_modules_load_all_in_directory
|
||||||
|
g_io_modules_load_all_in_directory_with_scope
|
||||||
g_io_modules_scan_all_in_directory
|
g_io_modules_scan_all_in_directory
|
||||||
|
g_io_modules_scan_all_in_directory_with_scope
|
||||||
g_io_module_load
|
g_io_module_load
|
||||||
g_io_module_unload
|
g_io_module_unload
|
||||||
g_io_module_query
|
g_io_module_query
|
||||||
|
@ -503,8 +503,13 @@ g_io_error_from_win32_error
|
|||||||
#endif
|
#endif
|
||||||
g_io_module_get_type
|
g_io_module_get_type
|
||||||
g_io_module_new
|
g_io_module_new
|
||||||
|
g_io_module_scope_block
|
||||||
|
g_io_module_scope_free
|
||||||
|
g_io_module_scope_new
|
||||||
g_io_modules_scan_all_in_directory
|
g_io_modules_scan_all_in_directory
|
||||||
|
g_io_modules_scan_all_in_directory_with_scope
|
||||||
g_io_modules_load_all_in_directory
|
g_io_modules_load_all_in_directory
|
||||||
|
g_io_modules_load_all_in_directory_with_scope
|
||||||
g_io_extension_point_register
|
g_io_extension_point_register
|
||||||
g_io_extension_point_lookup
|
g_io_extension_point_lookup
|
||||||
g_io_extension_point_set_required_type
|
g_io_extension_point_set_required_type
|
||||||
|
@ -1498,6 +1498,22 @@ typedef enum {
|
|||||||
G_TLS_DATABASE_LOOKUP_KEYPAIR = 1
|
G_TLS_DATABASE_LOOKUP_KEYPAIR = 1
|
||||||
} GTlsDatabaseLookupFlags;
|
} GTlsDatabaseLookupFlags;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GIOModuleScopeFlags:
|
||||||
|
* @G_IO_MODULES_SCOPE_NONE: No module scan flags
|
||||||
|
* @G_IO_MODULES_SCOPE_BLOCK_DUPLICATES: When using this scope to load or
|
||||||
|
* scan modules, automatically block a modules which has the same base
|
||||||
|
* basename as previously loaded module.
|
||||||
|
*
|
||||||
|
* Flags for use with g_io_module_scope_new().
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
G_IO_MODULE_SCOPE_NONE,
|
||||||
|
G_IO_MODULE_SCOPE_BLOCK_DUPLICATES
|
||||||
|
} GIOModuleScopeFlags;
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GIO_ENUMS_H__ */
|
#endif /* __GIO_ENUMS_H__ */
|
||||||
|
202
gio/giomodule.c
202
gio/giomodule.c
@ -108,7 +108,103 @@
|
|||||||
* see <link linkend="gio-querymodules">gio-querymodules</link>.
|
* see <link linkend="gio-querymodules">gio-querymodules</link>.
|
||||||
* You are expected to run this command after installing a
|
* You are expected to run this command after installing a
|
||||||
* GIO module.
|
* GIO module.
|
||||||
|
*
|
||||||
|
* The <envar>GIO_EXTRA_MODULES</envar> environment variable can be
|
||||||
|
* used to specify additional directories to automatically load modules
|
||||||
|
* from. This environment variable has the same syntax as the
|
||||||
|
* <envar>PATH</envar>. If two modules have the same base name in different
|
||||||
|
* directories, then the latter one will be ignored. If additional
|
||||||
|
* directories are specified GIO will load modules from the built-in
|
||||||
|
* directory last.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* GIOModuleScope:
|
||||||
|
*
|
||||||
|
* Represents a scope for loading IO modules. A scope can be used for blocking
|
||||||
|
* duplicate modules, or blocking a module you don't want to load.
|
||||||
|
*
|
||||||
|
* The scope can be used with g_io_modules_load_all_in_directory_with_scope()
|
||||||
|
* or g_io_modules_scan_all_in_directory_with_scope().
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
struct _GIOModuleScope {
|
||||||
|
GIOModuleScopeFlags flags;
|
||||||
|
GHashTable *basenames;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_io_module_scope_new:
|
||||||
|
* @flags: flags for the new scope
|
||||||
|
*
|
||||||
|
* Create a new scope for loading of IO modules. A scope can be used for
|
||||||
|
* blocking duplicate modules, or blocking a module you don't want to load.
|
||||||
|
*
|
||||||
|
* Specify the %G_IO_MODULES_SCOPE_BLOCK_DUPLICATES flag to block modules
|
||||||
|
* which have the same base name as a module that has already been seen
|
||||||
|
* in this scope.
|
||||||
|
*
|
||||||
|
* Returns: (transfer full): the new module scope
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
GIOModuleScope *
|
||||||
|
g_io_module_scope_new (GIOModuleScopeFlags flags)
|
||||||
|
{
|
||||||
|
GIOModuleScope *scope = g_new0 (GIOModuleScope, 1);
|
||||||
|
scope->flags = flags;
|
||||||
|
scope->basenames = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
|
||||||
|
return scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_io_module_scope_free:
|
||||||
|
* @scope: a module loading scope
|
||||||
|
*
|
||||||
|
* Free a module scope.
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_io_module_scope_free (GIOModuleScope *scope)
|
||||||
|
{
|
||||||
|
if (!scope)
|
||||||
|
return;
|
||||||
|
g_hash_table_destroy (scope->basenames);
|
||||||
|
g_free (scope);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_io_module_scope_block:
|
||||||
|
* @scope: a module loading scope
|
||||||
|
*
|
||||||
|
* Block modules with the given base name from being loaded when this scope
|
||||||
|
* is used with g_io_modules_scan_all_in_directory_with_scope() or
|
||||||
|
* g_io_modules_load_all_in_directory_with_scope().
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_io_module_scope_block (GIOModuleScope *scope,
|
||||||
|
const gchar *basename)
|
||||||
|
{
|
||||||
|
gchar *key;
|
||||||
|
|
||||||
|
g_return_if_fail (scope != NULL);
|
||||||
|
g_return_if_fail (basename != NULL);
|
||||||
|
|
||||||
|
key = g_strdup (basename);
|
||||||
|
g_hash_table_insert (scope->basenames, key, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_g_io_module_scope_contains (GIOModuleScope *scope,
|
||||||
|
const gchar *basename)
|
||||||
|
{
|
||||||
|
return g_hash_table_lookup (scope->basenames, basename) ? TRUE : FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
struct _GIOModule {
|
struct _GIOModule {
|
||||||
GTypeModule parent_instance;
|
GTypeModule parent_instance;
|
||||||
|
|
||||||
@ -253,20 +349,36 @@ g_io_module_new (const gchar *filename)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
is_valid_module_name (const gchar *basename)
|
is_valid_module_name (const gchar *basename,
|
||||||
|
GIOModuleScope *scope)
|
||||||
{
|
{
|
||||||
|
gboolean result;
|
||||||
|
|
||||||
#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
|
#if !defined(G_OS_WIN32) && !defined(G_WITH_CYGWIN)
|
||||||
return
|
if (!g_str_has_prefix (basename, "lib") ||
|
||||||
g_str_has_prefix (basename, "lib") &&
|
!g_str_has_suffix (basename, ".so"))
|
||||||
g_str_has_suffix (basename, ".so");
|
return FALSE;
|
||||||
#else
|
#else
|
||||||
return g_str_has_suffix (basename, ".dll");
|
if (!g_str_has_suffix (basename, ".dll"))
|
||||||
|
return FALSE;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
result = TRUE;
|
||||||
|
if (scope)
|
||||||
|
{
|
||||||
|
result = _g_io_module_scope_contains (scope, basename) ? FALSE : TRUE;
|
||||||
|
if (result && (scope->flags & G_IO_MODULE_SCOPE_BLOCK_DUPLICATES))
|
||||||
|
g_io_module_scope_block (scope, basename);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_io_modules_scan_all_in_directory:
|
* g_io_modules_scan_all_in_directory_with_scope:
|
||||||
* @dirname: pathname for a directory containing modules to scan.
|
* @dirname: pathname for a directory containing modules to scan.
|
||||||
|
* @scope: a scope to use when scanning the modules
|
||||||
*
|
*
|
||||||
* Scans all the modules in the specified directory, ensuring that
|
* Scans all the modules in the specified directory, ensuring that
|
||||||
* any extension point implemented by a module is registered.
|
* any extension point implemented by a module is registered.
|
||||||
@ -280,10 +392,11 @@ is_valid_module_name (const gchar *basename)
|
|||||||
* If you need to guarantee that all types are loaded in all the modules,
|
* If you need to guarantee that all types are loaded in all the modules,
|
||||||
* use g_io_modules_load_all_in_directory().
|
* use g_io_modules_load_all_in_directory().
|
||||||
*
|
*
|
||||||
* Since: 2.24
|
* Since: 2.30
|
||||||
**/
|
**/
|
||||||
void
|
void
|
||||||
g_io_modules_scan_all_in_directory (const char *dirname)
|
g_io_modules_scan_all_in_directory_with_scope (const char *dirname,
|
||||||
|
GIOModuleScope *scope)
|
||||||
{
|
{
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
char *filename;
|
char *filename;
|
||||||
@ -353,7 +466,7 @@ g_io_modules_scan_all_in_directory (const char *dirname)
|
|||||||
|
|
||||||
while ((name = g_dir_read_name (dir)))
|
while ((name = g_dir_read_name (dir)))
|
||||||
{
|
{
|
||||||
if (is_valid_module_name (name))
|
if (is_valid_module_name (name, scope))
|
||||||
{
|
{
|
||||||
GIOExtensionPoint *extension_point;
|
GIOExtensionPoint *extension_point;
|
||||||
GIOModule *module;
|
GIOModule *module;
|
||||||
@ -404,10 +517,34 @@ g_io_modules_scan_all_in_directory (const char *dirname)
|
|||||||
g_free (filename);
|
g_free (filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_io_modules_scan_all_in_directory:
|
||||||
|
* @dirname: pathname for a directory containing modules to scan.
|
||||||
|
*
|
||||||
|
* Scans all the modules in the specified directory, ensuring that
|
||||||
|
* any extension point implemented by a module is registered.
|
||||||
|
*
|
||||||
|
* This may not actually load and initialize all the types in each
|
||||||
|
* module, some modules may be lazily loaded and initialized when
|
||||||
|
* an extension point it implementes is used with e.g.
|
||||||
|
* g_io_extension_point_get_extensions() or
|
||||||
|
* g_io_extension_point_get_extension_by_name().
|
||||||
|
*
|
||||||
|
* If you need to guarantee that all types are loaded in all the modules,
|
||||||
|
* use g_io_modules_load_all_in_directory().
|
||||||
|
*
|
||||||
|
* Since: 2.24
|
||||||
|
**/
|
||||||
|
void
|
||||||
|
g_io_modules_scan_all_in_directory (const char *dirname)
|
||||||
|
{
|
||||||
|
g_io_modules_scan_all_in_directory_with_scope (dirname, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_io_modules_load_all_in_directory:
|
* g_io_modules_load_all_in_directory_with_scope:
|
||||||
* @dirname: pathname for a directory containing modules to load.
|
* @dirname: pathname for a directory containing modules to load.
|
||||||
|
* @scope: a scope to use when scanning the modules.
|
||||||
*
|
*
|
||||||
* Loads all the modules in the specified directory.
|
* Loads all the modules in the specified directory.
|
||||||
*
|
*
|
||||||
@ -421,9 +558,12 @@ g_io_modules_scan_all_in_directory (const char *dirname)
|
|||||||
* unload them (enabling on-demand loading) you must call
|
* unload them (enabling on-demand loading) you must call
|
||||||
* g_type_module_unuse() on all the modules. Free the list
|
* g_type_module_unuse() on all the modules. Free the list
|
||||||
* with g_list_free().
|
* with g_list_free().
|
||||||
|
*
|
||||||
|
* Since: 2.30
|
||||||
**/
|
**/
|
||||||
GList *
|
GList *
|
||||||
g_io_modules_load_all_in_directory (const char *dirname)
|
g_io_modules_load_all_in_directory_with_scope (const char *dirname,
|
||||||
|
GIOModuleScope *scope)
|
||||||
{
|
{
|
||||||
const gchar *name;
|
const gchar *name;
|
||||||
GDir *dir;
|
GDir *dir;
|
||||||
@ -439,7 +579,7 @@ g_io_modules_load_all_in_directory (const char *dirname)
|
|||||||
modules = NULL;
|
modules = NULL;
|
||||||
while ((name = g_dir_read_name (dir)))
|
while ((name = g_dir_read_name (dir)))
|
||||||
{
|
{
|
||||||
if (is_valid_module_name (name))
|
if (is_valid_module_name (name, scope))
|
||||||
{
|
{
|
||||||
GIOModule *module;
|
GIOModule *module;
|
||||||
gchar *path;
|
gchar *path;
|
||||||
@ -466,6 +606,29 @@ g_io_modules_load_all_in_directory (const char *dirname)
|
|||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_io_modules_load_all_in_directory:
|
||||||
|
* @dirname: pathname for a directory containing modules to load.
|
||||||
|
*
|
||||||
|
* Loads all the modules in the specified directory.
|
||||||
|
*
|
||||||
|
* If don't require all modules to be initialized (and thus registering
|
||||||
|
* all gtypes) then you can use g_io_modules_scan_all_in_directory()
|
||||||
|
* which allows delayed/lazy loading of modules.
|
||||||
|
*
|
||||||
|
* Returns: (element-type GIOModule) (transfer full): a list of #GIOModules loaded
|
||||||
|
* from the directory,
|
||||||
|
* All the modules are loaded into memory, if you want to
|
||||||
|
* unload them (enabling on-demand loading) you must call
|
||||||
|
* g_type_module_unuse() on all the modules. Free the list
|
||||||
|
* with g_list_free().
|
||||||
|
**/
|
||||||
|
GList *
|
||||||
|
g_io_modules_load_all_in_directory (const char *dirname)
|
||||||
|
{
|
||||||
|
return g_io_modules_load_all_in_directory_with_scope (dirname, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
G_LOCK_DEFINE_STATIC (registered_extensions);
|
G_LOCK_DEFINE_STATIC (registered_extensions);
|
||||||
G_LOCK_DEFINE_STATIC (loaded_dirs);
|
G_LOCK_DEFINE_STATIC (loaded_dirs);
|
||||||
|
|
||||||
@ -571,6 +734,7 @@ _g_io_modules_ensure_loaded (void)
|
|||||||
{
|
{
|
||||||
static gboolean loaded_dirs = FALSE;
|
static gboolean loaded_dirs = FALSE;
|
||||||
const char *module_path;
|
const char *module_path;
|
||||||
|
GIOModuleScope *scope;
|
||||||
|
|
||||||
_g_io_modules_ensure_extension_points_registered ();
|
_g_io_modules_ensure_extension_points_registered ();
|
||||||
|
|
||||||
@ -579,11 +743,10 @@ _g_io_modules_ensure_loaded (void)
|
|||||||
if (!loaded_dirs)
|
if (!loaded_dirs)
|
||||||
{
|
{
|
||||||
loaded_dirs = TRUE;
|
loaded_dirs = TRUE;
|
||||||
|
scope = g_io_module_scope_new (G_IO_MODULE_SCOPE_BLOCK_DUPLICATES);
|
||||||
|
|
||||||
g_io_modules_scan_all_in_directory (GIO_MODULE_DIR);
|
/* First load any overrides, extras */
|
||||||
|
|
||||||
module_path = g_getenv ("GIO_EXTRA_MODULES");
|
module_path = g_getenv ("GIO_EXTRA_MODULES");
|
||||||
|
|
||||||
if (module_path)
|
if (module_path)
|
||||||
{
|
{
|
||||||
gchar **paths;
|
gchar **paths;
|
||||||
@ -592,11 +755,18 @@ _g_io_modules_ensure_loaded (void)
|
|||||||
paths = g_strsplit (module_path, ":", 0);
|
paths = g_strsplit (module_path, ":", 0);
|
||||||
|
|
||||||
for (i = 0; paths[i] != NULL; i++)
|
for (i = 0; paths[i] != NULL; i++)
|
||||||
g_io_modules_scan_all_in_directory (paths[i]);
|
{
|
||||||
|
g_io_modules_scan_all_in_directory_with_scope (paths[i], scope);
|
||||||
|
}
|
||||||
|
|
||||||
g_strfreev (paths);
|
g_strfreev (paths);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Then load the compiled in path */
|
||||||
|
g_io_modules_scan_all_in_directory_with_scope (GIO_MODULE_DIR, scope);
|
||||||
|
|
||||||
|
g_io_module_scope_free (scope);
|
||||||
|
|
||||||
/* Initialize types from built-in "modules" */
|
/* Initialize types from built-in "modules" */
|
||||||
g_null_settings_backend_get_type ();
|
g_null_settings_backend_get_type ();
|
||||||
g_memory_settings_backend_get_type ();
|
g_memory_settings_backend_get_type ();
|
||||||
|
@ -32,6 +32,13 @@
|
|||||||
|
|
||||||
G_BEGIN_DECLS
|
G_BEGIN_DECLS
|
||||||
|
|
||||||
|
typedef struct _GIOModuleScope GIOModuleScope;
|
||||||
|
|
||||||
|
GIOModuleScope * g_io_module_scope_new (GIOModuleScopeFlags flags);
|
||||||
|
void g_io_module_scope_free (GIOModuleScope *scope);
|
||||||
|
void g_io_module_scope_block (GIOModuleScope *scope,
|
||||||
|
const gchar *basename);
|
||||||
|
|
||||||
#define G_IO_TYPE_MODULE (g_io_module_get_type ())
|
#define G_IO_TYPE_MODULE (g_io_module_get_type ())
|
||||||
#define G_IO_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_IO_TYPE_MODULE, GIOModule))
|
#define G_IO_MODULE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), G_IO_TYPE_MODULE, GIOModule))
|
||||||
#define G_IO_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_IO_TYPE_MODULE, GIOModuleClass))
|
#define G_IO_MODULE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), G_IO_TYPE_MODULE, GIOModuleClass))
|
||||||
@ -52,6 +59,11 @@ GIOModule *g_io_module_new (const gchar
|
|||||||
void g_io_modules_scan_all_in_directory (const char *dirname);
|
void g_io_modules_scan_all_in_directory (const char *dirname);
|
||||||
GList *g_io_modules_load_all_in_directory (const gchar *dirname);
|
GList *g_io_modules_load_all_in_directory (const gchar *dirname);
|
||||||
|
|
||||||
|
void g_io_modules_scan_all_in_directory_with_scope (const gchar *dirname,
|
||||||
|
GIOModuleScope *scope);
|
||||||
|
GList *g_io_modules_load_all_in_directory_with_scope (const gchar *dirname,
|
||||||
|
GIOModuleScope *scope);
|
||||||
|
|
||||||
GIOExtensionPoint *g_io_extension_point_register (const char *name);
|
GIOExtensionPoint *g_io_extension_point_register (const char *name);
|
||||||
GIOExtensionPoint *g_io_extension_point_lookup (const char *name);
|
GIOExtensionPoint *g_io_extension_point_lookup (const char *name);
|
||||||
void g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
|
void g_io_extension_point_set_required_type (GIOExtensionPoint *extension_point,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user