Handling message replies asynchronously in a separate thread
produces a warning
Jamie McCracken
jamiemcc at blueyonder.co.uk
Fri Nov 25 04:52:49 PST 2005
I occasionally get a warning from dbus when I return a reply to a dbus
message asynchronously (in a different thread). (I am calling
dbus_g_thread_init () at the start of my program so its not a threading
issue I think). The functionality of the app is not affected and
everything works as expected but I dont like that warning cropping up!
I am being a bit naughty as the message handling func will return
DBUS_HANDLER_RESULT_HANDLED even though the actual reply will be sent
back much later on in a different thread (there is no way round this for
me as its the only way to create a fast stateless multithreaded
middleware server)
The warning relates to calling dbus_message_ref (message) which I need
to do to keep the message alive after the message handler function has
exited and until its processed later on.
The warning happens very rarely and is as follows :
10308: arguments to dbus_message_ref() were incorrect, assertion
"!message->in_cache" failed in file dbus-message.c line 1083.
This is normally a bug in some application using the D-BUS library.
(the version of Dbus is 0.50)
By calling dbus_message_ref (message) earlier on in the function the
warning seems to disappear or occur less likely - why?.
The message handling function is below:
static DBusHandlerResult
message_func (DBusConnection *conn,
DBusMessage *message,
gpointer data)
{
DBusRec *rec;
rec = g_new (DBusRec, 1);
rec->connection = conn;
rec->message = message;
if (dbus_message_is_method_call (message,
TRACKER_FILE_METADATA_INTERFACE, "test")) {
/* ref the message here because we are going to reply to it in a
different thread so we need to keep it alive when this function exits */
dbus_message_ref (message);
rec->action = DBUS_ACTION_NONE;
/* queue request to be handled by a thread later on */
g_async_queue_push (user_request_queue, rec);
/* we have to return this even though we have not replied to the
message yet */
return DBUS_HANDLER_RESULT_HANDLED;
}
}
the threads that processes the queue look like :
static void
process_user_request_queue_thread ()
{
DBusRec *rec;
DBConnection db_con;
/* set thread safe DB connection */
mysql_thread_init ();
db_con.db = tracker_db_connect ();
tracker_db_prepare_queries (&db_con);
while (TRUE) {
DBusMessage *reply;
char **array = NULL;
int row_count, i;
MYSQL_ROW row = NULL;
char *str, *str2;
/* get a queued dbus message to process */
rec = g_async_queue_pop (user_request_queue);
switch (rec->action) {
case DBUS_ACTION_NONE:
dbus_message_get_args (rec->message, NULL,
DBUS_TYPE_STRING, &str2,
DBUS_TYPE_INVALID);
reply = dbus_message_new_method_return (rec->message);
str = g_strconcat ("testing with ", str2, "\n", NULL);
dbus_message_append_args (reply,
DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID);
dbus_connection_send (rec->connection, reply, NULL);
dbus_message_unref (reply);
g_free (str);
break;
Blah blah blah ...
dbus_message_unref (rec->message);
g_free (rec);
}
--
Mr Jamie McCracken
http://www.advogato.org/person/jamiemcc/
More information about the dbus
mailing list