Skip to content

BUG: test_shadow_socket_close fails randomly on aarch64-linux #2161

@steveej

Description

@steveej

This is a pyzmq bug

  • This is a pyzmq-specific bug, not an issue of zmq socket behavior. Don't worry if you're not sure! We'll figure it out together.

What pyzmq version?

26.3.0

What libzmq version?

unknown

Python version (and how it was installed)

python3-3.12.11 via Nix

OS

Nix on Linux

What happened?

I saw this failure on CI on an aarch64-linux test job which has a dependency on pyzmq.
Nix runs the upstream tests as parts of the package's check phase(s).
On a retry the job succeeded without any input changes.

Code to reproduce bug

Failed as part of the test suite:


       > Executing pytestCheckPhase
       > pytest flags: -m pytest -k not\ \(test_socket\)\ and\ not\ \(test_monitor\)\ and\ not\ \(test_cython\)\ and\ not\ \(test_mockable\)\ and\ not\ \(TestFutureSocket\)\ and\ not\ \(TestIOLoop\)\ and\ not\ \(TestPubLog\) -m not\ flaky
       > ============================= test session starts ==============================
       > platform linux -- Python 3.12.11, pytest-8.3.5, pluggy-1.5.0

Traceback, if applicable

failed: Cannot build '/nix/store/7frhlw3pcf9ld2pbpkw9hqyishkkid6w-python3.12-pyzmq-26.3.0.drv'.
       Reason: builder failed with exit code 1.
       Output paths:
         /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0
         /nix/store/fhz8wd6g4rw96jzqgbvc1ld1md0fz67k-python3.12-pyzmq-26.3.0-dist
