I have a GUI where I display the ActiveState of several systemd services.
At 10Hz, I use the sd-bus api to query each service like so:
sd_bus* bus;
sd_bus_error err = SD_BUS_ERROR_NULL;
char* msg = 0;
sd_bus_default_system(&bus);
sd_bus_get_property_string(bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1/unit/foo_2eservice",
"org.freedesktop.systemd1.Unit",
"ActiveState",
&err,
&msg);
My problem is that when I run this code, /sbin/init or /lib/systemd/systemd-logind consumes about 50% CPU. Profiling the code shows a massive amount of time consumed by sd_bus_get_property_string. I need to reduce the number of times I call this function.
The introspection of the d-bus interface is interesting:
busctl introspect \
org.freedesktop.systemd1 \
/org/freedesktop/systemd1/unit/foo_2eservice \
org.freedesktop.system1.Unit
NAME TYPE SIGNATURE RESULT/VALUE FLAGS
.Kill method si - -
.Ref method - - -
.Reload method s o -
.ReloadOrRestart method s o -
.ReloadOrTryRestart method s o -
.ResetFailed method - - -
.Restart method s o -
.SetProperties method ba(sv) - -
.Start method s o -
.Stop method s o -
.TryRestart method s o -
.Unref method - - -
.ActiveEnterTimestamp property t 0 emits-change
.ActiveEnterTimestampMonotonic property t 0 emits-change
.ActiveExitTimestamp property t 0 emits-change
.ActiveExitTimestampMonotonic property t 0 emits-change
.ActiveState property s "inactive" emits-change
...
This tells me that the ActiveState property emits a change.
How can I get a file-descriptor, or tap into the event-loop to receive that change?
The D-Bus specification suggests that systemd will emit a org.freedesktop.DBus.Properties.PropertiesChanged signal when properties change. I think I need to figure out how to subscribe to that signal.