diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-03-11 18:04:06 +0000 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2014-03-17 16:31:17 +0000 |
commit | 6df5fbcc4756d51ee2f702e7953690400f9c3b58 (patch) | |
tree | a23ab65f40744789662d2c8eb23227848cfd5292 | |
parent | 8a5d1bfaae12e202dccd00590302f563aa22b9ef (diff) |
Do domain-specific errors via GDBus, not dbus-glib
We can get rid of TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR, because
G_IO_ERROR_DBUS_ERROR doesn't have the same weird abuse of GError
semantics that DBUS_GERROR_REMOTE_EXCEPTION did.
I moved TP_DBUS_ERROR_INCONSISTENT from last to 0'th TP_DBUS_ERROR,
to avoid having to renumber all of them.
We can probably get rid of a lot of these errors in favour of
G_IO_ERROR or G_DBUS_ERROR members, but for now, let's keep them.
-rw-r--r-- | docs/reference/telepathy-glib/telepathy-glib-sections.txt | 1 | ||||
-rw-r--r-- | telepathy-glib/channel-group.c | 16 | ||||
-rw-r--r-- | telepathy-glib/connection.c | 6 | ||||
-rw-r--r-- | telepathy-glib/errors.c | 30 | ||||
-rw-r--r-- | telepathy-glib/proxy-internal.h | 3 | ||||
-rw-r--r-- | telepathy-glib/proxy.c | 170 | ||||
-rw-r--r-- | telepathy-glib/proxy.h | 5 | ||||
-rw-r--r-- | tests/dbus/connection-error.c | 51 | ||||
-rw-r--r-- | tests/suppressions/tpl.supp | 8 | ||||
-rw-r--r-- | tools/telepathy-glib.supp | 8 |
10 files changed, 67 insertions, 231 deletions
diff --git a/docs/reference/telepathy-glib/telepathy-glib-sections.txt b/docs/reference/telepathy-glib/telepathy-glib-sections.txt index cd52b7b4c..4e483ba71 100644 --- a/docs/reference/telepathy-glib/telepathy-glib-sections.txt +++ b/docs/reference/telepathy-glib/telepathy-glib-sections.txt @@ -3007,7 +3007,6 @@ tp_proxy_get_interface_by_id tp_proxy_check_interface_by_id tp_proxy_invalidate TpProxyInterfaceAddedCb -tp_proxy_subclass_add_error_mapping <SUBSECTION> TpProxyInvokeFunc tp_proxy_pending_call_v0_new diff --git a/telepathy-glib/channel-group.c b/telepathy-glib/channel-group.c index ddb9ee89d..462976324 100644 --- a/telepathy-glib/channel-group.c +++ b/telepathy-glib/channel-group.c @@ -590,17 +590,21 @@ members_changed_prepared_cb (GObject *object, if (error_detail != NULL) { + DEBUG ("detailed error: %s", error_detail); + /* CM specified a D-Bus error name */ tp_proxy_dbus_error_to_gerror (self, error_detail, - debug_message == NULL || debug_message[0] == '\0' - ? error_detail - : debug_message, - &self->priv->group_remove_error); + debug_message, &self->priv->group_remove_error); + + DEBUG ("-> %s #%d: %s", + g_quark_to_string (self->priv->group_remove_error->domain), + self->priv->group_remove_error->code, + self->priv->group_remove_error->message); /* ... but if we don't know anything about that D-Bus error * name, we can still do better by using RemovedFromGroup */ if (g_error_matches (self->priv->group_remove_error, - TP_DBUS_ERRORS, TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR)) + G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) { self->priv->group_remove_error->domain = TP_ERRORS_REMOVED_FROM_GROUP; @@ -611,6 +615,8 @@ members_changed_prepared_cb (GObject *object, } else { + DEBUG ("no detailed error"); + /* Use our separate error domain */ g_set_error_literal (&self->priv->group_remove_error, TP_ERRORS_REMOVED_FROM_GROUP, reason, debug_message); diff --git a/telepathy-glib/connection.c b/telepathy-glib/connection.c index 8666f1d7d..b81ca7dfc 100644 --- a/telepathy-glib/connection.c +++ b/telepathy-glib/connection.c @@ -1005,8 +1005,7 @@ tp_connection_status_changed_cb (TpConnection *self, /* ... but if we don't know anything about that D-Bus error * name, we can still be more helpful by deriving an error code from * TpConnectionStatusReason */ - if (g_error_matches (error, TP_DBUS_ERRORS, - TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR)) + if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) { GError *from_csr = NULL; @@ -2551,10 +2550,9 @@ tp_connection_get_detailed_error (TpConnection *self, break; case TP_DBUS_ERROR_OBJECT_REMOVED: - case TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR: case TP_DBUS_ERROR_INCONSISTENT: /* ... and all other cases up to and including - * TP_DBUS_ERROR_INCONSISTENT don't make sense in this context, so + * TP_DBUS_ERROR_CANCELLED don't make sense in this context, so * just use the generic one for them too */ default: return TP_ERROR_STR_DISCONNECTED; diff --git a/telepathy-glib/errors.c b/telepathy-glib/errors.c index 978e61d87..ae3039660 100644 --- a/telepathy-glib/errors.c +++ b/telepathy-glib/errors.c @@ -44,8 +44,8 @@ * enumeration. * * This macro expands to a call to a function returning the Telepathy error - * domain. Since 0.7.17, this function automatically registers the domain with - * dbus-glib for server-side use (using dbus_g_error_domain_register()) when + * domain. Since 0.UNRELEASED, this function automatically registers the + * domain with GIO (using g_dbus_error_register_error()) when * called. * * This used to be called %TP_ERRORS. @@ -318,11 +318,31 @@ tp_error_quark (void) if (g_once_init_enter (&quark)) { - GQuark domain = g_quark_from_static_string ("tp-error-quark"); + gsize domain = 0; + GEnumClass *cls; + guint i; + GDBusErrorEntry *entries; + + cls = g_type_class_ref (TP_TYPE_ERROR); + entries = g_new0 (GDBusErrorEntry, cls->n_values); + + for (i = 0; i < cls->n_values; i++) + { + entries[i].error_code = cls->values[i].value; + entries[i].dbus_error_name = g_strdup_printf ("%s.%s", + TP_ERROR_PREFIX, cls->values[i].value_nick); + } + + g_dbus_error_register_error_domain ("tp-error-quark", &domain, + entries, cls->n_values); + + for (i = 0; i < cls->n_values; i++) + g_free ((gchar *) entries[i].dbus_error_name); + + g_free (entries); - dbus_g_error_domain_register (domain, TP_ERROR_PREFIX, - TP_TYPE_ERROR); g_once_init_leave (&quark, domain); + g_type_class_unref (cls); } return (GQuark) quark; diff --git a/telepathy-glib/proxy-internal.h b/telepathy-glib/proxy-internal.h index cae4d8ed9..ba65ddef1 100644 --- a/telepathy-glib/proxy-internal.h +++ b/telepathy-glib/proxy-internal.h @@ -114,9 +114,6 @@ void _tp_proxy_signal_connection_take_results (TpProxySignalConnection *sc, */ void tp_private_proxy_set_implementation (TpProxyImplementation *impl); -GError *_tp_proxy_take_and_remap_error (TpProxy *self, GError *error) - G_GNUC_WARN_UNUSED_RESULT; - typedef void (*TpProxyProc) (TpProxy *); gboolean _tp_proxy_is_preparing (gpointer self, diff --git a/telepathy-glib/proxy.c b/telepathy-glib/proxy.c index f696d13e6..b4aa420f4 100644 --- a/telepathy-glib/proxy.c +++ b/telepathy-glib/proxy.c @@ -67,8 +67,9 @@ tp_dbus_errors_quark (void) /** * TpDBusError: - * @TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR: Raised if the error raised by - * a remote D-Bus object is not recognised + * @TP_DBUS_ERROR_INCONSISTENT: Raised if information received from a remote + * object is inconsistent or otherwise obviously wrong. + * See also %TP_ERROR_CONFUSED. * @TP_DBUS_ERROR_PROXY_UNREFERENCED: Emitted in #TpProxy::invalidated * when the #TpProxy has lost its last reference * @TP_DBUS_ERROR_NO_INTERFACE: Raised by #TpProxy methods if the remote @@ -91,9 +92,6 @@ tp_dbus_errors_quark (void) * is available. * @TP_DBUS_ERROR_CANCELLED: Raised from calls that re-enter the main * loop (*_run_*) if they are cancelled - * @TP_DBUS_ERROR_INCONSISTENT: Raised if information received from a remote - * object is inconsistent or otherwise obviously wrong (added in 0.7.17). - * See also %TP_ERROR_CONFUSED. * * #GError codes for use with the %TP_DBUS_ERRORS domain. * @@ -229,15 +227,6 @@ tp_dbus_errors_quark (void) * Since: 0.11.3 */ -typedef struct _TpProxyErrorMappingLink TpProxyErrorMappingLink; - -struct _TpProxyErrorMappingLink { - const gchar *prefix; - GQuark domain; - GEnumClass *code_enum_class; - TpProxyErrorMappingLink *next; -}; - struct _TpProxyFeaturePrivate { gpointer unused; @@ -716,19 +705,6 @@ tp_proxy_add_interfaces (TpProxy *self, } } -static GQuark -error_mapping_quark (void) -{ - static GQuark q = 0; - - if (G_UNLIKELY (q == 0)) - { - q = g_quark_from_static_string ("TpProxyErrorMappingCb_0.7.1"); - } - - return q; -} - /** * tp_proxy_dbus_error_to_gerror: * @self: a #TpProxy or subclass @@ -750,77 +726,27 @@ tp_proxy_dbus_error_to_gerror (gpointer self, const char *debug_message, GError **error) { - GType proxy_type = TP_TYPE_PROXY; - GType type; - g_return_if_fail (TP_IS_PROXY (self)); + g_return_if_fail (dbus_error != NULL); - if (error == NULL) - return; - - g_return_if_fail (*error == NULL); - - if (!tp_dbus_check_valid_interface_name (dbus_error, error)) + if (tp_str_empty (debug_message)) { - return; + /* best we can do */ + debug_message = dbus_error; } - if (debug_message == NULL) - debug_message = ""; - - for (type = G_TYPE_FROM_INSTANCE (self); - type != proxy_type; - type = g_type_parent (type)) + if (error != NULL) { - TpProxyErrorMappingLink *iter; + /* make sure the error domain is registered */ + TP_ERROR; - for (iter = g_type_get_qdata (type, error_mapping_quark ()); - iter != NULL; - iter = iter->next) - { - size_t prefix_len = strlen (iter->prefix); + *error = g_dbus_error_new_for_dbus_error (dbus_error, debug_message); - if (!strncmp (dbus_error, iter->prefix, prefix_len) - && dbus_error[prefix_len] == '.') - { - GEnumValue *code = - g_enum_get_value_by_nick (iter->code_enum_class, - dbus_error + prefix_len + 1); - - if (code != NULL) - { - g_set_error (error, iter->domain, code->value, - "%s", debug_message); - return; - } - } - } - } - - /* we don't have an error mapping - so let's just paste the - * error name and message into TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR */ - g_set_error (error, TP_DBUS_ERRORS, - TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR, "%s: %s", dbus_error, debug_message); -} - -GError * -_tp_proxy_take_and_remap_error (TpProxy *self, - GError *error) -{ - if (error == NULL || - error->domain != DBUS_GERROR || - error->code != DBUS_GERROR_REMOTE_EXCEPTION) - { - return error; - } - else - { - GError *replacement = NULL; - const gchar *dbus = dbus_g_error_get_name (error); - - tp_proxy_dbus_error_to_gerror (self, dbus, error->message, &replacement); - g_error_free (error); - return replacement; + /* Our old behaviour was that we only put the detailed D-Bus error + * in the message if we raised TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR. + * Be consistent with that. */ + if (!g_error_matches (*error, G_IO_ERROR, G_IO_ERROR_DBUS_ERROR)) + g_dbus_error_strip_remote_error (*error); } } @@ -1150,67 +1076,6 @@ tp_proxy_finalize (GObject *object) G_OBJECT_CLASS (tp_proxy_parent_class)->finalize (object); } -/** - * tp_proxy_subclass_add_error_mapping: - * @proxy_subclass: The #GType of a subclass of #TpProxy (which must not be - * #TpProxy itself) - * @static_prefix: A prefix for D-Bus error names, not including the trailing - * dot (which must remain valid forever, and should usually be in static - * storage) - * @domain: A quark representing the corresponding #GError domain - * @code_enum_type: The type of a subclass of #GEnumClass - * - * Register a mapping from D-Bus errors received from the given proxy - * subclass to #GError instances. - * - * When a D-Bus error is received, the #TpProxy code checks for error - * mappings registered for the class of the proxy receiving the error, - * then for all of its parent classes. - * - * If there is an error mapping for which the D-Bus error name - * starts with the mapping's @static_prefix, the proxy will check the - * corresponding @code_enum_type for a value whose @value_nick is - * the rest of the D-Bus error name (with the leading dot removed). If there - * isn't such a value, it will continue to try other error mappings. - * - * If a suitable error mapping and code are found, the #GError that is raised - * will have its error domain set to the @domain from the error mapping, - * and its error code taken from the enum represented by the @code_enum_type. - * - * If no suitable error mapping or code is found, the #GError will have - * error domain %TP_DBUS_ERRORS and error code - * %TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR. - * - * Since: 0.7.1 - */ -void -tp_proxy_subclass_add_error_mapping (GType proxy_subclass, - const gchar *static_prefix, - GQuark domain, - GType code_enum_type) -{ - GQuark q = error_mapping_quark (); - TpProxyErrorMappingLink *old_link = g_type_get_qdata (proxy_subclass, q); - TpProxyErrorMappingLink *new_link; - GType tp_type_proxy = TP_TYPE_PROXY; - - g_return_if_fail (proxy_subclass != tp_type_proxy); - g_return_if_fail (g_type_is_a (proxy_subclass, tp_type_proxy)); - g_return_if_fail (static_prefix != NULL); - g_return_if_fail (domain != 0); - g_return_if_fail (code_enum_type != G_TYPE_INVALID); - - new_link = g_slice_new0 (TpProxyErrorMappingLink); - new_link->prefix = static_prefix; - new_link->domain = domain; - /* We never unref the enum type - intentional one-per-process leak. - * See "tp_proxy_subclass_add_error_mapping refs the enum" in our valgrind - * suppressions file */ - new_link->code_enum_class = g_type_class_ref (code_enum_type); - new_link->next = old_link; /* may be NULL */ - g_type_set_qdata (proxy_subclass, q, new_link); -} - static void tp_proxy_once (void); static void @@ -1219,6 +1084,9 @@ tp_proxy_class_init (TpProxyClass *klass) GParamSpec *param_spec; GObjectClass *object_class = G_OBJECT_CLASS (klass); + /* Ensure that remote errors will be mapped to the TP_ERROR domain */ + TP_ERROR; + tp_proxy_once (); g_type_class_add_private (klass, sizeof (TpProxyPrivate)); diff --git a/telepathy-glib/proxy.h b/telepathy-glib/proxy.h index 3b4c68f16..b0727a6cc 100644 --- a/telepathy-glib/proxy.h +++ b/telepathy-glib/proxy.h @@ -47,7 +47,7 @@ typedef struct _TpProxy TpProxy; GQuark tp_dbus_errors_quark (void); typedef enum { - TP_DBUS_ERROR_UNKNOWN_REMOTE_ERROR = 0, + TP_DBUS_ERROR_INCONSISTENT = 0, TP_DBUS_ERROR_PROXY_UNREFERENCED = 1, TP_DBUS_ERROR_NO_INTERFACE = 2, TP_DBUS_ERROR_NAME_OWNER_LOST = 3, @@ -57,9 +57,8 @@ typedef enum { TP_DBUS_ERROR_INVALID_MEMBER_NAME = 7, TP_DBUS_ERROR_OBJECT_REMOVED = 8, TP_DBUS_ERROR_CANCELLED = 9, - TP_DBUS_ERROR_INCONSISTENT = 10, } TpDBusError; -#define TP_NUM_DBUS_ERRORS (TP_DBUS_ERROR_INCONSISTENT + 1) +#define TP_NUM_DBUS_ERRORS (TP_DBUS_ERROR_CANCELLED + 1) struct _TpProxy { /*<private>*/ diff --git a/tests/dbus/connection-error.c b/tests/dbus/connection-error.c index b9c5cc046..16fd4ce9c 100644 --- a/tests/dbus/connection-error.c +++ b/tests/dbus/connection-error.c @@ -53,30 +53,6 @@ typedef enum DOMAIN_SPECIFIC_ERROR = 0, } ExampleError; -/* example_com_error_get_type relies on this */ -G_STATIC_ASSERT (sizeof (GType) <= sizeof (gsize)); - -static GType -example_com_error_get_type (void) -{ - static gsize type = 0; - - if (g_once_init_enter (&type)) - { - static const GEnumValue values[] = { - { DOMAIN_SPECIFIC_ERROR, "DOMAIN_SPECIFIC_ERROR", - "DomainSpecificError" }, - { 0 } - }; - GType gtype; - - gtype = g_enum_register_static ("ExampleError", values); - g_once_init_leave (&type, gtype); - } - - return (GType) type; -} - static GQuark example_com_error_quark (void) { @@ -88,8 +64,10 @@ example_com_error_quark (void) g_assert (sizeof (GQuark) <= sizeof (gsize)); - dbus_g_error_domain_register (domain, "com.example", - example_com_error_get_type ()); + if (!g_dbus_error_register_error (domain, DOMAIN_SPECIFIC_ERROR, + "com.example.DomainSpecificError")) + g_assert_not_reached (); + g_once_init_leave (&quark, domain); } @@ -104,26 +82,10 @@ typedef struct { } Test; static void -global_setup (void) -{ - static gboolean done = FALSE; - - if (done) - return; - - done = TRUE; - - tp_debug_set_flags ("all"); - - tp_proxy_subclass_add_error_mapping (TP_TYPE_CONNECTION, - "com.example", example_com_error_quark (), example_com_error_get_type ()); -} - -static void setup (Test *test, gconstpointer nil G_GNUC_UNUSED) { - global_setup (); + tp_debug_set_flags ("all"); test->mainloop = g_main_loop_new (NULL, FALSE); @@ -169,6 +131,9 @@ test_registered_error (Test *test, tp_cli_connection_connect_to_status_changed (test->conn, on_status_changed, test->mainloop, NULL, NULL, NULL); + /* evaluate the error quark for its side-effect of registering the domain */ + g_assert_cmpuint (example_com_error_quark (), !=, 0); + tp_base_connection_disconnect_with_dbus_error ( test->service_conn_as_base, "com.example.DomainSpecificError", NULL, TP_CONNECTION_STATUS_REASON_NETWORK_ERROR); diff --git a/tests/suppressions/tpl.supp b/tests/suppressions/tpl.supp index 284da40a6..573d33962 100644 --- a/tests/suppressions/tpl.supp +++ b/tests/suppressions/tpl.supp @@ -258,14 +258,6 @@ } { - tp_proxy_subclass_add_error_mapping refs the enum - Memcheck:Leak - ... - fun:g_type_class_ref - fun:tp_proxy_subclass_add_error_mapping -} - -{ tp_dbus_daemon_constructor filter not freed til we fall off the bus Memcheck:Leak ... diff --git a/tools/telepathy-glib.supp b/tools/telepathy-glib.supp index 81d1c513a..bd6708ec4 100644 --- a/tools/telepathy-glib.supp +++ b/tools/telepathy-glib.supp @@ -309,14 +309,6 @@ } { - tp_proxy_subclass_add_error_mapping refs the enum - Memcheck:Leak - ... - fun:g_type_class_ref - fun:tp_proxy_subclass_add_error_mapping -} - -{ tp_dbus_daemon_constructor filter not freed til we fall off the bus Memcheck:Leak ... |