New holoscan based camera streamer sample app#187
Conversation
There was a problem hiding this comment.
Actionable comments posted: 1
♻️ Duplicate comments (1)
examples/camera_streamer/teleop_camera_app.py (1)
181-183:⚠️ Potential issue | 🟡 Minor
os._exit(0)is still hardcoded without issue reference or escape hatch.Line 183 bypasses normal Python shutdown unconditionally. If this is required, please document the exact Holoscan/GXF issue and gate hard-exit behind a flag for safer maintenance.
Minimal guard pattern
logger.info("Shutdown complete") - # Required to avoid GIL crash. - os._exit(0) + # Required to avoid GIL crash during Holoscan/GXF cleanup. + # Reference: <issue/PR/internal-tracker-id> + if os.getenv("TELEOP_FORCE_HARD_EXIT", "1") == "1": + os._exit(0) + sys.exit(0)#!/bin/bash rg -n 'os\._exit|GIL crash|TELEOP_FORCE_HARD_EXIT|sys\.exit' examples/camera_streamer/teleop_camera_app.py🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@examples/camera_streamer/teleop_camera_app.py` around lines 181 - 183, The unconditional call to os._exit(0) in teleop_camera_app.py bypasses normal shutdown and should be guarded and documented: replace the hard exit with a conditional hard-exit controlled by a flag (e.g. TELEOP_FORCE_HARD_EXIT env var or a command-line/Config option) and add a comment referencing the specific Holoscan/GXF GIL crash issue number or external link; update the shutdown sequence around logger.info("Shutdown complete") to call os._exit(0) only when the flag is set and otherwise allow normal exit (sys.exit or return), and add a brief docstring or inline comment in the module explaining why the hard exit is needed and how to disable it for debugging/maintenance.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@examples/camera_streamer/teleop_camera_app.py`:
- Around line 162-176: Replace the brittle substring check around
TeleopCameraApp.run by factoring the retry logic into a helper (e.g.,
is_xr_retryable_exception) that first inspects exception.__cause__ for typed
underlying errors and, if absent, matches against a narrowly defined, documented
regex anchored to Holoscan's documented XR error message format (instead of
loose substrings like _XR_RETRY_ERRORS); update the while loop to call this
helper before deciding to retry or re-raise and add a short comment documenting
the exact message pattern or contract expected from Holoscan so future changes
are obvious.
---
Duplicate comments:
In `@examples/camera_streamer/teleop_camera_app.py`:
- Around line 181-183: The unconditional call to os._exit(0) in
teleop_camera_app.py bypasses normal shutdown and should be guarded and
documented: replace the hard exit with a conditional hard-exit controlled by a
flag (e.g. TELEOP_FORCE_HARD_EXIT env var or a command-line/Config option) and
add a comment referencing the specific Holoscan/GXF GIL crash issue number or
external link; update the shutdown sequence around logger.info("Shutdown
complete") to call os._exit(0) only when the flag is set and otherwise allow
normal exit (sys.exit or return), and add a brief docstring or inline comment in
the module explaining why the hard exit is needed and how to disable it for
debugging/maintenance.
| _XR_RETRY_ERRORS = ("ErrorFormFactorUnavailable", "ErrorLimitReached") | ||
| while True: | ||
| app = TeleopCameraApp(config) | ||
| try: | ||
| app.run() | ||
| break | ||
| except KeyboardInterrupt: | ||
| logger.info("Interrupted by user") | ||
| break | ||
| except Exception as e: | ||
| msg = str(e) | ||
| if not any(err in msg for err in _XR_RETRY_ERRORS): | ||
| logger.error(f"Error: {e}") | ||
| raise | ||
| logger.warning(f"No XR headset connected, retrying in 2s... ({msg})") |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
# First, let's examine the actual file to confirm the code snippet
cat -n examples/camera_streamer/teleop_camera_app.py | sed -n '160,180p'Repository: NVIDIA/IsaacTeleop
Length of output: 894
🌐 Web query:
Holoscan OpenXR exception types error codes headset unavailable
💡 Result:
In Holoscan apps that use OpenXR, “headset unavailable / no headset” conditions usually show up as OpenXR XrResult error codes (Holoscan may surface these as a thrown exception or a logged failure that contains the XrResult value).
Error codes most associated with “headset unavailable”
XR_ERROR_FORM_FACTOR_UNAVAILABLE: The runtime supports the requested form factor (typicallyXR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY) but the device is not currently available (e.g., not connected, not powered on, not recognized by the runtime). This is the closest match to “headset unavailable.” [1]XR_ERROR_RUNTIME_UNAVAILABLE: The OpenXR loader can’t find or load any active runtime (i.e., no OpenXR runtime is set/installed correctly), so even creating an instance / enumerating properties can fail. [2]- Related/secondary codes you might also see
XR_ERROR_INITIALIZATION_FAILED: runtime/object initialization failed (can happen if the runtime is present but can’t initialize the headset). [1]XR_ERROR_INSTANCE_LOST/XR_ERROR_SESSION_LOST: runtime/session became unavailable after being created (e.g., runtime crash, device reset/disconnect). [1]
What to check/fix (common causes)
- Ensure an OpenXR runtime is actually set as active (Windows uses the OpenXR loader + an “active runtime” selection). For example, set Meta Quest Link or SteamVR as the active OpenXR runtime (and confirm the active runtime registry entry points to the runtime JSON). [3]
- Make sure the headset is connected and recognized by that runtime (power, cable/link, SteamVR/WMR portal running, etc.). If the runtime can’t see an HMD,
xrGetSystemcommonly returnsXR_ERROR_FORM_FACTOR_UNAVAILABLE. [1] - Platform mismatch example (HoloLens): plugging a HoloLens into a PC won’t make it appear as a PC “WMR headset”; OpenXR tools/runtime need to be installed/used on-device for HoloLens scenarios—otherwise you can hit
XR_ERROR_FORM_FACTOR_UNAVAILABLEwhen callingxrGetSystem. [4]
Sources:
[1] OpenXR spec: XrResult codes (incl. XR_ERROR_FORM_FACTOR_UNAVAILABLE) https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrResult.html
[2] OpenXR SDK changelog (introduces/clarifies XR_ERROR_RUNTIME_UNAVAILABLE) https://chromium.googlesource.com/external/github.com/KhronosGroup/OpenXR-SDK/%2B/458984d7f59d1ae6dc1b597d94b02e4f7132eaba/CHANGELOG.SDK.md
[3] Example troubleshooting: set the active OpenXR runtime (Meta/SteamVR + registry path) https://helpdesk.halocline.io/hc/en-us/articles/4652065185425-No-headset-found-OpenXR-Runtime
[4] HoloLens-specific explanation for XR_ERROR_FORM_FACTOR_UNAVAILABLE on PC tools https://stackoverflow.com/questions/70469006/how-to-setup-the-hololens2-with-the-mixedreality
🏁 Script executed:
# Search for any exception handling or error type references in the codebase
rg "ErrorFormFactorUnavailable|ErrorLimitReached" --type py -B 2 -A 2Repository: NVIDIA/IsaacTeleop
Length of output: 483
🏁 Script executed:
# Look for OpenXR related exception definitions or imports
rg "import.*xr|from.*xr" examples/camera_streamer/teleop_camera_app.py -iRepository: NVIDIA/IsaacTeleop
Length of output: 101
🏁 Script executed:
# Find where TeleopCameraApp is defined and how it uses xr module
fd -t f "\.py$" | xargs rg "class TeleopCameraApp" -lRepository: NVIDIA/IsaacTeleop
Length of output: 107
🏁 Script executed:
# Look for exception definitions or error handling in holohub related code
rg "ErrorFormFactorUnavailable|ErrorLimitReached" --type py -B 5 -A 5Repository: NVIDIA/IsaacTeleop
Length of output: 939
🏁 Script executed:
# Check if there are actual exception classes defined or if these are message patterns
rg "class.*Error.*:" examples/ --type pyRepository: NVIDIA/IsaacTeleop
Length of output: 44
🏁 Script executed:
# Look for any exception handling that shows what type of exception is being caught
rg "except.*Error|raise.*Error" examples/camera_streamer/teleop_camera_app.py -B 2 -A 2Repository: NVIDIA/IsaacTeleop
Length of output: 231
🌐 Web query:
holohub.xr exception error classes Python Holoscan
💡 Result:
In HoloHub’s XR (OpenXR) operators, there isn’t a dedicated, documented Python exception hierarchy like holohub.xr.SomeError. The XR components are implemented in C++ (XrSession, XrBeginFrameOp, XrEndFrameOp, swapchain/layer helpers, etc.) and exposed to Python via bindings, so failures typically surface in Python as a standard RuntimeError raised from the underlying Holoscan C++ error system. [1]
Holoscan’s core runtime exception type on the C++ side is holoscan::RuntimeError (derived from std::runtime_error) and it carries a Holoscan ErrorCode; when propagated through the Python bindings this is generally observed as Python RuntimeError. [2]
Practical takeaway (Python):
- Catch XR-related failures with
except RuntimeError as e: ...(and logstr(e)), rather than looking forholohub.xr.*Errorclasses. [1] [2]
Sources:
[1] HoloHub XR operators overview (OpenXR operators / XrSession / frame ops) https://raw.githubusercontent.com/nvidia-holoscan/holohub/main/operators/xr/README.md
[2] Holoscan C++ holoscan::RuntimeError documentation https://docs.nvidia.com/holoscan/archive/2.2.0/api/cpp/classholoscan_1_1runtimeerror.html
Retry detection via exception message substrings is fragile.
Line 173 classifies retryable XR failures using substring checks on str(e). This approach is brittle because exception message formatting can change between dependency versions. Since Holohub's XR operators raise standard RuntimeError from C++ bindings (rather than custom exception classes), the current code depends on stable message content.
Note: The suggested diff won't work as-is—it assumes exception classes named ErrorFormFactorUnavailable exist, but Holoscan surfaces XR errors as RuntimeError with embedded message patterns. A fix should either:
- Validate against Holoscan's documented error message format and handle changes explicitly, or
- Check
__cause__chains if the underlying error code is propagated as a typed exception, or - Document the specific expected message format as a contract with Holoscan versions
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@examples/camera_streamer/teleop_camera_app.py` around lines 162 - 176,
Replace the brittle substring check around TeleopCameraApp.run by factoring the
retry logic into a helper (e.g., is_xr_retryable_exception) that first inspects
exception.__cause__ for typed underlying errors and, if absent, matches against
a narrowly defined, documented regex anchored to Holoscan's documented XR error
message format (instead of loose substrings like _XR_RETRY_ERRORS); update the
while loop to call this helper before deciding to retry or re-raise and add a
short comment documenting the exact message pattern or contract expected from
Holoscan so future changes are obvious.
Adds the new holoscan based camera streamer with its own dockerfile and scripts.
~6.5K lines of code, mostly reviewed as part of GEAR initial version.
Diffs:
Summary by CodeRabbit
New Features
Documentation
Chores