On Sat, Feb 19, 2011 at 12:14:29AM -0500, Matthias Clasen wrote: > GError has a boxed type already: > > http://library.gnome.org/devel/gobject/2.27/gobject-Boxed-Types.html#G-TYPE-ERROR:CAPS Right, I didn’t see that at first because my local copy of the API documentation was outdated. However, it doesn’t really solve my problem: now that I have changed the marshal definition used by the input-request signal to BOOLEAN:BOXED and the GType of the relative parameter to G_TYPE_ERROR in the signal definition, the .gir file looks a little better: <glib:signal name="output-request"> <return-value transfer-ownership="none"> <type name="gboolean"/> </return-value> <parameters> <parameter name="object" transfer-ownership="none"> <type name="gchar"/> </parameter> <parameter name="p0" transfer-ownership="none"> <type name="GObject.Error"/> </parameter> </parameters> </glib:signal> but at the end of the day it doesn’t really matter since the library segfaults as soon as the signal is emitted, because the signal handler expects a GError** and the unboxed value is a GError*. I tried to work around it by making the signal handler accept a GError*: this way the segfault goes away, but I no longer have a memory location to store the error; not to mention the handler signature looks weird. Where do I go from here? I’m starting to think my use–case is really not supported by GLib; at the same time, I believe signal handlers that can fail, such as the ones I’m using, should be allowed to use a GError to report the exact reason of the failure. One workaround I can think of is adding to GLib a new boxed type, G_TYPE_ERROR_LOCATION, which can be used to store a GError**. That should do the trick. On the other hand, it doesn’t look so nice. In fact, the whole GError API feels a bit alien to the rest of GLib, with the requirement of passing around double pointers most of the time and the messed–up namespacing. What about creating a new error type (or a new API for GError — I guess it would be possible to make compatible additions to the current API, but it would take a lot of care to make sure both APIs are compatible) which is more similar to the rest of the GLib APIs? Something like a GException or GFailure. When you need to call a function that can fail, you do something like this: GException *ex; gboolean success; ex = g_exception_new (); success = function_that_can_fail (ex); if (!success) { g_warning ("Call failed: %s", g_exception_get_message (ex)); } g_exception_free (ex); Of course you wouldn’t need to allocate a new GException for every function you call, you could just create a single GException and clear its state between calls: GException *ex; ex = g_exception_new (); function_that_can_fail (ex); g_exception_clear (ex); another_function_that_can_fail (ex); g_exception_free (ex); If you are not interested in the exact error, you could still pass in a good’ol NULL pointer; we just need to make sure all g_exception* functions do nothing when such a pointer is passed. The only missing piece would be to have a way to identify a GException that contains a failure report from a cleared one, something like GException *ex; gboolean success; ex = g_exception_new (); g_assert (!g_exception_contains_error (ex)); success = function_that_always_fails (ex); g_assert (!success); g_assert (g_exception_contains_error (ex)); g_exception_clear (ex); g_assert (!g_exception_contains_error (ex)); g_exception_free (ex); Now there is no need, for a function that reports errors via GException, to allocate its own errors, unless of course the function calls some other function that reports failure only by setting a GException. I believe the number of such functions in the GNOME stack to be pretty low, because not returning FALSE or NULL on error is bad practice anyway. By the way, this new error type could have all its fields private, with dedicated accessor methods like g_exception_get_message, and with coherent namespacing. As you can see, I think the GError API is a really good one: if I were to design a new error reporting API (which I kinda just did ;) I would keep most things the way they are now. I believe this new API would be a little easier to learn and use, both because there is less pointer dereferencing going on and because it looks and feels like all the other APIs in the GNOME stack. The downside would be the need to allocate a GException even if the called function does not fail, which is mitigated by the fact that a single GException can be used for any number of possibly–failing function calls. What do you think? -- Andrea Bolognani <eof kiyuko org> Resistance is futile, you will be garbage collected.
Attachment:
signature.asc
Description: Digital signature