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