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