DBus: Is busy-polling the only way to check for emitted signals on the system-bus (via low-level ANSI C API)?

Greetings everybody!

I am wondering, if there is any way (via the low-level C API of DBus) to be informed about a certain signal being emitted without doing a busy polling loop… with some sleep() thrown in.

Here is some example code…

while (1) {
    dbus_connection_read_write (connection, 0);
    message = dbus_connection_pop_message (connection);

    if (message == NULL) { 
        sleep (1);
        continue;
    }

    if (dbus_message_is_signal (message, "net.hadess.SensorProxy", "PropertiesChanged")) {
        if (!dbus_message_iter_init (message, &args))
            printf("Message has passed no arguments!\n"); 
        else if (DBUS_TYPE_STRING != dbus_message_iter_get_arg_type (&args)) 
            printf ("Argument is not string!\n"); 
        else {
            dbus_message_iter_get_basic (&args, &value);
            printf ("Received signal with payload, value: %s\n", value);
        }
    }

    dbus_message_unref (message);
}

I looked through the DBus headers and found nothing that would hint towards some callback-mechanism, that one could use to have the dbus-daemon notify an interested application of a particular signal being emitted.

Thanks in advance!

Best regards…

MacSlow

well. As the documentation says:

If you use this low-level API directly, you’re signing up for some pain.

That said, you are using read_write with a timeout of 0. If I remember correctly, read_write should block until there is actually anything to process if you specified a non-0 timeout.

Using GDbus is much more comfortable than using libdbus directly - and since you are posting with the glib tag in the GNOME forum, I assume you are using glib somehow?

Hello, the low-level dbus API is not used by glib, so this is not really a question for this forum but I will answer anyway. It is necessary to use dbus_connection_set_watch_functions and dbus_connection_set_timeout_functions and then call poll yourself on the fds received from within those callbacks. I agree with the above reply by @jensgeorg and I would not recommend using the low-level API if you do not already have another low-level event loop you are integrating with without a native dbus binding, e.g. libuv or similar.

Thanks folks. I will look into those suggestions.

Since I plan to use this in a patch against kmscon (kmscon), I do not think I can easily use the GDBus bindings from GIO. That’s why I am sticking with the low-level C API of dbus for now.

Should it turn out, that I can “marry” kmscon’s eloop with glib’s event-loop, I will of course make that swtich.

Best regards…

MacSlow

That event loop does have functions for fd sources and timer sources, so you should be able to use them: kmscon/eloop.h at master · dvdhrm/kmscon · GitHub

The sd-bus bindings from systemd are another low-level OOM-safe binding that is more convenient to use than libdbus. GDBus is not a good fit for a low-level terminal, it is not OOM-safe.

I cannot agree with this emphatically enough.

Do not use libdbus, it has unfixable API problems, is a pain to use, and is in low-maintenance mode.

sd-bus is probably want you want to use. See this StackOverflow answer for a comparison of the different D-Bus bindings in C.