summaryrefslogtreecommitdiff
path: root/src/gdbusxx/gdbus-cxx-bridge.h
diff options
context:
space:
mode:
authorPatrick Ohly <patrick.ohly@intel.com>2012-07-10 07:05:16 +0000
committerPatrick Ohly <patrick.ohly@intel.com>2012-07-10 09:08:00 +0000
commit9e02f1fc933fc288cc6f929de30cb65d2108fa29 (patch)
tree59892cf436de8a4a6a52a6dc3fd3251519d3ef06 /src/gdbusxx/gdbus-cxx-bridge.h
parent35e81d293c79787cdac02de7513459a1a1cb5f4b (diff)
D-Bus GIO: reimplemented DBusWatch
The previous implementation did not work at all. It relied on "NameLost" signals with the watched D-Bus name as sender, but that is not how the signal works. It is sent by the D-Bus daemon to the old owner of that name if it looses the name. Instead we need to watch the "NameOwnerChanged" signal and detect when the peer we are watching is the one who disconnected from the bus. Also moved the actual code into the .cpp file because there is no need to inline all of it. This problem was found after adding more failure tests to test-dbus.py. The real-world effect was that syncevo-dbus-server did not clean up properly when clients disconnected early and that the command line kept running after syncevo-dbus-server crashed. Did not affect syncevolution.org binaries, which do not use D-Bus GIO.
Diffstat (limited to 'src/gdbusxx/gdbus-cxx-bridge.h')
-rw-r--r--src/gdbusxx/gdbus-cxx-bridge.h48
1 files changed, 33 insertions, 15 deletions
diff --git a/src/gdbusxx/gdbus-cxx-bridge.h b/src/gdbusxx/gdbus-cxx-bridge.h
index 4ed7c802..ad613f7e 100644
--- a/src/gdbusxx/gdbus-cxx-bridge.h
+++ b/src/gdbusxx/gdbus-cxx-bridge.h
@@ -1963,20 +1963,37 @@ class DBusWatch : public Watch
boost::function<void (void)> m_callback;
bool m_called;
guint m_watchID;
+ std::string m_peer;
- static void disconnect(GDBusConnection *connection,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *interface_name,
- const gchar *signal_name,
- GVariant *parameters,
- gpointer user_data)
+ static void nameOwnerChanged(GDBusConnection *connection,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *interface_name,
+ const gchar *signal_name,
+ GVariant *parameters,
+ gpointer user_data)
{
DBusWatch *watch = static_cast<DBusWatch *>(user_data);
if (!watch->m_called) {
- watch->m_called = true;
- if (watch->m_callback) {
- watch->m_callback();
+ gchar *name = NULL, *oldOwner = NULL, *newOwner = NULL;
+ g_variant_get(parameters, "(sss)", &name, &oldOwner, &newOwner);
+ bool matches = name && watch->m_peer == name &&
+ newOwner && !*newOwner;
+ g_free(name);
+ g_free(oldOwner);
+ g_free(newOwner);
+ if (matches) {
+ watch->disconnected();
+ }
+ }
+ }
+
+ void disconnected()
+ {
+ if (!m_called) {
+ m_called = true;
+ if (m_callback) {
+ m_callback();
}
}
}
@@ -2004,16 +2021,17 @@ class DBusWatch : public Watch
if (!peer) {
throw std::runtime_error("DBusWatch::activate(): no peer");
}
+ m_peer = peer;
// Install watch first ...
m_watchID = g_dbus_connection_signal_subscribe(m_conn.get(),
- peer,
+ NULL, // TODO org.freedesktop.DBus?
"org.freedesktop.DBus",
- "NameLost",
- "/org/freesktop/DBus",
+ "NameOwnerChanged",
+ "/org/freedesktop/DBus",
NULL,
G_DBUS_SIGNAL_FLAGS_NONE,
- disconnect,
+ nameOwnerChanged,
this,
NULL);
if (!m_watchID) {
@@ -2044,7 +2062,7 @@ class DBusWatch : public Watch
g_variant_get(result, "(b)", &actual_result);
if (!actual_result) {
- disconnect(m_conn.get(), NULL, NULL, NULL, NULL, NULL, this);
+ disconnected();
}
} else {
std::string error_message(error->message);