Skip to content

BUG: Test regressions related to garbage collection on Python 3.14.0a7 #2091

Closed
@musicinmybrain

Description

@musicinmybrain

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

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