Skip to content

Commit 6381813

Browse files
committed
fix: race condition
1 parent 14180b8 commit 6381813

File tree

2 files changed

+16
-9
lines changed

2 files changed

+16
-9
lines changed

src/arduino/app_peripherals/camera/examples/6_capture_websocket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from arduino.app_peripherals.camera import Camera
99

1010

11-
# Expose a WebSocket camera stream for clients to connect to and consume it
11+
# Expose a WebSocket camera stream for clients to connect to
1212
camera = Camera("ws://0.0.0.0:8080", timeout=5)
1313
camera.start()
1414

src/arduino/app_peripherals/camera/websocket_camera.py

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import cv2
1313
import websockets
1414
import asyncio
15+
from concurrent.futures import CancelledError, TimeoutError
1516

1617
from arduino.app_utils import Logger
1718

@@ -26,7 +27,9 @@ class WebSocketCamera(BaseCamera):
2627
WebSocket Camera implementation that hosts a WebSocket server.
2728
2829
This camera acts as a WebSocket server that receives frames from connected clients.
29-
Clients can send frames in various formats:
30+
Only one client can be connected at a time.
31+
32+
Clients can send frames in various 8-bit (e.g. JPEG, PNG 8-bit) formats:
3033
- Base64 encoded images
3134
- JSON messages with image data
3235
- Binary image data
@@ -252,6 +255,10 @@ def _close_camera(self):
252255
)
253256
try:
254257
future.result(timeout=1.0)
258+
except CancelledError as e:
259+
logger.debug(f"Error setting async stop event: CancelledError")
260+
except TimeoutError as e:
261+
logger.debug(f"Error setting async stop event: TimeoutError")
255262
except Exception as e:
256263
logger.warning(f"Error setting async stop event: {e}")
257264

@@ -260,11 +267,11 @@ def _close_camera(self):
260267
self._server_thread.join(timeout=10.0)
261268

262269
# Clear frame queue
263-
while not self._frame_queue.empty():
264-
try:
270+
try:
271+
while True:
265272
self._frame_queue.get_nowait()
266-
except queue.Empty:
267-
break
273+
except queue.Empty:
274+
pass
268275

269276
# Reset state
270277
self._server = None
@@ -273,8 +280,6 @@ def _close_camera(self):
273280

274281
async def _set_async_stop_event(self):
275282
"""Set the async stop event and close the client connection."""
276-
self._stop_event.set()
277-
278283
# Send goodbye message and close the client connection
279284
if self._client:
280285
try:
@@ -285,9 +290,11 @@ async def _set_async_stop_event(self):
285290
})
286291
# Give a brief moment for the message to be sent
287292
await asyncio.sleep(0.1)
288-
await self._client.close()
289293
except Exception as e:
290294
logger.warning(f"Error closing client in stop event: {e}")
295+
finally:
296+
await self._client.close()
297+
self._stop_event.set()
291298

292299
def _read_frame(self) -> Optional[np.ndarray]:
293300
"""Read a frame from the queue."""

0 commit comments

Comments
 (0)