From 0748e07a739e3db2a90aa915edea02d0b26b5bdf Mon Sep 17 00:00:00 2001 From: appel_c Date: Thu, 25 Jun 2026 08:53:13 +0200 Subject: [PATCH] fix(mcs): fix mcs card monitor thread --- .../devices/epics/mcs_card/mcs_card_csaxs.py | 57 ++++++++++--------- 1 file changed, 30 insertions(+), 27 deletions(-) diff --git a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py index 7f31e1b..b50cb06 100644 --- a/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py +++ b/csaxs_bec/devices/epics/mcs_card/mcs_card_csaxs.py @@ -454,33 +454,36 @@ class MCSCardCSAXS(PSIDeviceBase, MCSCard): NOTE! This logic currently works for any step scan, but has to be extended for fly scans. """ while not self._scan_done_thread_kill_event.is_set(): - while self._start_monitor_async_data_emission.wait(): - try: - if ( - hasattr(self.scan_parameters, "num_points") - and self.scan_parameters.num_points is not None - ): - if self.scan_parameters.scan_type == "software_triggered": - logger.info( - f"Software triggered scan: {self._current_data_index}/{self.scan_parameters.num_points} points received." - ) - if self._current_data_index == self.scan_parameters.num_points: - for callback in self._scan_done_callbacks: - callback(exception=None) - else: - if self._current_data_index >= 1: - for callback in self._scan_done_callbacks: - callback(exception=None) - - time.sleep(0.02) # 20ms delay to avoid busy loop - except Exception as exc: # pylint: disable=broad-except - content = traceback.format_exc() - logger.error( - f"Exception in monitoring thread of complete for {self.name}:\n{content}" - "Running callbacks to avoid deadlock." - ) - for callback in self._scan_done_callbacks: - callback(exception=exc) + # 20ms delay to avoid busy loop + if not self._start_monitor_async_data_emission.wait(timeout=0.02): + continue # Wait for the event to be set before checking data emission + try: + if ( + hasattr(self.scan_parameters, "num_points") + and self.scan_parameters.num_points is not None + ): + if self.scan_parameters.scan_type == "software_triggered": + logger.info( + f"Software triggered scan: {self._current_data_index}/{self.scan_parameters.num_points} points received." + ) + if self._current_data_index == self.scan_parameters.num_points: + for callback in self._scan_done_callbacks: + callback(exception=None) + else: + if self._current_data_index >= 1: + for callback in self._scan_done_callbacks: + callback(exception=None) + # 20ms delay to avoid busy loop + if self._scan_done_thread_kill_event.wait(timeout=0.02): + continue + except Exception as exc: # pylint: disable=broad-except + content = traceback.format_exc() + logger.error( + f"Exception in monitoring thread of complete for {self.name}:\n{content}" + "Running callbacks to avoid deadlock." + ) + for callback in self._scan_done_callbacks: + callback(exception=exc) def _status_callback(self, status: StatusBase, exception=None) -> None: """Callback for status completion."""