Skip to content

enum_next and pairwise_next can result in tuple elements with zero reference count in free-threading build #121464

Open
@eendebakpt

Description

@eendebakpt

Bug report

Bug description:

The enumerate object (and also the itertools.pairwise since #118219) re-uses tuples when possible. It does this by checking the reference count to be 1:

   // from enum_next in enumobject.c
    if (Py_REFCNT(result) == 1) {
        Py_INCREF(result);
        old_index = PyTuple_GET_ITEM(result, 0);
        old_item = PyTuple_GET_ITEM(result, 1);
        PyTuple_SET_ITEM(result, 0, next_index);
        PyTuple_SET_ITEM(result, 1, next_item);
        Py_DECREF(old_index);
        Py_DECREF(old_item);
        ....

The refcount check and increment are not atomic, so in the free-threading build multiple threads can end up operating on the result object. It is possible that one thread already sets an item in the tuple, and another thread decrefs the item believing it is still an old item.

In the nogil reference implementation (https://github.com/colesbury/nogil) no changes are made to address this. So maybe the issue cannot occur?

In #120591 this problem is addressed with a lock, which might be too much overhead (see the discussion in #120496)

@colesbury @hauntsaninja

CPython versions tested on:

CPython main branch

Operating systems tested on:

Windows

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions