dbus and asynchronous glib thread problem

Flavio Alberto flaviothunder at terra.com.br
Mon Feb 2 07:55:02 PST 2009


Hello list,

I'm have a process using glib and dbus-glib with two threads, the main thread consuming the content of a
circular buffer and doing some intensive graphic processing (spending considerable time) e after this doing a
g_main_context_iteration(NULL, FALSE) to actualize all glib dependant subsystems.
This circular buffer is writen by dbus signals coming from another process, in producer thread initialization I
do something of this :

void *
_main_thread(void *user_data)
{
    g_warning("INICIOU A _main_thread");
    char dbus_rule[1024];
    DBusError error;
    DBusObjectPathVTable vtable;

    g_warning("COMECOU A CRIAR o input_manager_new");

    LsiInputManager *input_manager = (LsiInputManager *)user_data;

    /* Input Manager initialization */
    g_type_init();
    dbus_error_init(&error);
   
    input_manager->ref = 1;

    input_manager->context = g_main_context_new();
    input_manager->loop = g_main_loop_new(input_manager->context, TRUE);

    input_manager->objname = LSI_INPUT_MANAGER_NOBODY;
    input_manager->num_watches = 0;
    input_manager->connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
    if (! input_manager->connection) {
        g_printerr("Failed to open connection to bus: %s\n", error.message);
        goto out_error;
    }

    dbus_connection_setup_with_g_main(input_manager->connection, NULL);
    //dbus_connection_setup_with_g_main(input_manager->connection, input_manager->context);

    /* Listen for messages coming from Input Manager objects */
    dbus_error_init(&error);
    snprintf(dbus_rule, sizeof(dbus_rule), 
            "type='signal',interface='%s',path='%s'", 
            DEEP_DBUS_INTERFACE, DEEP_DBUS_INPUT_MANAGER_PATH);
    dbus_bus_add_match(input_manager->connection, dbus_rule, &error);
    if (dbus_error_is_set(&error)) {
        g_warning("Error adding match to the bus: %s", error.message);
        goto out_error;
    }

    input_manager->quit = FALSE;

    vtable.message_function = input_manager_filter;
    vtable.unregister_function = NULL;
    dbus_connection_register_object_path(input_manager->connection, DEEP_DBUS_INPUT_MANAGER_PATH, &vtable,
input_manager->loop);

    pthread_mutex_lock(&mutex);
    initialized = TRUE;
    pthread_cond_signal(&condition);
    pthread_mutex_unlock(&mutex);

     g_main_loop_run(input_manager->loop);

out_error:
    if (dbus_error_is_set(&error))
        dbus_error_free(&error);
    g_free(input_manager);

    pthread_exit(NULL);
}

   The function input_manager_filter is the dbus filter function that receives the signal and fills the
circular buffer with these data from dbus channel launching another thread that write the buffer.

   The objective is keep this thread running and feeding the circular buffer until it is full while the main
thread are consuming it. After the buffer is full (case when the consumer is more slow than producer) we must
discard the incoming data to system not process too much delayed data.
   The problem occurs because the dbus filter function doesn't run in the second thread context, running in the
main context thread and blocking a long time when this thread is processing, I need to filter function (and
consequent write in the circular buffer) execute in separated thread.

    I thougth that using dbus_connection_setup_with_g_main(input_manager->connection, input_manager->context)
on the contrary  dbus_connection_setup_with_g_main(input_manager->connection, NULL) I could connect the dbus
system in the new context that I created inside the second thread but in this case none message is received and
appears that the dbus system is "dead".

    There's some way to run dbus-glib system in other GMainContext (and other GMainLoop) asynchronously the
GMainLoop from main thread ?

    Thanks for all help.

Flavio Alberto





More information about the dbus mailing list