guint name_acquired_subscription_id;
guint name_lost_subscription_id;
- gboolean cancelled;
+ volatile gboolean cancelled; /* must hold lock when reading or modifying */
gboolean needs_release;
} Client;
static void
call_acquired_handler (Client *client)
{
+ G_LOCK (lock);
if (client->previous_call != PREVIOUS_CALL_ACQUIRED)
{
client->previous_call = PREVIOUS_CALL_ACQUIRED;
if (!client->cancelled)
{
+ G_UNLOCK (lock);
do_call (client, CALL_TYPE_NAME_ACQUIRED);
+ goto out;
}
}
+ G_UNLOCK (lock);
+ out:
+ ;
}
static void
call_lost_handler (Client *client)
{
+ G_LOCK (lock);
if (client->previous_call != PREVIOUS_CALL_LOST)
{
client->previous_call = PREVIOUS_CALL_LOST;
if (!client->cancelled)
{
+ G_UNLOCK (lock);
do_call (client, CALL_TYPE_NAME_LOST);
+ goto out;
}
}
+ G_UNLOCK (lock);
+ out:
+ ;
}
/* ---------------------------------------------------------------------------------------------------- */
request_name_reply = 0;
result = NULL;
- result = g_dbus_connection_call_finish (client->connection,
+ /* don't use client->connection - it may be NULL already */
+ result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
res,
NULL);
if (result != NULL)
break;
}
+
if (subscribe)
{
+ GDBusConnection *connection = NULL;
+
+ /* if cancelled, there is no point in subscribing to signals - if not, make sure
+ * we use a known good Connection object since it may be set to NULL at any point
+ * after being cancelled
+ */
+ G_LOCK (lock);
+ if (!client->cancelled)
+ connection = g_object_ref (client->connection);
+ G_UNLOCK (lock);
+
/* start listening to NameLost and NameAcquired messages */
- client->name_lost_subscription_id =
- g_dbus_connection_signal_subscribe (client->connection,
- "org.freedesktop.DBus",
- "org.freedesktop.DBus",
- "NameLost",
- "/org/freedesktop/DBus",
- client->name,
- G_DBUS_SIGNAL_FLAGS_NONE,
- on_name_lost_or_acquired,
- client,
- NULL);
- client->name_acquired_subscription_id =
- g_dbus_connection_signal_subscribe (client->connection,
- "org.freedesktop.DBus",
- "org.freedesktop.DBus",
- "NameAcquired",
- "/org/freedesktop/DBus",
- client->name,
- G_DBUS_SIGNAL_FLAGS_NONE,
- on_name_lost_or_acquired,
- client,
- NULL);
+ if (connection != NULL)
+ {
+ client->name_lost_subscription_id =
+ g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameLost",
+ "/org/freedesktop/DBus",
+ client->name,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_name_lost_or_acquired,
+ client,
+ NULL);
+ client->name_acquired_subscription_id =
+ g_dbus_connection_signal_subscribe (connection,
+ "org.freedesktop.DBus",
+ "org.freedesktop.DBus",
+ "NameAcquired",
+ "/org/freedesktop/DBus",
+ client->name,
+ G_DBUS_SIGNAL_FLAGS_NONE,
+ on_name_lost_or_acquired,
+ client,
+ NULL);
+ g_object_unref (connection);
+ }
}
client_unref (client);
{
Client *client = user_data;
+ /* must not do anything if already cancelled */
+ G_LOCK (lock);
+ if (client->cancelled)
+ {
+ G_UNLOCK (lock);
+ goto out;
+ }
+ G_UNLOCK (lock);
+
client->connection = g_bus_get_finish (res, NULL);
if (client->connection == NULL)
{
g_assert (!name_has_owner_reply);
g_variant_unref (result);
+ /* Now try owning the name and then immediately decide to unown the name */
+ g_assert_cmpint (data.num_bus_acquired, ==, 1);
+ g_assert_cmpint (data.num_acquired, ==, 1);
+ g_assert_cmpint (data.num_lost, ==, 0);
+ g_assert_cmpint (data.num_free_func, ==, 2);
+ id = g_bus_own_name (G_BUS_TYPE_SESSION,
+ name,
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ bus_acquired_handler,
+ name_acquired_handler,
+ name_lost_handler,
+ &data,
+ (GDestroyNotify) own_name_data_free_func);
+ g_assert_cmpint (data.num_bus_acquired, ==, 1);
+ g_assert_cmpint (data.num_acquired, ==, 1);
+ g_assert_cmpint (data.num_lost, ==, 0);
+ g_assert_cmpint (data.num_free_func, ==, 2);
+ g_bus_unown_name (id);
+ g_assert_cmpint (data.num_bus_acquired, ==, 1);
+ g_assert_cmpint (data.num_acquired, ==, 1);
+ g_assert_cmpint (data.num_lost, ==, 0);
+ g_assert_cmpint (data.num_free_func, ==, 2);
+ g_main_loop_run (loop); /* the GDestroyNotify is called in idle because the bus is acquired in idle */
+ g_assert_cmpint (data.num_free_func, ==, 3);
+
/*
* Own the name again.
*/
g_bus_unown_name (id);
g_assert_cmpint (data.num_bus_acquired, ==, 1);
g_assert_cmpint (data.num_acquired, ==, 1);
- g_assert_cmpint (data.num_free_func, ==, 3);
+ g_assert_cmpint (data.num_free_func, ==, 4);
/* grab it again */
data.num_bus_acquired = 0;
data.num_acquired = 0;
g_assert_cmpint (data.num_acquired, ==, 2);
g_assert_cmpint (data.num_lost, ==, 2);
g_bus_unown_name (id);
- g_assert_cmpint (data.num_free_func, ==, 4);
+ g_assert_cmpint (data.num_free_func, ==, 5);
_g_object_wait_for_single_ref (c);
g_object_unref (c);