Skip to content

_py_abc Python implementation of abc is not thread-safe#130095

@colesbury

Description

@colesbury

Bug report

The update to the invalidation counter is not thread-safe and can lose updates in some Python implementations:

Failures seen on:

  • Python 3.14t
  • Python 3.9
  • pypy3.10
  • pypy3.11

But not on Python 3.10-3.14 with GIL due to limited GIL switch opportunities.

defregister(cls, subclass):
"""Register a virtual subclass of an ABC.
Returns the subclass, to allow usage as a class decorator.
"""
ifnotisinstance(subclass, type):
raiseTypeError("Can only register classes")
ifissubclass(subclass, cls):
returnsubclass# Already a subclass
# Subtle: test for cycles *after* testing for "already a subclass";
# this means we allow X.register(X) and interpret it as a no-op.
ifissubclass(cls, subclass):
# This would create a cycle, which is bad for the algorithm below
raiseRuntimeError("Refusing to create an inheritance cycle")
cls._abc_registry.add(subclass)
ABCMeta._abc_invalidation_counter+=1# Invalidate negative cache
returnsubclass

For example, consider the following repro, adapted from test_abc.test_registration_basics:

import_py_abcasabc# Use Python implementation of ABCs!!importthreadingimportosimportsyssys.setswitchinterval(1e-6) N=5defrun(b): b.wait() classA(metaclass=abc.ABCMeta): passA.register(int) ifnotisinstance(42, A): print("Oops!") os._exit(1) defmain(): for_inrange(10000): threads= [] b=threading.Barrier(N) for_inrange(N): t=threading.Thread(target=run, args=(b,)) threads.append(t) t.start() fortinthreads: t.join() if__name__=="__main__": main()

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibStandard Library Python modules in the Lib/ directorytype-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions