From 3743630aa6325831b1a467fc10699e2c473bd304 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patrick=20Jos=C3=A9=20Pereira?= Date: Thu, 4 Jul 2024 21:07:05 -0300 Subject: [PATCH] core: services: wifi: wpa_supplicant: Ensure that a single async operation will run for each command MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Patrick José Pereira --- core/services/wifi/wpa_supplicant.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/services/wifi/wpa_supplicant.py b/core/services/wifi/wpa_supplicant.py index 2b3d14632f..f866c0cb33 100644 --- a/core/services/wifi/wpa_supplicant.py +++ b/core/services/wifi/wpa_supplicant.py @@ -4,6 +4,7 @@ import socket import time from pathlib import Path +from threading import Lock from typing import Optional, Tuple, Union from loguru import logger @@ -17,6 +18,7 @@ class WPASupplicant: def __init__(self) -> None: self.sock: Optional[socket.socket] = None + self.lock = Lock() def __del__(self) -> None: if self.sock: @@ -56,12 +58,15 @@ async def send_command(self, command: str, timeout: float) -> bytes: timeout {float} -- Maximum time (in seconds) allowed for receiving an answer before raising a BusyError """ assert self.sock, "No socket assigned to WPA Supplicant" + # pylint: disable=consider-using-with + self.lock.acquire() timeout_start = time.time() while time.time() - timeout_start < timeout: try: self.sock.send(command.encode("utf-8")) data, _ = self.sock.recvfrom(self.BUFFER_SIZE) + logger.debug(data) except Exception as error: # Oh my, something is wrong! # For now, let us report the error but not without recreating the socket @@ -73,6 +78,8 @@ async def send_command(self, command: str, timeout: float) -> bytes: except Exception as inner_error: logger.error(f"Failed to send command and failed to recreate wpa socket: {inner_error}") raise SockCommError(error_message) from error + finally: + self.lock.release() if b"FAIL-BUSY" in data: logger.info(f"Busy during {command} operation. Trying again...") @@ -84,8 +91,12 @@ async def send_command(self, command: str, timeout: float) -> bytes: continue break else: + self.lock.release() raise BusyError(f"{command} operation took more than specified timeout ({timeout}). Cancelling.") + if self.lock.locked(): + self.lock.release() + if data == b"FAIL": raise WPAOperationFail(f"WPA operation {command} failed.")