Description
The global Steps._stack in labgrid/step.py is a plain Python list shared across all threads. I'm hitting an AssertionError in Steps.pop() intermittently, and I believe it is caused by a race condition between threads.
I'm not sure if my usage of USBVideoDriver is the intended one — I'm running a continuous background image capture (OpenCV/GStreamer) while simultaneously calling other @step-decorated drivers from the main thread. It's possible this use case was not anticipated, and that Steps was designed assuming single-threaded usage only.
That said, if other scenarios can also trigger background threads (e.g. async callbacks, GStreamer internals), this could affect more users.
My setup
USBVideoDriver is used to capture frames continuously in a background thread (via OpenCV/GStreamer)
- While the capture is running, the main thread calls
USBSDMuxDriver.set_mode() (or any other @step-decorated method)
- Both threads end up pushing/popping on the same shared
_stack, corrupting its order
Traceback
File ".../labgrid/step.py", line 222, in wrapper
step.stop()
File ".../labgrid/step.py", line 186, in stop
steps.pop(self)
File ".../labgrid/step.py", line 29, in pop
assert self._stack[-1] is step
AssertionError
Environment
- labgrid version: 25.0.1
- Python: 3.13
- OS: Ubuntu
- Test runner: Robot Framework
Question
Is it intentional that Steps is not thread-safe? Is my usage of USBVideoDriver in a background capture thread considered unsupported?
If making _stack thread-local is acceptable, I'd be happy to submit a PR:
import threading
class Steps:
def __init__(self):
self._local = threading.local()
self._subscribers = []
@property
def _stack(self):
if not hasattr(self._local, 'stack'):
self._local.stack = []
return self._local.stack
Description
The global
Steps._stackinlabgrid/step.pyis a plain Python list shared across all threads. I'm hitting anAssertionErrorinSteps.pop()intermittently, and I believe it is caused by a race condition between threads.I'm not sure if my usage of
USBVideoDriveris the intended one — I'm running a continuous background image capture (OpenCV/GStreamer) while simultaneously calling other@step-decorated drivers from the main thread. It's possible this use case was not anticipated, and thatStepswas designed assuming single-threaded usage only.That said, if other scenarios can also trigger background threads (e.g. async callbacks, GStreamer internals), this could affect more users.
My setup
USBVideoDriveris used to capture frames continuously in a background thread (via OpenCV/GStreamer)USBSDMuxDriver.set_mode()(or any other@step-decorated method)_stack, corrupting its orderTraceback
Environment
Question
Is it intentional that
Stepsis not thread-safe? Is my usage ofUSBVideoDriverin a background capture thread considered unsupported?If making
_stackthread-local is acceptable, I'd be happy to submit a PR: