-
-
Notifications
You must be signed in to change notification settings - Fork 30.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
_PyStaticType_Dealloc
does not invalidate type version tag
#101696
Comments
I'll file PR shortly. |
Good job debugging that! 👏🏻👏🏻👏🏻 |
…_Dealloc` (pythonGH-101697). (cherry picked from commit d9de079) Co-authored-by: Kumar Aditya <[email protected]>
_PyStaticType_Dealloc
does not invalidates type version tag_PyStaticType_Dealloc
does not invalidate type version tag
Given that static types should be immutable and immortal, I think a better approach would be reserve low values (up to a 1000 or so) for static classes. Once allocated, a static type would keep the same version number for the lifetime of the process. It might be handy to pre-allocate a few values for the most common types, but that's not necessary for correctness. |
Yeah, it makes sense and is on my todo list for a long time See #95795 |
Makes sense to me as well. As a proof-of-concept, reverting #101697 and applying the following seems to work: diff --git a/Objects/typeobject.c b/Objects/typeobject.c
index bf6ccdb77a..bc48845300 100644
--- a/Objects/typeobject.c
+++ b/Objects/typeobject.c
@@ -229,6 +229,13 @@ _PyType_CheckConsistency(PyTypeObject *type)
CHECK(type->tp_traverse != NULL);
}
+ if (_PyType_HasFeature(type, Py_TPFLAGS_VALID_VERSION_TAG)) {
+ CHECK(type->tp_version_tag != 0);
+ }
+ else {
+ CHECK(type->tp_version_tag == 0);
+ }
+
if (type->tp_flags & Py_TPFLAGS_DISALLOW_INSTANTIATION) {
CHECK(type->tp_new == NULL);
CHECK(PyDict_Contains(type->tp_dict, &_Py_ID(__new__)) == 0);
@@ -4469,8 +4476,6 @@ _PyStaticType_Dealloc(PyTypeObject *type)
}
type->tp_flags &= ~Py_TPFLAGS_READY;
- type->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG;
- type->tp_version_tag = 0;
if (type->tp_flags & _Py_TPFLAGS_STATIC_BUILTIN) {
_PyStaticType_ClearWeakRefs(type);
@@ -6968,6 +6973,8 @@ PyType_Ready(PyTypeObject *type)
/* Historically, all static types were immutable. See bpo-43908 */
if (!(type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
+ type->tp_version_tag = next_version_tag++;
+ type->tp_flags |= Py_TPFLAGS_VALID_VERSION_TAG;
type->tp_flags |= Py_TPFLAGS_IMMUTABLETYPE;
}
|
@erlend-aasland, your patch seems correct. I was going to ask what's the goal of your fix, since the merged fix addressed the originally described failure and gh-95795 addresses the rest. However, I think your fix might also deal with non-builtin static types (e.g. from community extension modules), which would probably be worth fixing too (regardless of how remote the possible failure). I have some additional feedback, but I can wait until you've made a PR. (Feel free to request a review from me.) |
Thanks for the comment, @ericsnowcurrently. I've alredy made a PR; I've requested your review. The PR is slightly different from my proposed patch here. I would also like to add some additional asserts, for example in |
As for the goal, I think Mark's reasoning is correct; making sure all immutable types have a lifelong (and immutable) valid version feels more correct than a fixup during finalise. |
That's the ideal goal yes but your PR only achieve valid version for only one cycle 1 of interpreter initialization, it is reset as #95795 is the complete solution for this, there is a lot of info about this in that thread. Footnotes
|
* main: (82 commits) pythongh-101670: typo fix in PyImport_ExtendInittab() (python#101723) pythonGH-99293: Document that `Py_TPFLAGS_VALID_VERSION_TAG` shouldn't be used. (#pythonGH-101736) no-issue: Add Dong-hee Na as the cjkcodecs codeowner (pythongh-101731) pythongh-101678: Merge math_1_to_whatever() and math_1() (python#101730) pythongh-101678: refactor the math module to use special functions from c11 (pythonGH-101679) pythongh-85984: Remove legacy Lib/pty.py code. (python#92365) pythongh-98831: Use opcode metadata for stack_effect() (python#101704) pythongh-101283: Version was just released, so should be changed in 3.11.3 (pythonGH-101719) pythongh-101283: Fix use of unbound variable (pythonGH-101712) pythongh-101283: Improved fallback logic for subprocess with shell=True on Windows (pythonGH-101286) pythongh-101277: Port more itertools static types to heap types (python#101304) pythongh-98831: Modernize CALL and family (python#101508) pythonGH-101696: invalidate type version tag in `_PyStaticType_Dealloc` (python#101697) pythongh-100221: Fix creating dirs in `make sharedinstall` (pythonGH-100329) pythongh-101670: typo fix in PyImport_AppendInittab() (pythonGH-101672) pythongh-101196: Make isdir/isfile/exists faster on Windows (pythonGH-101324) pythongh-101614: Don't treat python3_d.dll as a Python DLL when checking extension modules for incompatibility (pythonGH-101615) pythongh-100933: Improve `check_element` helper in `test_xml_etree` (python#100934) pythonGH-101578: Normalize the current exception (pythonGH-101607) pythongh-47937: Note that Popen attributes are read-only (python#93070) ...
True, Kumar, my PR is not a complete solution. |
Actually #101742 does not does this. The reason is that once a type is initialized via Lines 6957 to 6963 in d40a23c
So because of this #101742 has no effect because that code is only called once and subsequent initializations are skipped entirely. This happens in core static types because they are deallocated and reinitialized on every cycle unlike extension modules. |
Good point. |
Based on the discussion, I suggest closing #101742 and instead go for a complete fix, as proposed in Kumar's issue #95795. I could give it a go, just for fun1. OTOH, I don't want to waste review time, so I'm fine with leaving it to Kumar. Footnotes
|
The backport is merged so closing.
@erlend-aasland I'd say give it a shot, the points of implementation are written here #95795 (comment) and we can work together on this. |
Thanks, Kumar. I'll see if I can have something for you by the next weekend. |
_PyStaticType_Dealloc
does not invalidate the type version tag and when the interpreter is reinitialized it still points to the old index. It should be cleared after the runtime finalization to avoid a rare case where there is a cache hit from the old index.Found while working on https://github.com/python/cpython/actions/runs/4112993949/jobs/7098592004
Linked PRs
_PyStaticType_Dealloc
#101697_PyStaticType_Dealloc
(GH-101697) #101722The text was updated successfully, but these errors were encountered: