This is a pyzmq bug
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
This is a pyzmq bug
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
Traceback, if applicable
More info
No response