[Telepathy] telepathy-glib: *_run_* methods.
Simon McVittie
simon.mcvittie at collabora.co.uk
Tue Nov 18 06:50:27 PST 2008
On Tue, 18 Nov 2008 at 11:08:07 +0100, Murray Cumming wrote:
> It's been suggested that people should just never use the run functions
> such as tp_cli_connection_run_request_handles(), because these are
> really asynchronous operations.
> http://telepathy.freedesktop.org/doc/telepathy-glib/telepathy-glib-connection.html#tp-cli-connection-run-request-handles
We don't think people should ever use libdbus' pseudo-blocking API (as
exposed through dbus-glib), but the _run_ methods are indeed not the same
thing.
> However, these functions won't block the main mainloop, right. For
> instance, they won't prevent a GTK+ application from responding to
> button clicks. Or am I wrong?
You are correct.
> So the use of these functions really doesn't seem that awful. If you
> really know that there's nothing else you need to do while waiting,
> other than responding to user input, then they seem like a sensible way
> to simplify your code.
They have all the benefits and all the drawbacks of gtk_dialog_run()
(hence the naming convention). If your program is simple enough to cope
with reentrant main loops (like most of the telepathy-glib regression
tests), go ahead; otherwise, be afraid.
Any event can occur during a _run_, including D-Bus signals, returns from
other methods, etc., and the program has to cope gracefully.
I'm somewhat regretting introducing those functions, for the reasons
that Xavier and Alban pointed out. They can be useful in sufficiently
controlled environments, though.
In newer bits of telepathy-glib (like TpContact) I haven't been
implementing a _run_ variant of the API, only the underlying callback-based
version.
Some background information on pseudo-blocking, for the record...
The pseudo-blocking API (dbus_do_something_and_block(), and "synchronous"
calls in code generated by dbus-binding-tool) works like this:
* send method call message (call it M)
* while reply has not been received:
* select() or poll() on the D-Bus socket, ignoring all other I/O
* whenever a whole message has been received:
* check whether the message is a reply to M
* if it is (call it R), stop
* if it is not, put it on the incoming message queue
The messages received between M and R are delivered when the main loop is
next entered.
This can cause a number of problems:
* Messages are re-ordered: messages received between M and R
aren't delivered until after the reply, violating the ordering
guarantee that the D-Bus daemon usually provides.
(This causes practical problems if a signal indicating object destruction is
delayed - the client gets a method reply "UnknownMethod", has to guess
that this is because the object has vanished, and can't know why it vanished
until the signal indicating its destruction arrives with more details.)
* The client is completely unresponsive until the service replies -
if the service has somehow got wedged (e.g. telepathy-gabble is meant
to be purely non-blocking and asynchronous, but there are cases where
it will do blocking I/O on SSL connections due to Loudmouth bugs), the
client will be unresponsive for (by default) 25 seconds until the call
times out.
(Clients shouldn't crash or lock up, whatever happens to the services
they depend on.)
* The client can't parallelize calls - if a signal (e.g. an incoming
Text message) causes method calls to be made, a client that uses
pseudo-blocking calls can't even *start* processing the next message until
those method calls return
* If two processes make pseudo-blocking calls on each other, deadlock
occurs. This is particularly tricky in the presence of a plugin
architecture and shared D-Bus connections - a plugin that "knows" it's a
client and not a service, and a plugin in the same process that "knows"
it's a service and not a client, can end up sharing a connection,
resulting in a process that is both a service and a client (and hence
deadlock-prone).
(We've seen this happen in the OLPC Sugar environment and on Nokia
internet tablets; it's not just a theoretical concern.)
As a result, telepathy-glib's code generation mechanism does not generate
any pseudo-blocking code.
We make a couple of narrowly targeted exceptions to the "no pseudo-blocking"
policy, by allowing telepathy-glib internals to make a small number of
pseudo-blocking method calls to the dbus-daemon (which is the one component
we can definitely trust to return results promptly).
Simon
More information about the Telepathy
mailing list