I'm not be able to openning and clossing secuently the camera using threads from pyqt6

After successfully opening and closing a ZED-X camera with the ZED SDK in Python (using a QThread from qt6), all subsequent attempts to open the camera (in new threads) fail. The SDK returns a camera open error, and dmesg shows ‘probe failed with error -1’ and ‘serializer initialization failed’ for the ZED-X sensor (MAX96712).

For each thread, I open the camera, take a picture and close the camera, but when I repeat the program break.

Even after deleting the camera object, doing explicit garbage collection, and waiting several seconds (busy-wait), the device cannot be re-initialized without rebooting the system.

But if I do it in the main thread (sequentially in a loop, using a for), the camera opens and closes successfully every time.

This test was created by ChatGPT but works to proof my point.

import sys
import time
import traceback
import pyzed.sl as sl
import gc

from PyQt6.QtCore import QThread, pyqtSignal, QObject, QCoreApplication

# --- CONFIG BLOCK ---
CONFIG = {
    "max_cycles": 10,      # How many times to open/close
    "sleep_between": 2,    # Seconds between close and next open
    "resolution": sl.RESOLUTION.HD1080,
    "fps": 15,
    "depth_mode": sl.DEPTH_MODE.NEURAL,
    "timeout_on_open": 8,  # Not used - for future
    "verbose": True
}

class CameraThread(QThread):
    finished_signal = pyqtSignal(int, str)  # ciclo, resultado

    def __init__(self, cfg, cycle_id):
        super().__init__()
        self.cfg = cfg
        self.cycle_id = cycle_id

    def run(self):
        reslog = ""
        cam = None
        try:
            # --- OPEN ---
            if self.cfg["verbose"]:
                print(f"[Ciclo {self.cycle_id}] Opening ZED camera (QThread)...")
            cam = sl.Camera()
            init_params = sl.InitParameters(
                camera_resolution=self.cfg["resolution"],
                camera_fps=self.cfg["fps"],
                depth_mode=self.cfg["depth_mode"],
                coordinate_units=sl.UNIT.METER,
                coordinate_system=sl.COORDINATE_SYSTEM.RIGHT_HANDED_Y_UP,
                sdk_verbose=0
            )
            err = cam.open(init_params)
            cam.enable_positional_tracking()
            if err != sl.ERROR_CODE.SUCCESS:
                print(f"[Ciclo {self.cycle_id}] ❌ Open error: {err}")
                reslog = f"OPEN FAILED ({err})"
                return
            print(f"[Ciclo {self.cycle_id}] ✅ Camera opened!")

            # --- GRAB ---
            mat = sl.Mat()
            status = cam.grab()
            if status == sl.ERROR_CODE.SUCCESS:
                cam.retrieve_image(mat, sl.VIEW.LEFT)
                print(f"[Ciclo {self.cycle_id}] Image grab OK")
                reslog = "SUCCESS"
            else:
                print(f"[Ciclo {self.cycle_id}] Grab failed: {status}")
                reslog = f"GRAB FAILED ({status})"

            # --- CLOSE ---
            try:
                cam.disable_positional_tracking()
            except Exception:
                print(f"[Ciclo {self.cycle_id}] disable_positional_tracking() failed (maybe not enabled)")
            try:
                cam.close()
                print(f"[Ciclo {self.cycle_id}] Camera closed.")
            except Exception as e:
                print(f"[Ciclo {self.cycle_id}] Camera close error: {e}")

            del cam
            cam = None
            gc.collect()
            print(f"[Ciclo {self.cycle_id}] GC done.")

        except Exception as e:
            print(f"[Ciclo {self.cycle_id}] EXCEPTION: {e}")
            print(traceback.format_exc())
            reslog = f"EXCEPTION {e}"
        finally:
            # Emite señal de terminado para el ciclo
            self.finished_signal.emit(self.cycle_id, reslog)

def run_camera_cycles_qt(config):
    from PyQt6.QtWidgets import QApplication
    app = QApplication(sys.argv)
    logs = []

    def on_cycle_finished(cycle_id, result):
        print(f"=== Ciclo {cycle_id} terminado: {result} ===")
        logs.append(f"Cycle {cycle_id}: {result}")
        # Lanza el próximo ciclo o sale si ya son todos
        run_next_cycle(cycle_id + 1)

    def run_next_cycle(cycle):
        if cycle > config["max_cycles"]:
            print("==== TODOS LOS CICLOS HECHOS ====")
            for log in logs:
                print(log)
            QCoreApplication.quit()
            return

        print(f"\n--- Lanzando ciclo {cycle} ---")
        thread = CameraThread(config, cycle)
        # Necesario: guardar referencia hasta terminar, sino el thread es recolectado antes de tiempo
        threads.append(thread)
        thread.finished_signal.connect(on_cycle_finished)
        thread.start()

    threads = []
    run_next_cycle(1)
    app.exec()

if __name__ == "__main__":
    run_camera_cycles_qt(CONFIG)