From 2737f07b6bcb3ca19b8582b5319341c01fd0e015 Mon Sep 17 00:00:00 2001 From: Helmut Grohne Date: Wed, 21 Feb 2024 14:25:45 +0100 Subject: examples/cgroup.py: drive ravel using asyncio --- examples/cgroup.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/examples/cgroup.py b/examples/cgroup.py index baacf35..9a01d0d 100755 --- a/examples/cgroup.py +++ b/examples/cgroup.py @@ -6,10 +6,10 @@ (inside the namespace) becomes writeable to the user. """ +import asyncio import os import pathlib import sys -import time try: import ravel @@ -33,46 +33,50 @@ def get_cgroup(pid: int = -1) -> pathlib.PurePath: ) -def start_transient_unit_with_ravel(pid: int) -> None: +async def start_transient_unit_with_ravel(pid: int) -> None: """Call the StartTransientUnit dbus method on the user manager for the given pid. """ - bus = ravel.session_bus() + bus = await ravel.session_bus_async() jobs_removed = {} + scope_job = None systemd_path = "/org/freedesktop/systemd1" systemd_iface = "org.freedesktop.systemd1.Manager" + scope_created = asyncio.get_running_loop().create_future() @ravel.signal(name="JobRemoved", in_signature="uoss") def handle_job_removed(_1, path, _2, result): nonlocal jobs_removed - jobs_removed[path] = result + nonlocal scope_job + nonlocal scope_created + if scope_job is None: + jobs_removed[path] = result + elif path == scope_job: + scope_created.set_result(result) bus.listen_signal( systemd_path, False, systemd_iface, "JobRemoved", handle_job_removed ) - unitpath = ( + scope_job = ( bus["org.freedesktop.systemd1"][systemd_path] .get_interface(systemd_iface) .StartTransientUnit( f"cgroup-{pid}.scope", "fail", [("PIDs", ("au", [pid]))], [] ) )[0] - now = time.monotonic() - deadline = now + 60 - while unitpath not in jobs_removed: - if not bus.connection.read_write_dispatch(timeout=deadline - now): - break - now = time.monotonic() - if now > deadline: - break + if scope_job in jobs_removed: + scope_created.set_result(jobs_removed[scope_job]) + else: + try: + await asyncio.wait_for(scope_created, 60) + except TimeoutError: + print("Error: timed out waiting for StartTransientUnit") + sys.exit(1) bus.unlisten_signal( systemd_path, False, systemd_iface, "JobRemoved", handle_job_removed ) - if unitpath not in jobs_removed: - print("Error: timed out waiting for StartTransientUnit") - sys.exit(1) - if jobs_removed[unitpath] != "done": - print("Error: StartTransientUnit failed: " + jobs_removed[unitpath]) + if scope_created.result() != "done": + print("Error: StartTransientUnit failed: " + scope_created.result()) sys.exit(1) @@ -86,7 +90,9 @@ def main() -> None: # hiearchy is immediatly writeable. For others, we may create a scope # unit. if ravel is not None: - start_transient_unit_with_ravel(os.getpid()) + asyncio.get_event_loop().run_until_complete( + start_transient_unit_with_ravel(os.getpid()) + ) mycgroup = get_cgroup() else: # Re-execute ourselves via systemd-run. -- cgit v1.2.3