Making GModule use GError.
- From: Sebastian Wilhelmi <wilhelmi ira uka de>
- To: Gtk Development List <gtk-devel-list gnome org>, timj gtk org
- Subject: Making GModule use GError.
- Date: Tue, 07 Nov 2000 16:31:10 +0100
Hi,
to achieve a greater consistency (at the cost of backward compatibility) I
make the proposal to let GModule use GError functions instead of the rather
bad (IMHO) g_module_error () func. Attached is a patch, that implements it for
now only for gmodule-dl.c (i.e. Linux, Solaris, etc.), but if approved I would
of course change it for the other platforms too and the documentation as well.
For now I only introduced 3 errors:
G_MODULE_ERROR_UNKNOWN_SYMBOL,
G_MODULE_ERROR_INIT_CHECK,
G_MODULE_ERROR_FAILED
because in fact dl_error doesn't give us error codes (extremely stupid in the
first place, I think!), so we can not be any more precise (only in string
format again, which we simply copy from dl_error).
What do you think?
Bye,
Sebastian
For your fast reference here is the (incomplete) header file:
-----------8<------------------8<--------------8<------------------------8<------
#include <glib.h>
G_BEGIN_DECLS
typedef enum
{
G_MODULE_ERROR_UNKNOWN_SYMBOL,
G_MODULE_ERROR_INIT_CHECK,
G_MODULE_ERROR_FAILED
} GModuleError;
#define G_MODULE_ERROR g_module_error_quark()
GQuark g_module_error_quark();
typedef enum
{
G_MODULE_BIND_LAZY = 1 << 0,
G_MODULE_BIND_MASK = 0x01
} GModuleFlags;
typedef struct _GModule GModule;
typedef const gchar* (*GModuleCheckInit) (GModule *module);
typedef void (*GModuleUnload) (GModule *module);
/* return TRUE if dynamic module loading is supported */
gboolean g_module_supported (void) G_GNUC_CONST;
/* open a module `file_name' and return handle, which is NULL on error */
GModule* g_module_open (const gchar *file_name,
GModuleFlags flags,
GError **error);
/* close a previously opened module, returns TRUE on success */
gboolean g_module_close (GModule *module,
GError **error);
/* make a module resident so g_module_close on it will be ignored */
void g_module_make_resident (GModule *module);
/* retrive a symbol pointer from `module', returns TRUE on success */
gboolean g_module_symbol (GModule *module,
const gchar *symbol_name,
gpointer *symbol,
GError **error);
/* retrive the file name from an existing module */
gchar* g_module_name (GModule *module);
gchar* g_module_build_path (const gchar *directory,
const gchar *module_name);
G_END_DECLS
-----------8<------------------8<--------------8<------------------------8<------
--
Sebastian Wilhelmi
mailto:wilhelmi ira uka de
http://goethe.ira.uka.de/~wilhelmi
Index: gmodule-dl.c
===================================================================
RCS file: /cvs/gnome/glib/gmodule/gmodule-dl.c,v
retrieving revision 1.9
diff -u -b -B -r1.9 gmodule-dl.c
--- gmodule-dl.c 2000/07/26 11:02:01 1.9
+++ gmodule-dl.c 2000/11/07 15:18:21
@@ -70,31 +70,33 @@
/* --- functions --- */
-static gchar*
-fetch_dlerror (void)
+static void
+fetch_dlerror (GError **error)
{
gchar *msg = dlerror ();
- /* make sure we always return an error message != NULL */
+ /* make sure we always set an error message != NULL */
- return msg ? msg : "unknown dl-error";
+ g_set_error (error, G_MODULE_ERROR, G_MODULE_ERROR_FAILED,
+ msg ? msg : "unknown dl-error");
}
static gpointer
_g_module_open (const gchar *file_name,
- gboolean bind_lazy)
+ gboolean bind_lazy,
+ GError **error)
{
gpointer handle;
handle = dlopen (file_name, RTLD_GLOBAL | (bind_lazy ? RTLD_LAZY : RTLD_NOW));
if (!handle)
- g_module_set_error (fetch_dlerror ());
+ fetch_dlerror (error);
return handle;
}
static gpointer
-_g_module_self (void)
+_g_module_self (GError **error)
{
gpointer handle;
@@ -104,14 +106,15 @@
handle = dlopen (NULL, RTLD_GLOBAL | RTLD_LAZY);
if (!handle)
- g_module_set_error (fetch_dlerror ());
+ fetch_dlerror (error);
return handle;
}
-static void
+static gboolean
_g_module_close (gpointer handle,
- gboolean is_unref)
+ gboolean is_unref,
+ GError **error)
{
/* are there any systems out there that have dlopen()/dlclose()
* without a reference count implementation?
@@ -121,19 +124,25 @@
if (is_unref)
{
if (dlclose (handle) != 0)
- g_module_set_error (fetch_dlerror ());
+ {
+ fetch_dlerror (error);
+ return FALSE;
+ }
}
+
+ return TRUE;
}
static gpointer
_g_module_symbol (gpointer handle,
- const gchar *symbol_name)
+ const gchar *symbol_name,
+ GError **error)
{
gpointer p;
p = dlsym (handle, symbol_name);
if (!p)
- g_module_set_error (fetch_dlerror ());
+ fetch_dlerror (error);
return p;
}
Index: gmodule.c
===================================================================
RCS file: /cvs/gnome/glib/gmodule/gmodule.c,v
retrieving revision 1.28
diff -u -b -B -r1.28 gmodule.c
--- gmodule.c 2000/07/26 11:02:01 1.28
+++ gmodule.c 2000/11/07 15:18:21
@@ -30,7 +30,6 @@
#include "gmodule.h"
#include "gmoduleconf.h"
-#include <errno.h>
#include <string.h>
@@ -57,15 +56,17 @@
/* --- prototypes --- */
static gpointer _g_module_open (const gchar *file_name,
- gboolean bind_lazy);
-static void _g_module_close (gpointer handle,
- gboolean is_unref);
-static gpointer _g_module_self (void);
+ gboolean bind_lazy,
+ GError **error);
+static gboolean _g_module_close (gpointer handle,
+ gboolean is_unref,
+ GError **error);
+static gpointer _g_module_self ( GError **error);
static gpointer _g_module_symbol (gpointer handle,
- const gchar *symbol_name);
+ const gchar *symbol_name,
+ GError **error);
static gchar* _g_module_build_path (const gchar *directory,
const gchar *module_name);
-static inline void g_module_set_error (const gchar *error);
static inline GModule* g_module_find_by_handle (gpointer handle);
static inline GModule* g_module_find_by_name (const gchar *name);
@@ -75,7 +76,6 @@
const char *g_log_domain_gmodule = "GModule";
static GModule *modules = NULL;
static GModule *main_module = NULL;
-static GStaticPrivate module_error_private = G_STATIC_PRIVATE_INIT;
/* --- inline functions --- */
@@ -118,16 +118,8 @@
return retval;
}
-static inline void
-g_module_set_error (const gchar *error)
-{
- g_static_private_set (&module_error_private, g_strdup (error), g_free);
- errno = 0;
-}
-
-
/* --- include platform specifc code --- */
-#define SUPPORT_OR_RETURN(rv) { g_module_set_error (NULL); }
+#define SUPPORT_OR_RETURN(error, rv)
#if (G_MODULE_IMPL == G_MODULE_IMPL_DL)
#include "gmodule-dl.c"
#elif (G_MODULE_IMPL == G_MODULE_IMPL_DLD)
@@ -136,18 +128,24 @@
#include "gmodule-win32.c"
#else
#undef SUPPORT_OR_RETURN
-#define SUPPORT_OR_RETURN(rv) { g_module_set_error ("dynamic modules are " \
- "not supported by this system"); return rv; }
+#define SUPPORT_OR_RETURN(error, rv) \
+{ \
+ g_set_error (error, G_MODULE_ERROR, G_MODULE_ERROR_NOT_SUPPORTED, \
+ "dynamic modules are not supported by this system"); \
+ return rv; \
+}
+
static gpointer
_g_module_open (const gchar *file_name,
gboolean bind_lazy)
{
return NULL;
}
-static void
+static gboolean
_g_module_close (gpointer handle,
gboolean is_unref)
{
+ return FALSE;
}
static gpointer
_g_module_self (void)
@@ -169,29 +167,41 @@
#endif /* no implementation */
/* --- functions --- */
+GQuark
+g_module_error_quark()
+{
+ static GQuark quark;
+ if (!quark)
+ quark = g_quark_from_static_string ("g_module_error");
+ return quark;
+}
+
gboolean
g_module_supported (void)
{
- SUPPORT_OR_RETURN (FALSE);
+ SUPPORT_OR_RETURN (NULL, FALSE);
return TRUE;
}
GModule*
g_module_open (const gchar *file_name,
- GModuleFlags flags)
+ GModuleFlags flags,
+ GError **error)
{
GModule *module;
gpointer handle;
+ GModuleCheckInit check_init;
+ const gchar *check_failed = NULL;
- SUPPORT_OR_RETURN (NULL);
+ SUPPORT_OR_RETURN (error, NULL);
if (!file_name)
{
G_LOCK (GModule);
if (!main_module)
{
- handle = _g_module_self ();
+ handle = _g_module_self (error);
if (handle)
{
main_module = g_new (GModule, 1);
@@ -218,27 +228,23 @@
}
/* open the module */
- handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0);
- if (handle)
- {
- gchar *saved_error;
- GModuleCheckInit check_init;
- const gchar *check_failed = NULL;
+ handle = _g_module_open (file_name, (flags & G_MODULE_BIND_LAZY) != 0,
+ error);
+
+ if (!handle)
+ return NULL;
/* search the module list by handle, since file names are not unique */
module = g_module_find_by_handle (handle);
if (module)
{
- _g_module_close (module->handle, TRUE);
+ _g_module_close (module->handle, TRUE, NULL);
module->ref_count++;
- g_module_set_error (NULL);
+ g_clear_error (error);
return module;
}
- saved_error = g_strdup (g_module_error ());
- g_module_set_error (NULL);
-
module = g_new (GModule, 1);
module->file_name = g_strdup (file_name);
module->handle = handle;
@@ -251,36 +257,33 @@
G_UNLOCK (GModule);
/* check initialization */
- if (g_module_symbol (module, "g_module_check_init", (gpointer) &check_init))
+ if (g_module_symbol (module, "g_module_check_init",
+ (gpointer) &check_init, NULL))
check_failed = check_init (module);
/* we don't call unload() if the initialization check failed. */
if (!check_failed)
- g_module_symbol (module, "g_module_unload", (gpointer) &module->unload);
+ g_module_symbol (module, "g_module_unload",
+ (gpointer) &module->unload, NULL);
if (check_failed)
{
- gchar *error;
-
- error = g_strconcat ("GModule initialization check failed: ", check_failed, NULL);
- g_module_close (module);
- module = NULL;
- g_module_set_error (error);
- g_free (error);
- }
- else
- g_module_set_error (saved_error);
-
- g_free (saved_error);
+ g_set_error (error, G_MODULE_ERROR, G_MODULE_ERROR_INIT_CHECK,
+ "GModule initialization check failed: %s",
+ check_failed);
+ g_module_close (module, NULL);
+ return NULL;
}
return module;
}
gboolean
-g_module_close (GModule *module)
+g_module_close (GModule *module,
+ GError **error)
{
- SUPPORT_OR_RETURN (FALSE);
+ gboolean retval = TRUE;
+ SUPPORT_OR_RETURN (error, FALSE);
g_return_val_if_fail (module != NULL, FALSE);
g_return_val_if_fail (module->ref_count > 0, FALSE);
@@ -321,13 +324,13 @@
module->next = NULL;
G_UNLOCK (GModule);
- _g_module_close (module->handle, FALSE);
+ retval = _g_module_close (module->handle, FALSE, error);
g_free (module->file_name);
g_free (module);
}
- return g_module_error() == NULL;
+ return retval;
}
void
@@ -338,22 +341,17 @@
module->is_resident = TRUE;
}
-gchar*
-g_module_error (void)
-{
- return g_static_private_get (&module_error_private);
-}
-
gboolean
g_module_symbol (GModule *module,
const gchar *symbol_name,
- gpointer *symbol)
+ gpointer *symbol,
+ GError **error)
{
- gchar *module_error;
+ GError *local_error = NULL;
+ SUPPORT_OR_RETURN (error, FALSE);
if (symbol)
*symbol = NULL;
- SUPPORT_OR_RETURN (FALSE);
g_return_val_if_fail (module != NULL, FALSE);
g_return_val_if_fail (symbol_name != NULL, FALSE);
@@ -364,21 +362,18 @@
gchar *name;
name = g_strconcat ("_", symbol_name, NULL);
- *symbol = _g_module_symbol (module->handle, name);
+ *symbol = _g_module_symbol (module->handle, name, &local_error);
g_free (name);
}
#else /* !G_MODULE_NEED_USCORE */
- *symbol = _g_module_symbol (module->handle, symbol_name);
+ *symbol = _g_module_symbol (module->handle, symbol_name, &local_error);
#endif /* !G_MODULE_NEED_USCORE */
- module_error = g_module_error ();
- if (module_error)
+ if (local_error)
{
- gchar *error;
-
- error = g_strconcat ("`", symbol_name, "': ", module_error, NULL);
- g_module_set_error (error);
- g_free (error);
+ g_set_error (error, G_MODULE_ERROR, G_MODULE_ERROR_UNKNOWN_SYMBOL,
+ "`%s': %s", symbol_name, local_error->message);
+ g_error_free (local_error);
*symbol = NULL;
return FALSE;
Index: gmodule.h
===================================================================
RCS file: /cvs/gnome/glib/gmodule/gmodule.h,v
retrieving revision 1.18
diff -u -b -B -r1.18 gmodule.h
--- gmodule.h 2000/09/28 07:32:07 1.18
+++ gmodule.h 2000/11/07 15:18:21
@@ -30,10 +30,18 @@
extern const char *g_log_domain_gmodule;
#include <glib.h>
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+G_BEGIN_DECLS
+typedef enum
+{
+ G_MODULE_ERROR_UNKNOWN_SYMBOL,
+ G_MODULE_ERROR_INIT_CHECK,
+ G_MODULE_ERROR_FAILED
+} GModuleError;
+
+#define G_MODULE_ERROR g_module_error_quark()
+GQuark g_module_error_quark();
+
/* exporting and importing functions, this is special cased
* to feature Windows dll stubs.
*/
@@ -59,21 +67,21 @@
/* open a module `file_name' and return handle, which is NULL on error */
GModule* g_module_open (const gchar *file_name,
- GModuleFlags flags);
+ GModuleFlags flags,
+ GError **error);
/* close a previously opened module, returns TRUE on success */
-gboolean g_module_close (GModule *module);
+gboolean g_module_close (GModule *module,
+ GError **error);
/* make a module resident so g_module_close on it will be ignored */
void g_module_make_resident (GModule *module);
-/* query the last module error as a string */
-gchar* g_module_error (void);
-
/* retrive a symbol pointer from `module', returns TRUE on success */
gboolean g_module_symbol (GModule *module,
const gchar *symbol_name,
- gpointer *symbol);
+ gpointer *symbol,
+ GError **error);
/* retrive the file name from an existing module */
gchar* g_module_name (GModule *module);
@@ -92,10 +100,7 @@
*/
gchar* g_module_build_path (const gchar *directory,
const gchar *module_name);
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
+G_END_DECLS
#endif /* __GMODULE_H__ */
Index: libgplugin_a.c
===================================================================
RCS file: /cvs/gnome/glib/gmodule/libgplugin_a.c,v
retrieving revision 1.10
diff -u -b -B -r1.10 libgplugin_a.c
--- libgplugin_a.c 2000/07/26 11:02:01 1.10
+++ libgplugin_a.c 2000/11/07 15:18:21
@@ -54,6 +54,7 @@
G_MODULE_EXPORT void
gplugin_a_module_func (GModule *module)
{
+ GError *error = NULL;
void (*f) (void) = NULL;
gchar *string;
gchar *basename = g_path_get_basename (g_module_name (module));
@@ -62,9 +63,10 @@
g_print ("GPluginA: retrive symbol `%s' from \"%s\"\n",
string, basename);
g_free (basename);
- if (!g_module_symbol (module, string, (gpointer) &f))
+ g_module_symbol (module, string, (gpointer) &f, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
exit (1);
}
Index: testgmodule.c
===================================================================
RCS file: /cvs/gnome/glib/gmodule/testgmodule.c,v
retrieving revision 1.11
diff -u -b -B -r1.11 testgmodule.c
--- testgmodule.c 2000/07/26 11:02:01 1.11
+++ testgmodule.c 2000/11/07 15:18:22
@@ -50,6 +50,7 @@
gchar *plugin_a, *plugin_b;
SimpleFunc f_a, f_b, f_self;
GModuleFunc gmod_f;
+ GError *error = NULL;
string = g_get_current_dir ();
g_print ("testgmodule (%s):\n", string);
@@ -69,10 +70,10 @@
/* module handles
*/
g_print ("get main module handle\n");
- module_self = g_module_open (NULL, G_MODULE_BIND_LAZY);
- if (!module_self)
+ module_self = g_module_open (NULL, G_MODULE_BIND_LAZY, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("check that not yet bound symbols in shared libraries of main module are retrievable:\n");
@@ -80,24 +81,25 @@
basename = g_path_get_basename (g_module_name (module_self));
g_print ("retrive symbol `%s' from \"%s\":\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_self, string, (gpointer) &f_self))
+ g_module_symbol (module_self, string, (gpointer) &f_self, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("retrived symbol `%s' as %p\n", string, f_self);
g_print ("load plugin from \"%s\"\n", plugin_a);
- module_a = g_module_open (plugin_a, G_MODULE_BIND_LAZY);
- if (!module_a)
+ module_a = g_module_open (plugin_a, G_MODULE_BIND_LAZY, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("load plugin from \"%s\"\n", plugin_b);
- module_b = g_module_open (plugin_b, G_MODULE_BIND_LAZY);
- if (!module_b)
+ module_b = g_module_open (plugin_b, G_MODULE_BIND_LAZY, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
@@ -107,18 +109,20 @@
basename = g_path_get_basename (g_module_name (module_a));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_a, string, (gpointer) &f_a))
+ g_module_symbol (module_a, string, (gpointer) &f_a, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
string = "gplugin_b_func";
basename = g_path_get_basename (g_module_name (module_b));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_b, string, (gpointer) &f_b))
+ g_module_symbol (module_b, string, (gpointer) &f_b, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("call plugin function(%p) A: ", f_a);
@@ -132,25 +136,28 @@
basename = g_path_get_basename (g_module_name (module_self));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_self, string, (gpointer) &f_self))
+ g_module_symbol (module_self, string, (gpointer) &f_self, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
basename = g_path_get_basename (g_module_name (module_a));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_a, string, (gpointer) &f_a))
+ g_module_symbol (module_a, string, (gpointer) &f_a, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
basename = g_path_get_basename (g_module_name (module_b));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_b, string, (gpointer) &f_b))
+ g_module_symbol (module_b, string, (gpointer) &f_b, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("call plugin function(%p) self: ", f_self);
@@ -166,23 +173,29 @@
basename = g_path_get_basename (g_module_name (module_self));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_self, string, (gpointer) &f_self))
+ g_module_symbol (module_self, string, (gpointer) &f_self, &error);
+ if (error)
+ {
f_self = NULL;
+ g_clear_error (&error);
+ }
g_print ("retrived function `%s' from self: %p\n", string, f_self);
basename = g_path_get_basename (g_module_name (module_a));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_a, string, (gpointer) &f_a))
+ g_module_symbol (module_a, string, (gpointer) &f_a, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
basename = g_path_get_basename (g_module_name (module_b));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_b, string, (gpointer) &f_b))
+ g_module_symbol (module_b, string, (gpointer) &f_b, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("call plugin function(%p) A: ", f_a);
@@ -198,9 +211,10 @@
basename = g_path_get_basename (g_module_name (module_a));
g_print ("retrive symbol `%s' from \"%s\"\n", string, basename);
g_free (basename);
- if (!g_module_symbol (module_a, string, (gpointer) &gmod_f))
+ g_module_symbol (module_a, string, (gpointer) &gmod_f, &error);
+ if (error)
{
- g_print ("error: %s\n", g_module_error ());
+ g_print ("error: %s\n", error->message);
return 1;
}
g_print ("call plugin A's module function(%p):\n{\n", gmod_f);
@@ -211,15 +225,20 @@
/* unload plugins
*/
g_print ("unload plugin A:\n");
- if (!g_module_close (module_a))
- g_print ("error: %s\n", g_module_error ());
+ g_module_close (module_a, &error);
+ if (error)
+ {
+ g_print ("error: %s\n", error->message);
+ g_clear_error (&error);
+ }
g_print ("unload plugin B:\n");
- if (!g_module_close (module_b))
- g_print ("error: %s\n", g_module_error ());
+ g_module_close (module_b, &error);
+ if (error)
+ g_print ("error: %s\n", error->message);
#if 0
g_log_set_fatal_mask ("GModule", G_LOG_FATAL_MASK|G_LOG_LEVEL_WARNING);
- g_module_symbol (0, 0, 0);
+ g_module_symbol (0, 0, 0, NULL);
g_warning("jahooo");
g_on_error_query (".libs/testgmodule");
#endif
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]