error: builder for '/nix/store/7frhlw3pcf9ld2pbpkw9hqyishkkid6w-python3.12-pyzmq-26.3.0.drv' failed with exit code 1;
       last 229 log lines:
       > [nixbuild.net] Build 7055875 queued at 26-03-03 20:37:44Z. Allocated 1 CPU, 0.9 GB memory.
       > Sourcing python-remove-tests-dir-hook
       > Sourcing python-catch-conflicts-hook.sh
       > Sourcing python-remove-bin-bytecode-hook.sh
       > Sourcing pypa-build-hook
       > Using pypaBuildPhase
       > Sourcing python-runtime-deps-check-hook
       > Using pythonRuntimeDepsCheckHook
       > Sourcing pypa-install-hook
       > Using pypaInstallPhase
       > Sourcing python-imports-check-hook.sh
       > Using pythonImportsCheckPhase
       > Sourcing python-namespaces-hook
       > Sourcing python-catch-conflicts-hook.sh
       > Sourcing pytest-check-hook
       > Using pytestCheckPhase
       > Running phase: unpackPhase
       > unpacking source archive /nix/store/lk0f22l89v66gqg79b05baxf238hx6kd-pyzmq-26.3.0.tar.gz
       > source root is pyzmq-26.3.0
       > setting SOURCE_DATE_EPOCH to timestamp 1667997441 of file "pyzmq-26.3.0/zmqversion.py"
       > Running phase: patchPhase
       > Running phase: updateAutotoolsGnuConfigScriptsPhase
       > Running phase: configurePhase
       > no configure script, doing nothing
       > Running phase: buildPhase
       > Executing pypaBuildPhase
       > Creating a wheel...
       > pypa build flags: --no-isolation --outdir dist/ --wheel
       > * Getting build dependencies for wheel...
       > * Building wheel...
       > *** scikit-build-core 0.11.1 using CMake 3.31.6 (wheel)
       > *** Configuring CMake...
       > loading initial cache file /build/tmp7fm7dw1a/build/CMakeInit.txt
       > -- The C compiler identification is GNU 14.3.0
       > -- The CXX compiler identification is GNU 14.3.0
       > -- Detecting C compiler ABI info
       > -- Detecting C compiler ABI info - done
       > -- Check for working C compiler: /nix/store/gv6bdp4sk318jhvyfxng4icxfn10s76c-gcc-wrapper-14.3.0/bin/gcc - skipped
       > -- Detecting C compile features
       > -- Detecting C compile features - done
       > -- Detecting CXX compiler ABI info
       > -- Detecting CXX compiler ABI info - done
       > -- Check for working CXX compiler: /nix/store/gv6bdp4sk318jhvyfxng4icxfn10s76c-gcc-wrapper-14.3.0/bin/g++ - skipped
       > -- Detecting CXX compile features
       > -- Detecting CXX compile features - done
       > -- Found Python: /nix/store/16x768g8b0f38jxkrswyxjcj8x5msf84-python3-3.12.11/bin/python3.12 (found version "3.12.11") found components: Interpreter Development.Module
       > -- Looking for libzmq
       > -- Looking for libzmq - Found with cmake: _ZMQ_LOCATION-NOTFOUND
       > -- Using Python Python /nix/store/16x768g8b0f38jxkrswyxjcj8x5msf84-python3-3.12.11/bin/python3.12
       > -- Building Cython backend
       > -- Linking libzmq target libzmq
       > -- Configuring done (1.6s)
       > -- Generating done (0.1s)
       > -- Build files have been written to: /build/tmp7fm7dw1a/build
       > *** Building project with Ninja...
       > [2/3] Building C object CMakeFiles/_zmq.dir/_src/_zmq.c.o
       > In function ‘__Pyx_ssize_strlen’,
       >     inlined from ‘__pyx_pf_3zmq_7backend_6cython_4_zmq_5Frame_10get’ at /build/tmp7fm7dw1a/build/_src/_zmq.c:9097:17,
       >     inlined from ‘__pyx_pw_3zmq_7backend_6cython_4_zmq_5Frame_11get’ at /build/tmp7fm7dw1a/build/_src/_zmq.c:8866:13:
       > /build/tmp7fm7dw1a/build/_src/_zmq.c:35825:18: warning: argument 1 null where non-null expected [-Wnonnull]
       > 35825 |     size_t len = strlen(s);
       >       |                  ^~~~~~~~~
       > In file included from /nix/store/16x768g8b0f38jxkrswyxjcj8x5msf84-python3-3.12.11/include/python3.12/Python.h:26,
       >                  from /build/tmp7fm7dw1a/build/_src/_zmq.c:16:
       > /nix/store/sh3sjmgq543lfpjsq3dc0ksb6ckvhpdi-glibc-2.40-66-dev/include/string.h: In function ‘__pyx_pw_3zmq_7backend_6cython_4_zmq_5Frame_11get’:
       > /nix/store/sh3sjmgq543lfpjsq3dc0ksb6ckvhpdi-glibc-2.40-66-dev/include/string.h:407:15: note: in a call to function ‘strlen’ declared ‘nonnull’
       >   407 | extern size_t strlen (const char *__s)
       >       |               ^~~~~~
       > [3/3] Linking C shared module _zmq.cpython-312-aarch64-linux-gnu.so
       > *** Installing project into wheel...
       > -- Install configuration: "Release"
       > -- Installing: /build/tmp7fm7dw1a/wheel/platlib/zmq/backend/cython/_zmq.cpython-312-aarch64-linux-gnu.so
       > *** Making wheel...
       > *** Created pyzmq-26.3.0-cp312-cp312-linux_aarch64.whl
       > Successfully built pyzmq-26.3.0-cp312-cp312-linux_aarch64.whl
       > Finished creating a wheel...
       > Finished executing pypaBuildPhase
       > Running phase: pythonRuntimeDepsCheckHook
       > Executing pythonRuntimeDepsCheck
       > Checking runtime dependencies for pyzmq-26.3.0-cp312-cp312-linux_aarch64.whl
       > Finished executing pythonRuntimeDepsCheck
       > Running phase: installPhase
       > Executing pypaInstallPhase
       > Successfully installed pyzmq-26.3.0-cp312-cp312-linux_aarch64.whl
       > Finished executing pypaInstallPhase
       > Running phase: pythonOutputDistPhase
       > Executing pythonOutputDistPhase
       > Finished executing pythonOutputDistPhase
       > Running phase: fixupPhase
       > shrinking RPATHs of ELF executables and libraries in /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0
       > shrinking /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0/lib/python3.12/site-packages/zmq/backend/cython/_zmq.cpython-312-aarch64-linux-gnu.so
       > checking for references to /build/ in /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0...
       > patching script interpreter paths in /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0
       > stripping (with command strip and flags -S -p) in  /nix/store/8dpvqr0fi84cwbwng7bzs9m8laxkxjdj-python3.12-pyzmq-26.3.0/lib
       > shrinking RPATHs of ELF executables and libraries in /nix/store/fhz8wd6g4rw96jzqgbvc1ld1md0fz67k-python3.12-pyzmq-26.3.0-dist
       > checking for references to /build/ in /nix/store/fhz8wd6g4rw96jzqgbvc1ld1md0fz67k-python3.12-pyzmq-26.3.0-dist...
       > patching script interpreter paths in /nix/store/fhz8wd6g4rw96jzqgbvc1ld1md0fz67k-python3.12-pyzmq-26.3.0-dist
       > Executing pythonRemoveTestsDir
       > Finished executing pythonRemoveTestsDir
       > Running phase: installCheckPhase
       > no Makefile or custom installCheckPhase, doing nothing
       > Running phase: pythonCatchConflictsPhase
       > Running phase: pythonRemoveBinBytecodePhase
       > Running phase: pythonImportsCheckPhase
       > Executing pythonImportsCheckPhase
       > Check whether the following modules can be imported: zmq
       > Running phase: pytestCheckPhase
       > Executing pytestCheckPhase
       > pytest flags: -m pytest -k not\ \(test_socket\)\ and\ not\ \(test_monitor\)\ and\ not\ \(test_cython\)\ and\ not\ \(test_mockable\)\ and\ not\ \(TestFutureSocket\)\ and\ not\ \(TestIOLoop\)\ and\ not\ \(TestPubLog\) -m not\ flaky
       > ============================= test session starts ==============================
       > platform linux -- Python 3.12.11, pytest-8.3.5, pluggy-1.5.0
       > rootdir: /build/pyzmq-26.3.0
       > configfile: pytest.ini
       > testpaths: tests
       > plugins: asyncio-0.26.0
       > asyncio: mode=Mode.AUTO, asyncio_default_fixture_loop_scope=function, asyncio_default_test_loop_scope=function
       > collected 364 items / 84 deselected / 1 skipped / 280 selected
       > tests/test_asyncio.py ......................                             [  7%]
       > tests/test_auth.py ...............................                       [ 18%]
       > tests/test_cffi_backend.py ssssssssssssss                                [ 23%]
       > tests/test_constants.py .........................................        [ 38%]
       > tests/test_context.py ...................s.....                          [ 47%]
       > tests/test_decorators.py ...........................                     [ 57%]
       > tests/test_device.py ........                                            [ 60%]
       > tests/test_draft.py ss                                                   [ 60%]
       > tests/test_error.py ...                                                  [ 61%]
       > tests/test_etc.py .ss                                                    [ 62%]
       > tests/test_ext.py .                                                      [ 63%]
       > tests/test_imports.py ..........s.s.s.s.s.s.s                            [ 71%]
       > tests/test_includes.py ..                                                [ 72%]
       > tests/test_ioloop.py ..                                                  [ 72%]
       > tests/test_message.py ...s................                               [ 80%]
       > tests/test_monqueue.py ......                                            [ 82%]
       > tests/test_multipart.py ..                                               [ 82%]
       > tests/test_pair.py ....                                                  [ 84%]
       > tests/test_poll.py ......                                                [ 86%]
       > tests/test_proxy_steerable.py sss                                        [ 87%]
       > tests/test_pubsub.py ..                                                  [ 88%]
       > tests/test_reqrep.py ......                                              [ 90%]
       > tests/test_retry_eintr.py s..s.                                          [ 92%]
       > tests/test_security.py .....                                             [ 93%]
       > tests/test_ssh.py .                                                      [ 94%]
       > tests/test_version.py ....                                               [ 95%]
       > tests/test_win32_shim.py s                                               [ 96%]
       > tests/test_z85.py ....                                                   [ 97%]
       > tests/test_zmqstream.py ......F                                          [100%]
       > =================================== FAILURES ===================================
       > ___________________________ test_shadow_socket_close ___________________________
       > context = <zmq.Context() at 0xfffff4da24b0>
       > caplog = <_pytest.logging.LogCaptureFixture object at 0xfffff4cf62d0>
       >     async def test_shadow_socket_close(context, caplog):
       >         with context.socket(zmq.PUSH) as push, context.socket(zmq.PULL) as pull:
       >             push.linger = pull.linger = 0
       >             port = push.bind_to_random_port('tcp://127.0.0.1')
       >             pull.connect(f'tcp://127.0.0.1:{port}')
       >             shadow_pull = zmq.Socket.shadow(pull)
       >             stream = zmqstream.ZMQStream(shadow_pull)
       >             # send some messages
       >             for i in range(10):
       >                 push.send_string(str(i))
       >             # make sure at least one message has been delivered
       >             pull.recv()
       >             # register callback
       >             # this should schedule event callback on the next tick
       >             stream.on_recv(print)
       >             # close the shadowed socket
       >             pull.close()
       >         # run the event loop, which should see some events on the shadow socket
       >         # but the socket has been closed!
       >         with warnings.catch_warnings(record=True) as records:
       >             await asyncio.sleep(0.2)
       >         warning_text = "\n".join(str(r.message) for r in records)
       > >       assert "after closing socket" in warning_text
       > E       AssertionError: assert 'after closing socket' in ''
       > tests/test_zmqstream.py:158: AssertionError
       > =============================== warnings summary ===============================
       > ../../nix/store/17ay4xaxf0b2xpdyhvrhw674qi0hfjfm-python3.12-pytest-asyncio-0.26.0/lib/python3.12/site-packages/pytest_asyncio/plugin.py:272
       >   /nix/store/17ay4xaxf0b2xpdyhvrhw674qi0hfjfm-python3.12-pytest-asyncio-0.26.0/lib/python3.12/site-packages/pytest_asyncio/plugin.py:272: PytestDeprecationWarning: io_loop is asynchronous and explicitly requests the "event_loop" fixture. Asynchronous fixtures and test functions should use "asyncio.get_running_loop()" instead.
       >     warnings.warn(
       > ../../nix/store/17ay4xaxf0b2xpdyhvrhw674qi0hfjfm-python3.12-pytest-asyncio-0.26.0/lib/python3.12/site-packages/pytest_asyncio/plugin.py:272
       >   /nix/store/17ay4xaxf0b2xpdyhvrhw674qi0hfjfm-python3.12-pytest-asyncio-0.26.0/lib/python3.12/site-packages/pytest_asyncio/plugin.py:272: PytestDeprecationWarning: _async_setup is asynchronous and explicitly requests the "event_loop" fixture. Asynchronous fixtures and test functions should use "asyncio.get_running_loop()" instead.
       >     warnings.warn(
       > tests/test_auth.py:410
       >   tests/test_auth.py:410: PytestDeprecationWarning: test_ioloop_authenticator is asynchronous and explicitly requests the "event_loop" fixture. Asynchronous fixtures and test functions should use "asyncio.get_running_loop()" instead.
       >     async def test_ioloop_authenticator(context, event_loop, io_loop):
       > tests/test_poll.py:159
       >   /build/pyzmq-26.3.0/tests/test_poll.py:159: PytestUnknownMarkWarning: Unknown pytest.mark.flaky - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
       >     @mark.flaky(reruns=3)
       > tests/test_poll.py:194
       >   /build/pyzmq-26.3.0/tests/test_poll.py:194: PytestUnknownMarkWarning: Unknown pytest.mark.flaky - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
       >     @mark.flaky(reruns=3)
       > tests/test_retry_eintr.py:60
       >   /build/pyzmq-26.3.0/tests/test_retry_eintr.py:60: PytestUnknownMarkWarning: Unknown pytest.mark.flaky - is this a typo?  You can register custom marks to avoid this warning - for details, see https://docs.pytest.org/en/stable/how-to/mark.html
       >     @mark.flaky(reruns=3)
       > tests/test_asyncio.py: 20 warnings
       > tests/test_auth.py: 31 warnings
       > tests/test_zmqstream.py: 7 warnings
       >   /nix/store/17ay4xaxf0b2xpdyhvrhw674qi0hfjfm-python3.12-pytest-asyncio-0.26.0/lib/python3.12/site-packages/pytest_asyncio/plugin.py:884: DeprecationWarning: The event_loop fixture provided by pytest-asyncio has been redefined in
       >   /build/pyzmq-26.3.0/tests/conftest.py:73
       >   Replacing the event_loop fixture with a custom implementation is deprecated
       >   and will lead to errors in the future.
       >   If you want to request an asyncio event loop with a scope other than function
       >   scope, use the "loop_scope" argument to the asyncio mark when marking the tests.
       >   If you want to return different types of event loops, use the event_loop_policy
       >   fixture.
       >
       >     warnings.warn(
       > tests/test_auth.py::test_ioloop_authenticator
       >   /build/pyzmq-26.3.0/tests/test_auth.py:414: DeprecationWarning: zmq.auth.ioloop.IOLoopAuthenticator is deprecated. Use zmq.auth.asyncio.AsyncioAuthenticator
       >     from zmq.auth.ioloop import IOLoopAuthenticator
       > tests/test_imports.py::test_eventloop
       >   /build/pyzmq-26.3.0/tests/test_imports.py:52: DeprecationWarning: zmq.eventloop.ioloop is deprecated in pyzmq 17. pyzmq now works with default tornado and asyncio eventloops.
       >     from zmq.eventloop import ioloop, zmqstream
       > -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
       > ============================= slowest 10 durations =============================
       > 1.25s call     tests/test_poll.py::TestPoll::test_reqrep
       > 1.20s call     tests/test_monqueue.py::TestMonitoredQueue::test_router_router
       > 1.01s call     tests/test_asyncio.py::test_process_teardown
       > 1.00s call     tests/test_monqueue.py::TestMonitoredQueue::test_prefix
       > 1.00s call     tests/test_context.py::TestContext::test_instance_threadsafe
       > 0.70s call     tests/test_security.py::TestSecurity::test_curve
       > 0.70s call     tests/test_device.py::TestDevice::test_single_socket_forwarder_bind
       > 0.70s call     tests/test_device.py::TestDevice::test_single_socket_forwarder_connect
       > 0.70s call     tests/test_security.py::TestSecurity::test_plain
       > 0.60s call     tests/test_monqueue.py::TestMonitoredQueue::test_queue
       > =========================== short test summary info ============================
       > FAILED tests/test_zmqstream.py::test_shadow_socket_close - AssertionError: assert 'after closing socket' in ''
       > ==== 1 failed, 246 passed, 34 skipped, 84 deselected, 66 warnings in 23.67s ====

More info

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions