using dbus in the platform

Havoc Pennington hp at redhat.com
Tue Oct 9 08:45:29 PDT 2007


Hi,

Simon McVittie wrote:
> However, to make a decent Python binding, libdbus will have to get
> better at being wrapped in high-level languages (the "everything returns
> a DBusError, nothing aborts for reasons that can't be checked for"
> approach that libdbus explicitly doesn't follow at the moment). Would
> you accept patches that improve libdbus' behaviour in that respect?

I think there's a way to do this, yes, but we have to be careful about 
how. I have a vague idea that needs more elaboration, I will give you 
the vague version.

First the problem statement: we want to share code among language 
bindings that checks for bugs in app-provided args or data, so those 
bindings can throw an exception.

The vague idea: take a function like dbus_message_set_path(const char 
*path). We could add:
    dbus_message_set_path_checked(const char *path, DBusError *error);

For programming bugs, the error could always be set to a single name, 
say DBUS_ERROR_APPLICATION_BUG or DBUS_ERROR_BAD_ARGUMENTS or something 
like that.

I'm not sure if set_path() (for example) should wrap the checked 
version, or vice versa; depends on specifically how the code works out 
both ways and which one looks cleaner. We want to get understandable 
messages in both the DBusError and the return_if_fail message, and we 
should avoid all the checking overhead if libdbus is built with 
--disable-checks (but the _checked() flavors have to still work with 
--disable-checks since --disable-checks should not change the API contract)

I would suggest sticking all the "checked" variants in a separate 
header, i.e. not in dbus.h, because they are only correct for language 
bindings.

I'm not sure about the naming ("checked") - that may not make sense for 
all functions.

If possible, we could avoid a whole lot of "checked" variants by *not* 
doing stuff like:
   dbus_connection_ref_checked(DBusConnection *connection, DBusError 
*error);
I think it is reasonable to expect that bindings do not pass in a NULL 
connection, and it's probably easier for bindings to write their own "if 
null then throw" than for them to handle the DBusError there. At least, 
I hope so. If we need error-throwing variants of *everything* just to 
check for NULL, that will be a lot of new library symbols.

Also remember here that we need the dbus-daemon enhancement to shove an 
error message down the socket before dropping a connection, if malformed 
protocol is seen. That will fix another type of silent error. This is 
just missing a patch.

> My goal is that nothing the Python programmer can do can cause libdbus
> to abort (in Python, every error is meant to raise an exception, including
> programmer error and OOM, but not including internal checks that would
> indicate a Python implementation bug). At the moment that's impossible to
> ensure.

fwiw "impossible" is certainly not intended. Hard, sure, since all the 
args to every function have to be validated in a language binding 
context. But where it's impossible, I'd generally consider it a bug.

> The most glaring example is that libdbus will warn (and usually abort)
> when you try to register two objects with the same object-path, but there's
> no easy way to tell whether there's already an object at the path the Python
> programmer has asked for. In any case dbus_is_there_an_object_here() has
> the wrong semantics in a multi-threaded program - the right API would be
> a dbus_try_register_object_path() that returns a
> high-level-language-friendly, non-fatal error if the object path already
> exists.

That sounds like a fine addition.

> My other major problem with libdbus was that I spent a week thinking
> about increasingly cunning ways to use weak references to avoid cyclic
> references between the shared connection and the Python wrapper, and
> eventually gave up.

Just ask if you hit stuff like this. Probably we just need to add toggle 
references like GObject, then we can do as well as pygtk I would think.

http://mail.gnome.org/archives/gtk-devel-list/2005-April/msg00095.html

There really are not any new problems in libdbus; everything is modeled 
on how X or GObject or whatever works, so most of these issues have 
already been worked out, and it's just a matter of copying the ideas 
over. Omitting toggle refs was an oversight, just didn't think of it.

> It's likely that good solutions to the problems I'm facing in
> dbus-python would require more of libdbus' internal API to become
> public, in much the same way that Daf's dbus_message_marshal() and
> dbus_message_unmarshal() expose (a copy of) the actual message data. I hope
> that's not a problem.

It's not a problem to extend the API when there are good reasons to do so.

Havoc


More information about the dbus mailing list