Closed
Description
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.4.0
What libzmq version?
4.3.5 (this should be the system zeromq package, but it also should not matter)
Python version (and how it was installed)
Python 3.14.4a7, installed in Fedora 41 via dnf (system RPM package)
OS
Fedora 41 (x86_64
)
What happened?
Three tests from tests/test_message.py
, related to garbage collection, fail on Python 3.14.0a7.
====================================== short test summary info =======================================
FAILED tests/test_message.py::TestFrame::test_above_30 - AssertionError: assert 2 == 1
FAILED tests/test_message.py::TestFrame::test_lifecycle1 - AssertionError: assert 2 == 1
FAILED tests/test_message.py::TestFrame::test_lifecycle2 - AssertionError: assert 2 == 1
====================== 3 failed, 353 passed, 32 skipped, 411 warnings in 36.50s ======================
Code to reproduce bug
$ python3.14 --version
Python 3.14.0a7
$ python3.14 -m venv _e
$ . _e/bin/activate
(_e) $ pip install -e .
(_e) $ pip install -r test-requirements.txt
(_e) $ pytest
Traceback, if applicable
============================================== FAILURES ==============================================
______________________________________ TestFrame.test_above_30 _______________________________________
self = <tests.test_message.TestFrame testMethod=test_above_30>
@skip_pypy
def test_above_30(self):
"""Message above 30 bytes are never copied by 0MQ."""
for i in range(5, 16): # 32, 64,..., 65536
s = (2**i) * x
rc = grc(s)
m = zmq.Frame(s, copy=False)
assert grc(s) == rc + 2
del m
await_gc(s, rc)
> assert grc(s) == rc
E AssertionError: assert 2 == 1
E + where 2 = grc(b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
tests/test_message.py:67: AssertionError
_____________________________________ TestFrame.test_lifecycle1 ______________________________________
self = <tests.test_message.TestFrame testMethod=test_lifecycle1>
@skip_pypy
def test_lifecycle1(self):
"""Run through a ref counting cycle with a copy."""
for i in range(5, 16): # 32, 64,..., 65536
s = (2**i) * x
rc = rc_0 = grc(s)
m = zmq.Frame(s, copy=False)
rc += 2
assert grc(s) == rc
m2 = copy.copy(m)
rc += 1
assert grc(s) == rc
# no increase in refcount for accessing buffer
# which references m2 directly
buf = m2.buffer
assert grc(s) == rc
assert s == bytes(m2)
assert s == m.bytes
assert s == bytes(buf)
del m2
assert grc(s) == rc
# buf holds direct reference to m2 which holds
del buf
rc -= 1
assert grc(s) == rc
del m
rc -= 2
await_gc(s, rc)
> assert grc(s) == rc
E AssertionError: assert 2 == 1
E + where 2 = grc(b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
tests/test_message.py:141: AssertionError
_____________________________________ TestFrame.test_lifecycle2 ______________________________________
self = <tests.test_message.TestFrame testMethod=test_lifecycle2>
@skip_pypy
def test_lifecycle2(self):
"""Run through a different ref counting cycle with a copy."""
for i in range(5, 16): # 32, 64,..., 65536
s = (2**i) * x
rc = rc_0 = grc(s)
m = zmq.Frame(s, copy=False)
rc += 2
assert grc(s) == rc
m2 = copy.copy(m)
rc += 1
assert grc(s) == rc
# no increase in refcount for accessing buffer
# which references m directly
buf = m.buffer
assert grc(s) == rc
assert s == bytes(m2)
assert s == m2.bytes
assert s == m.bytes
assert s == bytes(buf)
del buf
assert grc(s) == rc
del m
rc -= 1
assert grc(s) == rc
del m2
rc -= 2
await_gc(s, rc)
> assert grc(s) == rc
E AssertionError: assert 2 == 1
E + where 2 = grc(b'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx')
tests/test_message.py:173: AssertionError
More info
I originally observed this with the 26.4.0 release, but I also reproduced it on the current main
branch, 27abf26. I am working on Fedora 41, x86_64
, but I do not believe this issue should not be specific to a particular OS or distribution.
Metadata
Metadata
Assignees
Labels
No labels