drop stale shm cache refs when cached segment size doesn't match requested shape

The cached SharedMemoryFrameManager reference can point at a segment whose
size no longer matches the requested shape — the segment was unlinked and
recreated at a different size in a camera add/remove cycle. This catches
both a resolution increase (cached too small) and a decrease (cached too
large, pointing at an orphaned inode whose stale bytes would otherwise be
misinterpreted at the new shape, producing distorted/miscolored YUV frames).

After reopening, if the OS-level segment still doesn't match the requested
shape we're in a transient mid-recreate state — either the maintainer
hasn't allocated the new segment yet (size too small) or we opened a
pre-recycle segment (size too big). Either way, skip the frame and don't
cache the mismatched ref.
This commit is contained in:
Josh Hawkins 2026-05-22 08:46:17 -05:00
parent 155699c594
commit d9dfe299a4

View File

@ -1091,11 +1091,8 @@ class SharedMemoryFrameManager(FrameManager):
try:
required = int(np.prod(shape))
shm = self.shm_store.get(name)
if shm is not None and shm.size < required:
# Cached reference points at an older, smaller segment
# that was unlinked and recreated at a larger size in a
# camera add/remove cycle. Drop the stale ref so we
# reopen the current segment.
if shm is not None and shm.size != required:
# stale cached ref from a same-name recreate — drop and reopen
try:
shm.close()
except Exception:
@ -1104,12 +1101,8 @@ class SharedMemoryFrameManager(FrameManager):
shm = None
if shm is None:
shm = UntrackedSharedMemory(name=name)
if shm.size < required:
# Transient mid-recreate state: the OS-level segment
# is still at the previous (smaller) size because the
# maintainer hasn't allocated the new one yet. Don't
# cache it (so the next call re-opens once the
# maintainer has caught up) and skip this frame.
if shm.size != required:
# mid-recreate: OS segment doesn't match shape yet; skip
try:
shm.close()
except Exception: