refactor: Simplify D-Bus handling by using address-based connections
Replaced direct `SystemBus` and `SessionBus` instances with address-based D-Bus connections. BusProviders will open their own bus connections and close it at the end. Signed-off-by: Sven Sager <s.sager@kunbus.com>
This commit is contained in:
@@ -4,16 +4,16 @@
|
|||||||
"""Main daemon of revpi-middleware."""
|
"""Main daemon of revpi-middleware."""
|
||||||
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
|
from os import getuid, environ
|
||||||
from threading import Event
|
from threading import Event
|
||||||
from time import perf_counter
|
from time import perf_counter
|
||||||
from typing import Union, List
|
from typing import List
|
||||||
|
|
||||||
from dbus import SystemBus, SessionBus
|
from gi.repository import Gio
|
||||||
|
|
||||||
from . import proginit as pi
|
from . import proginit as pi
|
||||||
from .dbus_ios1 import BusProviderIos1
|
from .dbus_ios1 import BusProviderIos1
|
||||||
from .dbus_middleware1 import BusProviderMiddleware1
|
from .dbus_middleware1 import BusProviderMiddleware1
|
||||||
from .helper import get_new_session_dbus_connection, get_new_system_dbus_connection
|
|
||||||
|
|
||||||
log = getLogger(__name__)
|
log = getLogger(__name__)
|
||||||
|
|
||||||
@@ -43,19 +43,23 @@ class MiddlewareDaemon:
|
|||||||
|
|
||||||
log.debug("leave MiddlewareDaemon._configure")
|
log.debug("leave MiddlewareDaemon._configure")
|
||||||
|
|
||||||
def _get_bus(self) -> Union[SystemBus, SessionBus]:
|
@staticmethod
|
||||||
return (
|
def _get_bus_address() -> str:
|
||||||
get_new_session_dbus_connection()
|
if pi.pargs.use_session_bus:
|
||||||
if pi.pargs.use_session_bus
|
environ_name = "DBUS_SESSION_BUS_ADDRESS"
|
||||||
else get_new_system_dbus_connection()
|
bus_address = Gio.dbus_address_get_for_bus_sync(Gio.BusType.SESSION)
|
||||||
)
|
else:
|
||||||
|
environ_name = "DBUS_SYSTEM_BUS_ADDRESS"
|
||||||
|
bus_address = Gio.dbus_address_get_for_bus_sync(Gio.BusType.SYSTEM)
|
||||||
|
|
||||||
|
return environ.get(environ_name, bus_address)
|
||||||
|
|
||||||
def dbus_start(self):
|
def dbus_start(self):
|
||||||
log.debug("enter MiddlewareDaemon.dbus_start")
|
log.debug("enter MiddlewareDaemon.dbus_start")
|
||||||
|
|
||||||
dbus_middleware1_running = self.bp_middleware1 and self.bp_middleware1.is_alive()
|
dbus_middleware1_running = self.bp_middleware1 and self.bp_middleware1.is_alive()
|
||||||
if not dbus_middleware1_running:
|
if not dbus_middleware1_running:
|
||||||
self.bp_middleware1 = BusProviderMiddleware1(self._get_bus())
|
self.bp_middleware1 = BusProviderMiddleware1(self._get_bus_address())
|
||||||
self.bp_middleware1.start()
|
self.bp_middleware1.start()
|
||||||
|
|
||||||
dbus_ios1_running = self.bp_ios1 and self.bp_ios1.is_alive()
|
dbus_ios1_running = self.bp_ios1 and self.bp_ios1.is_alive()
|
||||||
@@ -79,14 +83,12 @@ class MiddlewareDaemon:
|
|||||||
self.bp_middleware1.join(timeout=10.0)
|
self.bp_middleware1.join(timeout=10.0)
|
||||||
if self.bp_middleware1.is_alive():
|
if self.bp_middleware1.is_alive():
|
||||||
log.warning("dbus middleware1 provider thread is still alive")
|
log.warning("dbus middleware1 provider thread is still alive")
|
||||||
self.bp_middleware1.bus.con.close()
|
|
||||||
|
|
||||||
if self.bp_ios1 and self.bp_ios1 in bus_filter:
|
if self.bp_ios1 and self.bp_ios1 in bus_filter:
|
||||||
self.bp_ios1.stop()
|
self.bp_ios1.stop()
|
||||||
self.bp_ios1.join(timeout=10.0)
|
self.bp_ios1.join(timeout=10.0)
|
||||||
if self.bp_ios1.is_alive():
|
if self.bp_ios1.is_alive():
|
||||||
log.warning("dbus ios1 provider thread is still alive")
|
log.warning("dbus ios1 provider thread is still alive")
|
||||||
self.bp_ios1.bus.con.close()
|
|
||||||
|
|
||||||
log.debug("leave MiddlewareDaemon.dbus_stop")
|
log.debug("leave MiddlewareDaemon.dbus_stop")
|
||||||
|
|
||||||
|
|||||||
@@ -5,11 +5,10 @@
|
|||||||
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
import revpimodio2
|
import revpimodio2
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
from pydbus import SessionBus, SystemBus
|
from pydbus import connect
|
||||||
|
|
||||||
from . import REVPI_DBUS_NAME
|
from . import REVPI_DBUS_NAME
|
||||||
from .interface_devices import (
|
from .interface_devices import (
|
||||||
@@ -29,14 +28,14 @@ class BusProviderIos1(Thread):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
dbus: Union[SystemBus, SessionBus],
|
dbus_address: str,
|
||||||
picontrol_device="/dev/piControl0",
|
picontrol_device="/dev/piControl0",
|
||||||
config_rsc="/etc/revpi/config.rsc",
|
config_rsc="/etc/revpi/config.rsc",
|
||||||
):
|
):
|
||||||
log.debug("enter BusProviderIos1.__init__")
|
log.debug("enter BusProviderIos1.__init__")
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._bus = dbus
|
self._bus_address = dbus_address
|
||||||
self._loop = GLib.MainLoop()
|
self._loop = GLib.MainLoop()
|
||||||
self._lst_device_interfaces = []
|
self._lst_device_interfaces = []
|
||||||
self._lst_io_interfaces = []
|
self._lst_io_interfaces = []
|
||||||
@@ -52,22 +51,23 @@ class BusProviderIos1(Thread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
log.debug("enter BusProviderIos1.run")
|
log.debug("enter BusProviderIos1.run")
|
||||||
|
bus = connect(self._bus_address)
|
||||||
|
|
||||||
self._lst_device_interfaces.clear()
|
self._lst_device_interfaces.clear()
|
||||||
self._lst_io_interfaces.clear()
|
self._lst_io_interfaces.clear()
|
||||||
|
|
||||||
for device in self._modio.device:
|
for device in self._modio.device:
|
||||||
self._lst_device_interfaces.append(
|
self._lst_device_interfaces.append(
|
||||||
InterfaceDevice(self._bus, device),
|
InterfaceDevice(bus, device),
|
||||||
)
|
)
|
||||||
|
|
||||||
for io in self._modio.io:
|
for io in self._modio.io:
|
||||||
interface = None
|
interface = None
|
||||||
try:
|
try:
|
||||||
if io.type == revpimodio2.INP:
|
if io.type == revpimodio2.INP:
|
||||||
interface = InterfaceInput(self._bus, io)
|
interface = InterfaceInput(bus, io)
|
||||||
elif io.type == revpimodio2.OUT:
|
elif io.type == revpimodio2.OUT:
|
||||||
interface = InterfaceOutput(self._bus, io)
|
interface = InterfaceOutput(bus, io)
|
||||||
elif io.type == revpimodio2.MEM:
|
elif io.type == revpimodio2.MEM:
|
||||||
# todo: Implement memory
|
# todo: Implement memory
|
||||||
pass
|
pass
|
||||||
@@ -85,7 +85,7 @@ class BusProviderIos1(Thread):
|
|||||||
(interface.object_path, interface) for interface in self._lst_io_interfaces
|
(interface.object_path, interface) for interface in self._lst_io_interfaces
|
||||||
]
|
]
|
||||||
try:
|
try:
|
||||||
self._bus.publish(
|
bus.publish(
|
||||||
REVPI_DBUS_NAME,
|
REVPI_DBUS_NAME,
|
||||||
InterfaceDeviceManager(self._lst_device_interfaces),
|
InterfaceDeviceManager(self._lst_device_interfaces),
|
||||||
InterfaceIoManager(self._lst_io_interfaces, self._modio),
|
InterfaceIoManager(self._lst_io_interfaces, self._modio),
|
||||||
@@ -100,6 +100,7 @@ class BusProviderIos1(Thread):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"can not run dbus mainloop: {e}")
|
log.error(f"can not run dbus mainloop: {e}")
|
||||||
|
|
||||||
|
bus.con.close()
|
||||||
self._modio.cleanup()
|
self._modio.cleanup()
|
||||||
|
|
||||||
log.debug("leave BusProviderIos1.run")
|
log.debug("leave BusProviderIos1.run")
|
||||||
@@ -109,10 +110,6 @@ class BusProviderIos1(Thread):
|
|||||||
self._loop.quit()
|
self._loop.quit()
|
||||||
log.debug("leave BusProviderIos1.stop")
|
log.debug("leave BusProviderIos1.stop")
|
||||||
|
|
||||||
@property
|
|
||||||
def bus(self) -> Union[SystemBus, SessionBus]:
|
|
||||||
return self._bus
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def running(self):
|
def running(self):
|
||||||
return self._loop.is_running()
|
return self._loop.is_running()
|
||||||
|
|||||||
@@ -5,10 +5,9 @@
|
|||||||
|
|
||||||
from logging import getLogger
|
from logging import getLogger
|
||||||
from threading import Thread, Event
|
from threading import Thread, Event
|
||||||
from typing import Union
|
|
||||||
|
|
||||||
from gi.repository import GLib
|
from gi.repository import GLib
|
||||||
from pydbus import SessionBus, SystemBus
|
from pydbus import connect
|
||||||
|
|
||||||
from . import REVPI_DBUS_NAME
|
from . import REVPI_DBUS_NAME
|
||||||
from .process_image import InterfacePiControl
|
from .process_image import InterfacePiControl
|
||||||
@@ -21,14 +20,14 @@ class BusProviderMiddleware1(Thread):
|
|||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
dbus: Union[SystemBus, SessionBus],
|
dbus_address: str,
|
||||||
picontrol_device="/dev/piControl0",
|
picontrol_device="/dev/piControl0",
|
||||||
config_rsc="/etc/revpi/config.rsc",
|
config_rsc="/etc/revpi/config.rsc",
|
||||||
):
|
):
|
||||||
log.debug("enter BusProviderMiddleware1.__init__")
|
log.debug("enter BusProviderMiddleware1.__init__")
|
||||||
super().__init__()
|
super().__init__()
|
||||||
|
|
||||||
self._bus = dbus
|
self._bus_address = dbus_address
|
||||||
self._loop = GLib.MainLoop()
|
self._loop = GLib.MainLoop()
|
||||||
|
|
||||||
self.picontrol_device = picontrol_device
|
self.picontrol_device = picontrol_device
|
||||||
@@ -37,6 +36,7 @@ class BusProviderMiddleware1(Thread):
|
|||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
log.debug("enter BusProviderMiddleware1.run")
|
log.debug("enter BusProviderMiddleware1.run")
|
||||||
|
bus = connect(self._bus_address)
|
||||||
|
|
||||||
# The 2nd, 3rd, ... arguments can be objects or tuples of a path and an object
|
# The 2nd, 3rd, ... arguments can be objects or tuples of a path and an object
|
||||||
# Example(),
|
# Example(),
|
||||||
@@ -44,13 +44,13 @@ class BusProviderMiddleware1(Thread):
|
|||||||
# ("Subdir2", Example()),
|
# ("Subdir2", Example()),
|
||||||
# ("Subdir2/Whatever", Example())
|
# ("Subdir2/Whatever", Example())
|
||||||
lst_interfaces = [
|
lst_interfaces = [
|
||||||
InterfacePiControl(self._bus, self.picontrol_device, self.config_rsc),
|
InterfacePiControl(bus, self.picontrol_device, self.config_rsc),
|
||||||
InterfaceRevpiConfig(self._bus),
|
InterfaceRevpiConfig(bus),
|
||||||
InterfaceSoftwareServices(self._bus),
|
InterfaceSoftwareServices(bus),
|
||||||
]
|
]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
self._bus.publish(
|
bus.publish(
|
||||||
REVPI_DBUS_NAME,
|
REVPI_DBUS_NAME,
|
||||||
*lst_interfaces,
|
*lst_interfaces,
|
||||||
)
|
)
|
||||||
@@ -63,6 +63,8 @@ class BusProviderMiddleware1(Thread):
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error(f"can not run dbus mainloop: {e}")
|
log.error(f"can not run dbus mainloop: {e}")
|
||||||
|
|
||||||
|
bus.con.close()
|
||||||
|
|
||||||
# Clean up all interfaces
|
# Clean up all interfaces
|
||||||
for interface in lst_interfaces:
|
for interface in lst_interfaces:
|
||||||
if type(interface) is tuple:
|
if type(interface) is tuple:
|
||||||
@@ -76,10 +78,6 @@ class BusProviderMiddleware1(Thread):
|
|||||||
self._loop.quit()
|
self._loop.quit()
|
||||||
log.debug("leave BusProviderMiddleware1.stop")
|
log.debug("leave BusProviderMiddleware1.stop")
|
||||||
|
|
||||||
@property
|
|
||||||
def bus(self) -> Union[SystemBus, SessionBus]:
|
|
||||||
return self._bus
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def running(self):
|
def running(self):
|
||||||
return self._loop.is_running()
|
return self._loop.is_running()
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
# -*- coding: utf-8 -*-
|
|
||||||
# SPDX-FileCopyrightText: 2025 KUNBUS GmbH
|
|
||||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
"""Helper functions for the root project."""
|
|
||||||
|
|
||||||
from os import environ, getuid
|
|
||||||
|
|
||||||
from pydbus import connect
|
|
||||||
|
|
||||||
|
|
||||||
def get_new_system_dbus_connection():
|
|
||||||
"""
|
|
||||||
Establishes a new connection to the system D-Bus.
|
|
||||||
|
|
||||||
This function retrieves the system D-Bus address from the environment
|
|
||||||
variable `DBUS_SYSTEM_BUS_ADDRESS`, defaulting to
|
|
||||||
`unix:path=/run/dbus/system_bus_socket` if the variable is not set.
|
|
||||||
It then establishes and returns a connection to the D-Bus at that
|
|
||||||
address.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
An error may be raised if establishing the connection fails.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The established system D-Bus connection.
|
|
||||||
"""
|
|
||||||
address = environ.get("DBUS_SYSTEM_BUS_ADDRESS", "unix:path=/run/dbus/system_bus_socket")
|
|
||||||
return connect(address)
|
|
||||||
|
|
||||||
|
|
||||||
def get_new_session_dbus_connection():
|
|
||||||
"""
|
|
||||||
Establishes a new connection to the session D-Bus.
|
|
||||||
|
|
||||||
This function retrieves the session D-Bus address from the environment
|
|
||||||
variable `DBUS_SESSION_BUS_ADDRESS`, defaulting to
|
|
||||||
`unix:path=/run/user/{UID}/bus` if the variable is not set.
|
|
||||||
It then establishes and returns a connection to the D-Bus at that
|
|
||||||
address.
|
|
||||||
|
|
||||||
Raises:
|
|
||||||
An error may be raised if establishing the connection fails.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
The established session D-Bus connection.
|
|
||||||
"""
|
|
||||||
address = environ.get("DBUS_SESSION_BUS_ADDRESS", f"unix:path=/run/user/{getuid()}/bus")
|
|
||||||
return connect(address)
|
|
||||||
Reference in New Issue
Block a user