gh-116909: fix data race with versions in typeobject by duaneg · Pull Request #134651 · python/cpython · GitHub
Skip to content

gh-116909: fix data race with versions in typeobject - #134651

Closed
duaneg wants to merge 5 commits into
python:mainfrom
duaneg:gh-116909
Closed

gh-116909: fix data race with versions in typeobject#134651
duaneg wants to merge 5 commits into
python:mainfrom
duaneg:gh-116909

Conversation

@duaneg

@duaneg duaneg commented May 25, 2025

Copy link
Copy Markdown
Contributor

Global state _PyRuntime.types.next_version_tag is being accessed without synchronization or atomics. This could potentially result in the same version being used in two different type objects, incrementing past the maximum limit, and the usual non-atomic memory access issues.

Fix this by using atomics to ensure the version is accessed and updated in a race-free manner, while also ensuring it is never incremented past the expected (maximum + 1).

Note there is a theoretical change in behaviour with the second use, for static builtin types, if their versions exceed the maximum, with assertions disabled: previously they would have continued incrementing past the maximum and using the increasing version number; now they will all use the maximum. It might be better to replace the assert with an abort(): I assume we would be crashing shortly if we continue after this, both before and after this change.

Global state `_PyRuntime.types.next_version_tag` is being accessed without
synchronization or atomics. This could potentially result in the same version
being used in two different type objects, incrementing past the maximum limit,
and the usual non-atomic memory access issues.

Fix this by using atomics to ensure the version is accessed and updated in a
race-free manner, while also ensuring it is never incremented past the expected
(maximum + 1).

Note there is a theoretical change in behaviour with the second use, for static
builtin types, if their versions exceed the maximum, with assertions disabled:
previously they would have continued incrementing past the maximum and using
the increasing version number; now they will all use the maximum. It might be
better to replace the `assert` with an `abort()`: I assume we would be crashing
shortly if we continue after this, both before and after this change.

@ZeroIntensity ZeroIntensity left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for doing this. I'm not sure we're able to skip the subinterpreter test yet, because there are still races when doing non-atomic stores of the version on static types. I've looked into fixing those myself, and it's signficantly more complex.

@duaneg

duaneg commented May 26, 2025

Copy link
Copy Markdown
Contributor Author

@ZeroIntensity ZeroIntensity left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mostly LGTM

Comment thread Misc/NEWS.d/next/Core_and_Builtins/2025-05-25-23-55-43.gh-issue-116909.FGbNKx.rst Outdated
…e-116909.FGbNKx.rst

Co-authored-by: Peter Bierma <zintensitydev@gmail.com>
@StanFromIreland

Copy link
Copy Markdown
Member

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants