Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion services/xr-media-hub/xr_media_hub/ipc/_hub.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ async def _replay_roster(self) -> None:
def _handle_registration(self, reg: ConnectorRegistration) -> None:
if reg.connector_id in self._ring_registry:
logger.warning("Connector {} re-registered — replacing ring buffer", reg.connector_id)
old_ring = self._ring_registry[reg.connector_id]
old_ring = self._ring_registry.pop(reg.connector_id)
# Drop any frames still held in the old ring BEFORE closing it.
# A live SlotView keeps a sliced memoryview exported into the ring's
# mmap; closing with that outstanding makes ShmRingBuffer.close()'s
Expand Down
30 changes: 29 additions & 1 deletion tests/test_participant_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
import asyncio

import pytest
import xr_media_hub.ipc._hub as hub_module

from xr_ai_hub import ParticipantEvent, PixelFormat
from xr_ai_hub import ConnectorRegistration, ParticipantEvent, PixelFormat

pytestmark = pytest.mark.asyncio

Expand Down Expand Up @@ -160,3 +161,30 @@ async def test_connector_reregistration_releases_held_slots(hub, make_connector,
)
await settle()
assert ("alice", "cam") in hub._latest_slots


async def test_connector_reregistration_open_failure_drops_stale_ring(monkeypatch):
"""Regression for #209: a failed SHM reopen during connector
re-registration must not leave the just-closed old ring in the registry."""

class CloseTrackingRing:
def __init__(self) -> None:
self.closed = False

def close(self) -> None:
self.closed = True

def fail_open(*, name: str, create: bool):
raise RuntimeError(f"cannot open {name} create={create}")

hub = hub_module.HubEndpoint.__new__(hub_module.HubEndpoint)
old_ring = CloseTrackingRing()
hub._latest_slots = {}
hub._ring_registry = {}
hub._ring_registry["conn"] = old_ring
monkeypatch.setattr(hub_module, "ShmRingBuffer", fail_open)

hub._handle_registration(ConnectorRegistration(connector_id="conn", shm_name="missing"))

assert old_ring.closed is True
assert "conn" not in hub._ring_registry