Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Documentation/example missing for use of Inhibitor interface #34004

Open
jimklimov opened this issue Aug 15, 2024 · 8 comments
Open

Documentation/example missing for use of Inhibitor interface #34004

jimklimov opened this issue Aug 15, 2024 · 8 comments

Comments

@jimklimov
Copy link

Component

No response

Is your feature request related to a problem? Please describe

I investigate for an issue at networkupstools/nut#1070 to develop integration for a daemon with the systemd inhibitor interface, so that NUT upsmon would not shut down the system after a sleep and wake-up due to "lost" UPS last known to be in a critical state.

Documentation at https://www.freedesktop.org/software/systemd/man/latest/org.freedesktop.login1.html implies that it "provides both a C library interface as well as a D-Bus interface", at https://www.freedesktop.org/software/systemd/man/latest/sd-login.html that "It is possible (and often a very good choice) to mix calls to the synchronous interface of sd-login.h with the asynchronous D-Bus interface of systemd-logind" and at https://systemd.io/INHIBITOR_LOCKS/ and https://github.com/systemd/systemd/blob/main/docs/INHIBITOR_LOCKS.md offers actual (pseudo-)code with Inhibit() method getting a file descriptor to close() later.

I did not find any headers with C methods like Inhibit, PrepareForSleep, PrepareForShutdown or ListInhibitors on a couple of systems with libsystemd-dev(el) installed.

Describe the solution you'd like

Clarify if there is actually a plain C API and provide a simple complete example.

Describe alternatives you've considered

Looking a bit at monsters like https://stackoverflow.com/questions/78653343/how-to-get-an-inhibitor-lock-for-a-service-in-c-language makes me scared about complex changes needed for a platform-specific bit.

If this is the only supported way, so be it, but I hoped that I can just call if (PrepareForSleep(...)) in the program's main loop, and react to the returned value (e.g. set a flag internally to not consider stale UPS data as fatal, and clear the inhibitor lock so the system can go to sleep to conserve the battery).

The systemd version you checked that didn't have the feature you are asking for

249

@jimklimov jimklimov added the RFE 🎁 Request for Enhancement, i.e. a feature request label Aug 15, 2024
@bluca
Copy link
Member

bluca commented Aug 15, 2024

Clarify if there is actually a plain C API and provide a simple complete example.

API means D-Bus API. You can find a full implementation to find inspiration from here: https://github.com/systemd/systemd/blob/main/src/login/inhibit.c

@jimklimov
Copy link
Author

Ok, thanks. So the C-looking "pseudo code" in the docs was just that - really pseudo, just C-looking, and in fact was about D-bus calls to the systemd daemons managing the system like bus_call_method(bus, bus_login_mgr, "Inhibit", error, &reply, "ssss", arg_what, arg_who, arg_why, arg_mode); right?

In that case, perhaps a link to this source from the doc would be helpful =D

Also, does the phrase "Taking inhibitor locks is a privileged operation" mean that taking such locks is an operation limited to privileged users or systemd units set up with special properties, so a random user-space process would not block OS life-cycle? Is there something to be detailed about this in that doc (e.g. what can non-root services do to get that privilege) or did I misunderstand the statement?

@jimklimov
Copy link
Author

jimklimov commented Aug 19, 2024

Seems the referenced inhibit.c refers to project-private headers. The /usr/include/systemd/sd-bus.h packaged on my system has at least some of those methods prefixed by sd_ (so a blunt copy-paste did not compile, testing now how much chiseling is needed).

Wondering also if there is an autotools-friendly way to determine support for the feature, or just that the systemd version is to be consulted?

@poettering poettering added login documentation and removed RFE 🎁 Request for Enhancement, i.e. a feature request labels Aug 19, 2024
@jimklimov
Copy link
Author

jimklimov commented Aug 19, 2024

This doc seems important to reference for "independent" development (that does not rely on internal headers etc.):

...because my tinkering so far reflects inhibit.c tool source less and less :D

That man page also notes that sd_bus_call_method() was added in libsystemd 221 (while inhibitor generally is there since 183 - just was not exposed via D-Bus API all too well?) - same said in https://www.freedesktop.org/software/systemd/man/latest/sd_bus_message_read_basic.html and https://www.freedesktop.org/software/systemd/man/latest/sd_bus_default_system.html

The tool also refers to https://www.freedesktop.org/software/systemd/man/latest/sd_bus_message_enter_container.html which seems to be since 246 (no clear reference)...

@jimklimov
Copy link
Author

And also https://systemd.io/INHIBITOR_LOCKS/ is not in sync with https://github.com/systemd/systemd/blob/main/docs/INHIBITOR_LOCKS.md at least in regard to block-weak/delay-weak "mode" values (so the "Two different modes of locks..." intro is not too pedantically correct). Just above that, "Seven distinct inhibitor lock types" have a list of six numbered bullets :) although one more is unnumbered.

@jimklimov
Copy link
Author

jimklimov commented Aug 19, 2024

@bluca : If I may, got another moment to clarify: as far as these bus messages and boolean states go, is "sleep" same as "suspend" or "hibernate"?

@jimklimov
Copy link
Author

jimklimov commented Aug 19, 2024

Man pages to sd_bus_open() et al seem to lack a note of ENOENT for the peculiar practical case: absence of /run/dbus/system_bus_socket.
Bit me while testing on WSL2 with alleged systemd support (services work, bus absent it seems?)
UPDATE: Seems it got disabled during some update:

$ systemctl status
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down

@jimklimov
Copy link
Author

jimklimov commented Aug 19, 2024

Well, with systemd in WSL2 enabled via /etc/wsl.conf and VM reboot, and iterating on typos etc. most of that NUT PR works for me - feel free to reference in docs for a standalone systemd/dbus client example for this use-case, if needed.

Can't get WSL2 to systemctl suspend (nor hibernate) though:

# systemctl suspend
Failed to set wall message, ignoring: Interactive authentication required.
Failed to suspend system via logind: Sleep verb "suspend" not supported

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

3 participants