Calling out to user code should be re-entrant
Submitted by Simon McVittie
Assigned to D-Bus Maintainers
Description
telepathy-glib has code that re-enters the main loop (much like gtk_dialog_run()) in order to make "blocking" method calls without suffering the undesirable side-effects of making a blocking call in libdbus (message re-ordering, and no other messages or input being processed).
I ran into trouble implementing the following pattern: when method A returns, do something with its return value and pass it straight to method B. The problematic case was when method A was called asynchronously, and method B was called in a "blocking" way by re-entering the main loop.
To make this work, I had to ensure that user callbacks (specifically, the callback for method A) were run from a high priority idle handler, rather than having dbus_connection_dispatch() in the stack - this is because the D-Bus event source is not marked as re-entrant, so when the main loop is re-entered, the D-Bus event source is blocked and the reply to method B never arrives.
The same thing happens if I make a re-entrant call to method B in a handler for D-Bus signal C (this is an obvious and convenient way to implement "whenever C happens, call B").
If it is in fact safe to use the D-Bus event source in a re-entrant way, it should be marked as such so GLib won't block it. If it's not safe to do so, the "high priority idle handler" hack should probably move into dbus-glib, so higher-level code like telepathy-glib doesn't have to worry about it.