Skip to content

[BUG] Race condition writing to exttype attributes #7907

Closed

Description

@scoder

Describe the bug

Writing to object attributes of extension types uses decref before assignment, leaving the attribute value in an invalid state for a split second:

  __Pyx_GOTREF((PyObject *)__pyx_v_obj->attr);
  __Pyx_DECREF((PyObject *)__pyx_v_obj->attr);  // <- dead reference !
  __pyx_v_obj->attr = __pyx_v_value;

Code to reproduce the behaviour:

cdef class Value:
    pass

cdef class Ext:
    cdef Value attr

def update():
    x = Ext()
    value = Value()
    x.attr = value  # <-

Expected behaviour

We should use ExprNode.generate_decref_set() to generate "read-update-decref" ordering. That's still not completely safe (race condition between read and update) but avoids leaving the potentially dead reference in the attribute before updating it. Thus, concurrent updates would stay unsafe, but an update with only concurrent reads would become safe, which brings it to a reasonable and cheap level of safety that is user controllable.

OS

No response

Python version

No response

Cython version

master

Additional context

No response

Activity

  1. da-woods commented on Aug 22, 2026

    @da-woods
    Collaborator

    I think I do have a branch with this fixed in it somewhere (as part of a bigger attempted refactor of refcounting). It's probably easier just to make the individual change than to dig it out of something else specifically but I can do if useful.

    Ignoring freethreading the issue is more "arbitrary code in decref" since that can try to access the dead attribute even in the absence of threads.

    I'd claim the proposed fix doesn't hugely improve thread-safety specifically but is the right thing to do.

  2. added this to the 3.3.1 milestone on Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions