using dbus in the platform

Havoc Pennington hp at redhat.com
Tue Oct 9 09:51:16 PDT 2007


Hi,

Simon McVittie wrote:
> syntactically valid (dbus-python had to NIH validation for that sort of thing
> because libdbus doesn't provide it).

There are old threads about adding validate_path etc. calls to the 
library, I don't remember the details. I don't recall being against 
adding those, though.

> I'd tend to go for NAMESPACE_try_VERB, which is quite concise, reminds
> the reader of try/catch or try/except blocks in most languages with
> exceptions, and has the right implication of "try to do this, but if you can't,
> let me know rather than panicking".

We may want to do register_object_path() differently from something like 
message_set_path().

Here is the bright-line difference between "checks" (the current 
return_if_fail() stuff) and DBusError: it makes sense to handle errors, 
and it does not make sense to handle failed checks.

That is, the following code is not reasonable:

  try {
     frobate("foo");
  } catch (FooIsAnInvalidArgumentToFrobateException) {
     // ... um, what are you going to do here?
  }

The reason it's not reasonable is that you can simply fix the app to 
never cause the error. Handling an error that you caused yourself on the 
previous line is just nuts.

I want to preserve this bright line - while allowing languages with 
exceptions to map both cases to exceptions. This is *also* the line 
between g_return_if_fail() and GError, and I think it is the rational 
line between RuntimeException and checked exceptions in Java (though 
many Java programmers and even official APIs mangle this completely).

For try_register_object_path(), for example, I can imagine that you have 
a plugin and you want it to provide a particular object if nobody else 
already has. So having a way to conditionally register the object path 
makes sense.

However, for dbus_message_set_path(), I can't think of any reasonable 
scenario where you pass in an invalid path. There is a corner case where 
the path is provided by a user, say as a command line arg; but I think 
this is a 1% case, that happens only with dbus-related utilities like 
dbus-send or something, so I think it's reasonable for the utility to 
validate its input. Most of the time object paths are just hardcoded in 
the source code, and so having a typo in one is an app bug plain and 
simple, and the right fix is to fix the typo, not to handle a DBusError.

In languages with exceptions, there's a way to "give up" and refuse to 
continue - throwing the exception. So we want to do that even for app 
bugs (checks). But in a C API, the convention - at least my preferred 
convention, and the one matching GLib - is the one libdbus uses.
The GError docs go into some detail on the convention.

> I've done an implementation of dbus_connection_try_register_object_path and
> dbus_connection_try_register_fallback (attached).

I'll check this out later today and reply, thanks.

> Something that might be useful to adopt from GLib is that passing in a
> NULL DBusError* should be allowed, in the same way that a NULL GError*
> is allowed

This is already allowed. I designed/implemented GError, and DBusError is 
simply a copy of it, with a slight difference (DBusError is on the stack).

> - it means "I don't care about any failure, probably because
> I happen to know that only OOM can happen". That way, new API can be
> provided in the more complex form only, and the caller can just pass
> NULL if they know it won't fail for non-OOM reasons.

I do not want to see this - this is why I suggested the separate header 
for the "checked" variants of functions.

It is *important information* whether a function can fail or not. The 
functions in libdbus that don't have a DBusError either can't fail (as 
long as the API contract is met), or they can fail in only one way and 
indicate that via return value alone (generally they can fail due to out 
of memory only).

Right now, if you pass NULL for an error, it means "I am ignoring an 
error that can in fact happen." And if you write error handlers for a 
DBusError, those handlers exist for good reason.

If DBusError is returned for functions that can't fail, then those 
things aren't true.

> It'd also be good to be able to avoid calling dbus_error_init() all the
> time, by providing a DBUS_ERROR_INITIALIZER macro:
> 
> /* in dbus-errors.h */
> #define DBUS_ERROR_INITIALIZER { NULL, NULL, 0, 0, 0, 0, 0, NULL }
> 
> /* in user code */
> DBusError error = DBUS_ERROR_INITIALIZER;
> 

That might be interesting, I have to look at the code briefly to see 
what the implications are though.

Havoc



More information about the dbus mailing list