diff options
author | Ryan Lortie <desrt@desrt.ca> | 2012-07-05 23:34:54 -0400 |
---|---|---|
committer | Ryan Lortie <desrt@desrt.ca> | 2012-07-06 00:19:44 -0400 |
commit | c700f20b765fc7324c14707607603615e93ec37a (patch) | |
tree | 8d9657a0ffb9f044cc9023c4a214696582f1ca9f /gdbus | |
parent | dbf4f8cd7fd1804ec4bfb6780a6cc01d7feaf45b (diff) | |
download | dconf-c700f20b765fc7324c14707607603615e93ec37a.tar.gz |
GDBus filter backend: fix reply-serial handling
The handling of the reply serial number in the filter-based GDBus
backend (disabled by default) was incorrect. This fixes it.
Diffstat (limited to 'gdbus')
-rw-r--r-- | gdbus/dconf-gdbus-filter.c | 67 |
1 files changed, 40 insertions, 27 deletions
diff --git a/gdbus/dconf-gdbus-filter.c b/gdbus/dconf-gdbus-filter.c index d0c0654..09ff43d 100644 --- a/gdbus/dconf-gdbus-filter.c +++ b/gdbus/dconf-gdbus-filter.c @@ -63,7 +63,7 @@ dconf_gdbus_handle_reply (ConnectionState *state, DConfGDBusCall *call; call = g_queue_pop_head (&state->queue); - g_assert_cmpuint (g_dbus_message_get_serial (message), ==, call->serial); + g_assert_cmpuint (g_dbus_message_get_reply_serial (message), ==, call->serial); handle = call->handle; g_slice_free (DConfGDBusCall, call); @@ -223,36 +223,49 @@ dconf_engine_dbus_call_async_func (GBusType bus_type, g_dbus_message_set_body (message, parameters); g_mutex_lock (&dconf_gdbus_lock); + { + volatile guint *serial_ptr; + guint my_serial; + + /* We need to set the serial in call->serial. Sometimes we also + * need to set it in state->waiting_for_serial (in the case that no + * other items are queued yet). + * + * g_dbus_connection_send_message() only has one out_serial parameter + * so we can only set one of them atomically. If needed, we elect + * to set the waiting_for_serial because that is the one that is + * accessed from the filter function without holding the lock. + * + * The serial number in the call structure is only accessed after the + * lock is acquired which allows us to take our time setting it (for + * as long as we're still holding the lock). + * + * In the case that waiting_for_serial should not be set we just use + * a local variable and use that to fill call->serial. + * + * Also: the queue itself isn't accessed until after the lock is + * taken, so we can delay adding the call to the queue until we know + * that the sending of the message was successful. + */ + + if (g_queue_is_empty (&state->queue)) + serial_ptr = &state->waiting_for_serial; + else + serial_ptr = &my_serial; - /* We need to set the serial in two places: state->waiting_for_serial - * and call->serial. - * - * g_dbus_connection_send_message() only has one out_serial parameter - * so we can only set one of them atomically. We elect to set the - * waiting_for_serial because that is the one that is accessed from - * the filter function without holding the lock. - * - * The serial number in the call structure is only accessed after the - * lock is acquired which allows us to take our time setting it (for - * as long as we're still holding the lock). - * - * Also: the queue itself isn't accessed until after the lock is - * taken, so we can delay adding the call to the queue until we know - * that the sending of the message was successful. - */ - success = g_dbus_connection_send_message (connection_state_get_connection (state), message, - G_DBUS_SEND_MESSAGE_FLAGS_NONE, &state->waiting_for_serial, error); - - if (success) - { - call = g_slice_new (DConfGDBusCall); + success = g_dbus_connection_send_message (connection_state_get_connection (state), message, + G_DBUS_SEND_MESSAGE_FLAGS_NONE, serial_ptr, error); - call->handle = handle; - call->serial = state->waiting_for_serial; + if (success) + { + call = g_slice_new (DConfGDBusCall); - g_queue_push_tail (&state->queue, call); - } + call->handle = handle; + call->serial = *serial_ptr; + g_queue_push_tail (&state->queue, call); + } + } g_mutex_unlock (&dconf_gdbus_lock); return success; |