-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
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
bpo-41631: _ast module uses again a global state #21961
Conversation
Hum, I'm not sure that this change is correct. If a second instance of the _ast module is created, astmodule_clear() will clear the state which makes the first instance unusable :-( |
I also reverted partially the commit b1cc6ba "Convert _ast extension to PEP 489": astmodule_clear() and astmodule_free() now do nothing, the global _ast module state is never cleared. |
Parser/asdl_c.py
Outdated
@@ -1473,6 +1452,7 @@ def write_source(f, mod): | |||
f.write('#include "Python.h"\n') | |||
f.write('#include "%s-ast.h"\n' % mod.name) | |||
f.write('#include "structmember.h" // PyMemberDef\n') | |||
f.write('#include "pycore_pylifecycle.h" // export _PyAST_Fini()\n') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This code line occurs Py_BUILD_CORE
error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like extern void _PyAST_Fini(PyThreadState *tstate);
is not needed to export the symbol. I just removed the include.
Unfortunately, now all the node types are heap types shared across interpreters. Can they be made static again? Or maybe the AST state can be part of interpreter state. |
@vstinner @pablogsal: I've made the module state per-interpreter, i.e. part of the interpreter state, here: vstinner/cpython@revert_ast...encukou:revert_ast The complication is that @vstinner, do you want to use that commit for this PR? |
I updated my PR to convert AST_type again to a static type to fix a corner case with subinterpreters: https://bugs.python.org/issue41631#msg376686 cc @encukou |
@pablogsal @corona10: Would you mind to review this PR? It fix a release blocker for Python 3.9.0, a regression compared to 3.8: see https://bugs.python.org/issue41631 The deadline for 3.9.0rc2 is next monday :-( @encukou proposes PR #21973 to workaround the regression and to fix the regression in a 3.9 bugfix release (like 3.9.1). This PR is non-trivial, but _ast got tons of changes between 3.8 and 3.9, and I would prefer to avoid further large changes (like this PR) in the 3.9 stable branch after 3.9.0 final release. I'm not sure what is the best option :-( I suggest you to revert the two commits separately, since they are non-trivial: Note: If we choose to merge this PR and backport it to Python 3.9, do you think that it would be better to merge the second commit in a separated PR, since commits of this PR will be squashed? |
Summary of my change: this PR reverts changes made after 3.8, to move back to the battle-tested 3.8 code. I reverted the changes which causes many bugs. |
If possible, I would prefer to https://bugs.python.org/issue41631 regression in Python 3.9.x (the best would be to fix it in 3.9.0). |
I fixed the Windows build, but now the documentation job fails with:
It seems to be unrelated to my change: https://bugs.python.org/issue41762 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, I locally run this PR and it looks good.
Close/reopen to attempt to magically fix https://bugs.python.org/issue41762 |
I tried to review reviewed this today but time ran out so I will try to do a review tomorrow. In any case, it would be good to have regression test for the problems we have uncovered. |
My PR has a regression test; feel free to adapt it: https://github.com/python/cpython/pull/21973/files#diff-f265a39e24fab89dc68309a7db18e171R1948 |
Partially revert commit ac46eb4: "bpo-38113: Update the Python-ast.c generator to PEP384 (gh-15957)". Using a module state per module instance is causing subtle practical problems. For example, the Mercurial project replaces the __import__() function to implement lazy import, whereas Python expected that "import _ast" always return a fully initialized _ast module. Add _PyAST_Fini() to clear the state at exit. The _ast module has no state (set _astmodule.m_size to 0). Remove astmodule_traverse(), astmodule_clear() and astmodule_free() functions.
This does not really move One of the bugs was already present in 3.8 – it's possible to objects across subinterpreters. We can agree to ignore that in 3.9.0\ and say that multiple interpreters still aren't safe. That's fine with me at this point; I opened ericsnowcurrently/multi-core-python#68 to track this. But then, the second commit here doesn't solve anything: it makes only one of the types static, when are lots of heap types still remaining. Or is it supposed to solve a different problem? If not, I say we should merge only the first commit here, plus any tests. |
@pablogsal: I added 3 tests to test_ast which should cover all bugs listed in https://bugs.python.org/issue41631 With the new subinterpreter test, I noticed two reference leak bugs which are not introduced by my PR, but simply have not be seen previously. So I fixed them as part of this PR as well. Otherwise, this PR would make all Refleak buildbot failing. |
You are correct that I attempted to better isolate the _ast module in subinterpreter (fix ericsnowcurrently/multi-core-python#68 ). My intent was to fix some bugs by doing that, but I introduced other new bugs :-( Example:
This code displays Since it's not a regression compared to Python 3.8, I suggest to open a new issue if you consider that the _ast module should be enhanced.
My intent is to move back to Python 3.8 status quo (behavior) for the _ast.AST type. For example, with my change, it's not possible to add a new attribute to _ast.AST in the main interpreter or in a subinterpreter. Example:
This code raises |
I added a 4th test to check this behavior with the comment:
|
Right. Commits 2 and 3 in this PR are not necessary. To me, reverting to 3.8 would make sense as a reason if |
My first intent was to prevent changes of the _ast module in a subinterpreter which would impact other interpreters. Sadly, I didn't notice that it was already possible to modify other interpreter using _ast.AST subtypes. By the way, |
I'm fine with leaving _ast.AST as a heap type in Python 3.9 (remove my commits 2 and 3), and so keep this minor behavior change. It can be fixed later. As I wrote, there was already other ways to change the state of other interpreters using _ast.AST subtypes. Do other people have an opinion on that? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since this PR is a blocker,
I would like to approve this PR if the mercurial issue is solved and other regression.
(And looks like this issue is solved)
And other minor behavior can be modified after this release.
* Only call _PyAST_Fini() in the main interpreter * "import ast" only adds deprecated methods once to _ast.Constant and _ast.Tuple types.
I removed the commits which convert _ast.AST back to a static type. |
@ambv: Please replace |
Sorry, @vstinner and @ambv, I could not cleanly backport this to |
Partially revert commit ac46eb4: "bpo-38113: Update the Python-ast.c generator to PEP384 (pythongh-15957)". Using a module state per module instance is causing subtle practical problems. For example, the Mercurial project replaces the __import__() function to implement lazy import, whereas Python expected that "import _ast" always return a fully initialized _ast module. Add _PyAST_Fini() to clear the state at exit. The _ast module has no state (set _astmodule.m_size to 0). Remove astmodule_traverse(), astmodule_clear() and astmodule_free() functions.. (cherry picked from commit e5fbe0c) Co-authored-by: Victor Stinner <vstinner@python.org>
GH-22258 is a backport of this pull request to the 3.9 branch. |
…-22258) Partially revert commit ac46eb4: "bpo-38113: Update the Python-ast.c generator to PEP384 (gh-15957)". Using a module state per module instance is causing subtle practical problems. For example, the Mercurial project replaces the __import__() function to implement lazy import, whereas Python expected that "import _ast" always return a fully initialized _ast module. Add _PyAST_Fini() to clear the state at exit. The _ast module has no state (set _astmodule.m_size to 0). Remove astmodule_traverse(), astmodule_clear() and astmodule_free() functions.. (cherry picked from commit e5fbe0c) Co-authored-by: Victor Stinner <vstinner@python.org>
Partially revert commit ac46eb4: "bpo-38113: Update the Python-ast.c generator to PEP384 (pythongh-15957)". Using a module state per module instance is causing subtle practical problems. For example, the Mercurial project replaces the __import__() function to implement lazy import, whereas Python expected that "import _ast" always return a fully initialized _ast module. Add _PyAST_Fini() to clear the state at exit. The _ast module has no state (set _astmodule.m_size to 0). Remove astmodule_traverse(), astmodule_clear() and astmodule_free() functions.
Using a different state per module instance is causing subtle
practical problems.
For example, the Mercurial project replaces the import() function
to implement lazy import, whereas Python expected that "import _ast"
always return a fully initialized _ast module.
https://bugs.python.org/issue41631