3
votes

I have a problem using Glib. I want to subscribe to a dbus signal without launching the mainloop with g_main_loop_run.

I create the connection to the correct bus and call the function g_dbus_connection_signal_subscribe.

I replaced the call to g_main_loop_run in the main function by a while(1).

Unfortunately, it's not working. If I understand correctly the GLib, there is no need to launch the mainloop for a such treatment.

Please help.

Sample code :

session_bus = g_bus_get_sync(G_BUS_TYPE_SESSION,
                             NULL,
                             NULL );


g_dbus_connection_signal_subscribe(session_bus,
                                   "org.freedesktop.Notifications",
                                   "org.freedesktop.Notifications",
                                   "NotificationClosed",
                                   "/org/freedesktop/Notifications",
                                   NULL,
                                   G_DBUS_SIGNAL_FLAGS_NONE,
                                   (GDBusSignalCallback) onNotifClosed,
                                   NULL,
                                   NULL );

loop = g_main_loop_new(NULL, FALSE);
g_main_loop_run(loop);
g_main_loop_unref(loop);
g_object_unref(session_bus);
2
"there is no need to launch the mainloop" - on the contrary, the only way it will work is to run a main loop. - ptomato

2 Answers

4
votes

If I understand correctly the GLib, there is no need to launch the mainloop for a such treatment.

If you want to wait for incoming DBus events, you have to run main loop. What main loop does is to wait and process events, and you want to wait and then process events. As an alternative to g_main_loop_run, you may try to run g_main_context_iteration in while(1).

1
votes

I had a similar need to process GLib events in a non-blocking manner and I couldn't find a complete answer anywhere, so I'm posting my solution here for reference.

As el.pescado said, the one alternative to g_main_loop_run() is calling g_main_context_iteration() repeatedly on the context of the GMainLoop object. This may be done in a loop for example, allowing some intervening_task() to be performed between event processing cycles until some sort of termination_condition() is met:

GMainLoop *loop = g_main_loop_new();
while (!termination_condition())
{
  g_main_context_iteration(g_main_loop_get_context(loop), FALSE);
  intervening_task();
}

g_main_loop_unref(loop);

In the snippet above, the loop context is retrieved by g_main_loop_get_context(), and any pending GLib events are processed by g_main_context_iteration(). Setting the may_block argument to FALSE causes the function to return immediately if there are no pending events (otherwise it would block waiting for something to process).

It's worth noticing however that if the above is all you want to do, then you might as well stick to g_main_loop_run() and use g_timeout_add() or g_idle_add() to register the intervening task and termination condition as event callbacks — the later would call g_main_loop_quit() to terminate the loop. The point here is not to use that code as-is, but merely to demonstrate how GLib events can be processed in a non-blocking manner, so it can be integrated to the main loop of another framework. e.g. Qt or ROS.