From e0e506197ddd08bab0b17c4b199a6bb609583d2c Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Thu, 16 Oct 2014 17:20:17 +0100 Subject: [PATCH 7/8] Add public API by which a service can tell why it got disconnected This is not necessarily very informative because we don't communicate error details across the stream before disconnecting the peer, so one peer will have error details and the other will have DBUS_ERROR_DISCONNECTED... but it's better than nothing! --- bus/connection.c | 22 ++++++++++++---------- dbus/dbus-connection-internal.h | 3 --- dbus/dbus-connection.c | 28 +++++++++++++++++++++++++--- dbus/dbus-connection.h | 4 ++++ test/corrupt.c | 13 +++++++++++++ 5 files changed, 54 insertions(+), 16 deletions(-) diff --git a/bus/connection.c b/bus/connection.c index cfe8f9e..a7fbf9c 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -200,20 +200,22 @@ bus_connection_disconnected (DBusConnection *connection) dbus_error_init (&error); - if (!_dbus_connection_check_connected (connection, &error)) + if (dbus_connection_check_connected (connection, &error)) { - if (strcmp (error.name, DBUS_ERROR_DISCONNECTED) != 0) - { - bus_context_log (d->connections->context, - DBUS_SYSTEM_LOG_INFO, - "Connection %s disconnected abnormally: %s: %s", - d->name ? d->name : "(inactive)", - error.name, error.message); - } + _dbus_assert_not_reached ("should already be disconnected"); + } - dbus_error_free (&error); + if (strcmp (error.name, DBUS_ERROR_DISCONNECTED) != 0) + { + bus_context_log (d->connections->context, + DBUS_SYSTEM_LOG_INFO, + "Connection %s disconnected abnormally: %s: %s", + d->name ? d->name : "(inactive)", + error.name, error.message); } + dbus_error_free (&error); + _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n", d->name ? d->name : "(inactive)"); diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h index 4933a72..2897404 100644 --- a/dbus/dbus-connection-internal.h +++ b/dbus/dbus-connection-internal.h @@ -134,9 +134,6 @@ const char* _dbus_connection_get_address (DBusConnection *connection); void _dbus_bus_notify_shared_connection_disconnected_unlocked (DBusConnection *connection); -dbus_bool_t _dbus_connection_check_connected (DBusConnection *connection, - DBusError *error); - /** @} */ diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 5a3cf7a..42b1112 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2963,7 +2963,8 @@ _dbus_connection_get_is_connected_unlocked (DBusConnection *connection, * Gets whether the connection is currently open. A connection may * become disconnected when the remote application closes its end, or * exits; a connection may also be disconnected with - * dbus_connection_close(). + * dbus_connection_close() or because the message stream from the + * other end is corrupted. * * There are not separate states for "closed" and "disconnected," the two * terms are synonymous. This function should really be called @@ -2986,12 +2987,33 @@ dbus_connection_get_is_connected (DBusConnection *connection) return res; } +/** + * Gets whether the connection is currently open. A connection may + * become disconnected when the remote application closes its end, or + * exits; a connection may also be disconnected with + * dbus_connection_close() or because the message stream from the + * other end is corrupted. + * + * Unlike dbus_connection_get_is_connected(), this function raises a + * #DBusError to indicate why the connection closed. This will typically + * be #DBUS_ERROR_DISCONNECTED for normal disconnection or if we are + * disconnected by the peer. + * + * There are not separate states for "closed" and "disconnected," the two + * terms are synonymous. + * + * @param connection the connection. + * @returns #TRUE if the connection is still alive. + */ dbus_bool_t -_dbus_connection_check_connected (DBusConnection *connection, - DBusError *error) +dbus_connection_check_connected (DBusConnection *connection, + DBusError *error) { dbus_bool_t res; + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_error_is_set (error, FALSE); + CONNECTION_LOCK (connection); res = _dbus_connection_get_is_connected_unlocked (connection, error); CONNECTION_UNLOCK (connection); diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index fe4d04e..3ca4e03 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -438,6 +438,10 @@ DBUS_EXPORT dbus_bool_t dbus_connection_get_socket (DBusConnection *connection, int *fd); +DBUS_EXPORT +dbus_bool_t dbus_connection_check_connected (DBusConnection *connection, + DBusError *error); + /** @} */ diff --git a/test/corrupt.c b/test/corrupt.c index 1a7d446..8447d0c 100644 --- a/test/corrupt.c +++ b/test/corrupt.c @@ -275,6 +275,7 @@ test_byte_order (Fixture *f, int blob_len; DBusMessage *message; dbus_bool_t mem; + dbus_bool_t connected; test_message (f, addr); @@ -339,6 +340,18 @@ test_byte_order (Fixture *f, dbus_message_unref (message); + connected = dbus_connection_check_connected (f->server_conn, &f->e); + g_assert (!connected); + g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_DISCONNECTED); + g_message ("sender of corrupt message got: %s: %s", f->e.name, f->e.message); + dbus_error_free (&f->e); + + connected = dbus_connection_check_connected (f->client_conn, &f->e); + g_assert (!connected); + g_message ("detecter of corrupt message got: %s: %s", f->e.name, f->e.message); + g_assert_cmpstr (f->e.name, ==, DBUS_ERROR_INVALID_ARGS); + dbus_error_free (&f->e); + /* Free the DBusConnection before the GSocket, as above. */ dbus_connection_close (f->server_conn); dbus_connection_unref (f->server_conn); -- 2.1.1