5

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);
1
  • 3
    "there is no need to launch the mainloop" - on the contrary, the only way it will work is to run a main loop. Commented May 20, 2014 at 5:56

2 Answers 2

5

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.

Sign up to request clarification or add additional context in comments.

4 Comments

You’ve basically reinvented a poor version of g_main_loop_run() there. If you look at the source code for g_main_loop_run(), it does the equivalent of calling g_main_context_iteration() in a loop. You would be better off creating a GSource for your intervening_task() (for example, using g_idle_source_new()) and adding that to the main context. Then your intervening task can be polled/waited for in the same poll() call as the rest of the event sources in the main context.
Yes, but you miss the point. The purpose of that code snippet is not to be used as-is, but to demonstrate how GLib events can be processed in a non-blocking manner. Then you're free to apply that however you need.
In my case for example, I wanted to call g_main_context_iteration() from a ROS timer callback function. If I had seen a snippet like that, it would have made things easier for me, even though my finished code looks nothing like that.
Ah, I missed the fact that you were calling g_main_context_iteration() with may_block set to false. i.e. Chaining the GLib main loop to another main loop, rather than the other way round. What you’ve said makes sense in that case, sorry for the misinterpretation. One simplification you could make is to drop the GMainLoop entirely, and construct/use GMainContext directly (g_main_context_new() or g_main_context_default()). GMainLoop is just a closure which contains a GMainContext and an exit condition.
4

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).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.