feat(revpiconfig): Add thread safety for config.txt file operations

Introduced a threading lock to safeguard read and write operations on
the `config.txt` file. This ensures thread-safe access and prevents
potential race conditions during concurrent execution.

Signed-off-by: Sven Sager <s.sager@kunbus.com>
This commit is contained in:
Sven Sager
2025-06-26 06:41:59 +02:00
parent b4f817b477
commit fedb0f8924

View File

@@ -10,6 +10,7 @@ from glob import glob
from logging import getLogger from logging import getLogger
from os import X_OK, access from os import X_OK, access
from os.path import exists, join from os.path import exists, join
from threading import Lock
from typing import List, Optional from typing import List, Optional
from pydbus import SystemBus from pydbus import SystemBus
@@ -24,6 +25,7 @@ ConfigVariable = namedtuple("ConfigVariable", ["name", "value", "line_index"])
LINUX_BT_CLASS_PATH = "/sys/class/bluetooth" LINUX_BT_CLASS_PATH = "/sys/class/bluetooth"
LINUX_WLAN_CLASS_PATH = "/sys/class/ieee80211" LINUX_WLAN_CLASS_PATH = "/sys/class/ieee80211"
CONFIG_TXT_LOCATIONS = ("/boot/firmware/config.txt", "/boot/config.txt") CONFIG_TXT_LOCATIONS = ("/boot/firmware/config.txt", "/boot/config.txt")
CONFIG_TXT_LOCK = Lock()
class ComputeModuleTypes(IntEnum): class ComputeModuleTypes(IntEnum):
@@ -228,11 +230,6 @@ class ConfigTxt:
to manipulate specific parameters within the configuration and supports to manipulate specific parameters within the configuration and supports
managing dtoverlay and dtparam entries. The primary aim of this class managing dtoverlay and dtparam entries. The primary aim of this class
is to abstract file operations and make modifications user-friendly. is to abstract file operations and make modifications user-friendly.
Attributes:
_config_txt_path (str): The path to the configuration file `config.txt`.
_config_txt_lines (list[str]): Contains all lines of the configuration
file as a list of strings, where each string represents a line.
""" """
re_name_value = re.compile(r"^\s*(?!#)(?P<name>[^=\s].+?)\s*=\s*(?P<value>\S+)\s*$") re_name_value = re.compile(r"^\s*(?!#)(?P<name>[^=\s].+?)\s*=\s*(?P<value>\S+)\s*$")
@@ -318,6 +315,7 @@ class ConfigTxt:
Returns: Returns:
None None
""" """
with CONFIG_TXT_LOCK:
with open(self._config_txt_path, "r") as f: with open(self._config_txt_path, "r") as f:
self._config_txt_lines = f.readlines() self._config_txt_lines = f.readlines()
@@ -333,6 +331,7 @@ class ConfigTxt:
if not self._config_txt_lines: if not self._config_txt_lines:
return return
with CONFIG_TXT_LOCK:
tmp_path = f"{self._config_txt_path}.tmp" tmp_path = f"{self._config_txt_path}.tmp"
with open(tmp_path, "w") as f: with open(tmp_path, "w") as f:
f.writelines(self._config_txt_lines) f.writelines(self._config_txt_lines)