I'm developing a Python application which will be distributed to users on Linux in various forms (Flatpak, PyInstaller executable, maybe others). In this application, I want to call the Inhibit
method on the org.freedesktop.login1.Manager
dbus interface. Due to the relatively complex/diverse distribution requirements, I went with dbus-fast which is a pure Python implementation of dbus. Additionally, dbus-python's authors start the documentation of the library with various warnings, which was another point in dbus-fast's favour.
Anyway, dbus-fast seems to be working fine overall, and I am able to call e.g. the ListUsers
method without problems like so:
import asyncio
from dbus_fast import BusType
from dbus_fast.aio import MessageBus
async def list_users() -> None:
system_bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
introspection = await system_bus.introspect(
"org.freedesktop.login1",
"/org/freedesktop/login1",
)
login_object = system_bus.get_proxy_object(
"org.freedesktop.login1",
"/org/freedesktop/login1",
introspection,
)
login_manager_interface = login_object.get_interface(
"org.freedesktop.login1.Manager",
)
user_list = await login_manager_interface.call_list_users()
print(user_list)
asyncio.run(list_users())
Which I then can run and get a list like so:
$ python -m dbus_list_users
[[1000, 'newbyte', '/org/freedesktop/login1/user/_1000']]
However, if I try to call the Inhibit
method, I get EOFError
, which I don't understand the meaning of in this context. Here is the code:
import asyncio
from dbus_fast import BusType
from dbus_fast.aio import MessageBus
async def do_inhibit() -> None:
system_bus = await MessageBus(bus_type=BusType.SYSTEM).connect()
introspection = await system_bus.introspect(
"org.freedesktop.login1",
"/org/freedesktop/login1",
)
login_object = system_bus.get_proxy_object(
"org.freedesktop.login1",
"/org/freedesktop/login1",
introspection,
)
login_manager_interface = login_object.get_interface(
"org.freedesktop.login1.Manager",
)
inhibit_fd = await login_manager_interface.call_inhibit(
"sleep",
"Stack Overflow example man",
"To demonstrate that it does not work",
"delay",
)
print(inhibit_fd)
asyncio.run(do_inhibit())
Running it gives me this long traceback:
$ python -m dbus_inhibit
Traceback (most recent call last):
File "<frozen runpy>", line 198, in _run_module_as_main
File "<frozen runpy>", line 88, in _run_code
File "/mnt/storage/Programming/sparvio_toolbox/dbus_inhibit.py", line 28, in <module>
asyncio.run(do_inhibit())
File "/usr/lib64/python3.12/asyncio/runners.py", line 194, in run
return runner.run(main)
^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.12/asyncio/runners.py", line 118, in run
return self._loop.run_until_complete(task)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/usr/lib64/python3.12/asyncio/base_events.py", line 687, in run_until_complete
return future.result()
^^^^^^^^^^^^^^^
File "/mnt/storage/Programming/sparvio_toolbox/dbus_inhibit.py", line 20, in do_inhibit
inhibit_fd = await login_manager_interface.call_inhibit(
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/mnt/storage/Programming/sparvio_toolbox/_host-env/lib64/python3.12/site-packages/dbus_fast/aio/proxy_object.py", line 92, in method_fn
msg = await self.bus.call(
^^^^^^^^^^^^^^^^^^^^
File "/mnt/storage/Programming/sparvio_toolbox/_host-env/lib64/python3.12/site-packages/dbus_fast/aio/message_bus.py", line 385, in call
await future
File "src/dbus_fast/aio/message_reader.py", line 19, in dbus_fast.aio.message_reader._message_reader
File "src/dbus_fast/_private/unmarshaller.py", line 775, in dbus_fast._private.unmarshaller.Unmarshaller._unmarshall
File "src/dbus_fast/_private/unmarshaller.py", line 636, in dbus_fast._private.unmarshaller.Unmarshaller._read_header
File "src/dbus_fast/_private/unmarshaller.py", line 376, in dbus_fast._private.unmarshaller.Unmarshaller._read_to_pos
File "src/dbus_fast/_private/unmarshaller.py", line 339, in dbus_fast._private.unmarshaller.Unmarshaller._read_sock_without_fds
EOFError
I don't understand what to make of this. I've tried looking through the official documentation for inhibitor locks from systemd, but I haven't been able to figure anything out. How can I call the Inhibit
method of org.freedesktop.login1.Manager
and take an inhibitor lock in Python with dbus_python?
For some reason, dbus-fast does not enable support for file descriptor transfer by default. You must specify negotiate_unix_fd=True
as a parameter to MessageBus() to enable this.