Skip to content

[BUG(test only)]: test_graphics_api_smoketest failing on headless nodes #1165

Closed

Description

@rwgk

I keep running into the error below on colossus machines.

I have a fix that I need to extract from my CTK-next work, but logging the error here first for visibility.

=================================== FAILURES ===================================
_________________________ test_graphics_api_smoketest __________________________

self = <pyglet._ModuleProxy object at 0xef3118b30b30>, name = 'Texture'

    def __getattr__(self, name: str): # noqa: ANN204
        try:
>           return getattr(self._module, name)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
E           AttributeError: 'NoneType' object has no attribute 'Texture'

../TestVenv/lib/python3.12/site-packages/pyglet/__init__.py:439: AttributeError

During handling of the above exception, another exception occurred:

    def test_graphics_api_smoketest():
        # Due to lazy importing in pyglet, pytest.importorskip doesn't work
        try:
            import pyglet

>           tex = pyglet.image.Texture.create(512, 512)
                  ^^^^^^^^^^^^^^^^^^^^

tests/test_graphics_apis.py:13:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
../TestVenv/lib/python3.12/site-packages/pyglet/__init__.py:445: in __getattr__
    __import__(import_name)
../TestVenv/lib/python3.12/site-packages/pyglet/image/__init__.py:106: in <module>
    from pyglet.gl import (
../TestVenv/lib/python3.12/site-packages/pyglet/gl/__init__.py:205: in <module>
    import pyglet.window  # noqa: F401
    ^^^^^^^^^^^^^^^^^^^^
../TestVenv/lib/python3.12/site-packages/pyglet/window/__init__.py:1904: in <module>
    gl._create_shadow_window()  # noqa: SLF001
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
../TestVenv/lib/python3.12/site-packages/pyglet/gl/__init__.py:179: in _create_shadow_window
    _shadow_window = ShadowWindow()
                     ^^^^^^^^^^^^^^
../TestVenv/lib/python3.12/site-packages/pyglet/gl/__init__.py:168: in __init__
    super().__init__(width=1, height=1, visible=False)
../TestVenv/lib/python3.12/site-packages/pyglet/window/xlib/__init__.py:167: in __init__
    super().__init__(*args, **kwargs)
../TestVenv/lib/python3.12/site-packages/pyglet/window/__init__.py:508: in __init__
    display = pyglet.display.get_display()
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
../TestVenv/lib/python3.12/site-packages/pyglet/display/__init__.py:77: in get_display
    return Display()
           ^^^^^^^^^
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _

self = <pyglet.display.xlib.XlibDisplay object at 0xef3118b35a30>, name = None
x_screen = 0

    def __init__(self, name=None, x_screen=None):
        self._screens = []

        if x_screen is None:
            x_screen = 0

        if isinstance(name, str):
            name = c_char_p(name.encode('ascii'))

        self._display = xlib.XOpenDisplay(name)
        if not self._display:
>           raise NoSuchDisplayException(f'Cannot connect to "{name}"')
E           pyglet.display.xlib.NoSuchDisplayException: Cannot connect to "None"

../TestVenv/lib/python3.12/site-packages/pyglet/display/xlib.py:102: NoSuchDisplayException
=========================== short test summary info ============================
FAILED tests/test_graphics_apis.py::test_graphics_api_smoketest - pyglet.display.xlib.NoSuchDisplayException: Cannot connect to "None"
=================== 1 failed, 222 passed in 94.29s (0:01:34) ===================

Activity

  1. self-assigned this
    on Oct 21, 2025
  2. added
    bugSomething isn't working
    cuda.bindingsEverything related to the cuda.bindings module
    on Oct 21, 2025
  3. added theissue type on Oct 21, 2025
  4. cpcloud commented on Oct 21, 2025

    @cpcloud
    Contributor

    This seems like a oneline fix with pytest:

    @pytest.mark.xfail(condition=os.environ.get("DISPLAY") is None, raises=NoSuchDisplayException)
  5. leofang commented on Oct 22, 2025

    @leofang
    Member

    Hi @pijyoi, do you know if there is a way we can run pyglet-based graphics-interop tests in a headless env (such as CI/CD)?

  6. rwgk commented on Oct 22, 2025

    @rwgk
    ContributorAuthor

    Sorry I created this issue mainly for visiblity/tracking, I have a solution already, posting it here now:

    diff --git a/cuda_bindings/tests/test_graphics_apis.py b/cuda_bindings/tests/test_graphics_apis.py
    index ae2f074..67f674b 100644
    --- a/cuda_bindings/tests/test_graphics_apis.py
    +++ b/cuda_bindings/tests/test_graphics_apis.py
    @@ -6,15 +6,15 @@ from cuda.bindings import runtime as cudart
    
    
     def test_graphics_api_smoketest():
    -    # Due to lazy importing in pyglet, pytest.importorskip doesn't work
    +    pyglet = pytest.importorskip("pyglet")
         try:
    -        import pyglet
    -
             tex = pyglet.image.Texture.create(512, 512)
    -    except (ImportError, AttributeError):
    -        pytest.skip("pyglet not available or could not create GL context")
    -        # return to make linters happy
    -        return
    +    except ImportError:
    +        pytest.skip("pyglet lazy ImportError")
    +    except AttributeError:
    +        pytest.skip("pyglet lazy import AttributeError")
    +    except pyglet.display.xlib.NoSuchDisplayException:
    +        pytest.skip("pyglet.display.xlib.NoSuchDisplayException")
    
         err, gfx_resource = cudart.cudaGraphicsGLRegisterImage(
             tex.id, tex.target, cudart.cudaGraphicsRegisterFlags.cudaGraphicsRegisterFlagsWriteDiscard

    I'm not sure if the except AttributeError is actually needed, but that fix has been working fine for me on a couple headless machines.

    I'll port it to the main branch here when I'm in calmer waters with my current main project.

  7. rwgk commented on Oct 22, 2025

    @rwgk
    ContributorAuthor

    Another patch needed for the CTK-next work:

    diff --git a/cuda_bindings/tests/test_graphics_apis.py b/cuda_bindings/tests/test_graphics_apis.py
    old mode 100644
    new mode 100755
    index 67f674b..d8bb2ee
    --- a/cuda_bindings/tests/test_graphics_apis.py
    +++ b/cuda_bindings/tests/test_graphics_apis.py
    @@ -1,6 +1,8 @@
     # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
     # SPDX-License-Identifier: LicenseRef-NVIDIA-SOFTWARE-LICENSE
    
    +import os
    +
     import pytest
     from cuda.bindings import runtime as cudart
    
    @@ -22,6 +24,8 @@ def test_graphics_api_smoketest():
         error_name = cudart.cudaGetErrorName(err)[1].decode()
         if error_name == "cudaSuccess":
             assert int(gfx_resource) != 0
    +    elif os.environ.get("DISPLAY") is None:
    +        assert error_name == "cudaErrorOperatingSystem"
         else:
             assert error_name in ("cudaErrorInvalidValue", "cudaErrorUnknown")
    
  8. pijyoi commented on Oct 23, 2025

    @pijyoi

    Adding the headless option right after importing pyglet seemed to work on Linux (but not Windows) for me.

    import pyglet
    pyglet.options['headless'] = True
    
    tex = pyglet.image.Texture.create(512, 512)
    ...

    After this, I could ssh in and cudaGraphicsGLRegisterImage would succeed.

  9. rwgk commented on Nov 4, 2025

    @rwgk
    ContributorAuthor

    xref: PR #1210

  10. rwgk commented on Nov 4, 2025

    @rwgk
    ContributorAuthor

    pyglet.options['headless'] = True

    This requires libEGL.

    I got it to work locally (PR #1210), but none of our CI runners has it available.

    Related to the work on that PR: https://chatgpt.com/share/690984da-f570-8008-b959-58d4ac0a0daf

  11. rwgk commented on Nov 7, 2025

    @rwgk
    ContributorAuthor

    @pijyoi thanks for the pyglet.options['headless'] hint, that got me on the right track!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingcuda.bindingsEverything related to the cuda.bindings module

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions