This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author brandtbucher
Recipients Mark.Shannon, brandtbucher, gvanrossum, pablogsal
Date 2021-12-15.20:55:30
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1639601731.02.0.904150269203.issue46090@roundup.psfhosted.org>
In-reply-to
Content
I'm specifically concerned about Greenlet here (since it's a dependency of pyperformance), but this discussion is equally relevant to any library like it that dynamically swaps out the currently executing frame.

CPython 3.11 makes several major changes to how frame objects are used and represented internally:

- bpo-44032: Move data stack to thread from FrameObject. (https://github.com/python/cpython/pull/26076)
- bpo-44590: Lazily allocate frame objects (https://github.com/python/cpython/pull/27077)
- bpo-45637: Store the frame pointer in the cframe (https://github.com/python/cpython/pull/29267)

These changes break Greenlet's hot-swapping of frame objects (https://github.com/python-greenlet/greenlet/blob/be41e1a24925326b72a02ef5cb6d1ed9643eb062/src/greenlet/greenlet_greenlet.hpp#L768-L811) in a pretty serious way, and it's not immediately clear what the best fix is. A fairly high-level overview of the new design:

When a frame is executing, the current thread state points to the current CFrame, which itself points to a C-level InterpreterFrame. This interpreter frame is located within a "data stack" that is managed by the thread state. If a PyFrameObject for the currently executing frame is requested (using PyThreadState_GetFrame), the new PyFrameObject points into the InterpreterFrame, where all of the important data is still stored. So far so good.

The issue is what happens next. If the InterpreterFrame is replaced, or exits in any way, its memory may be reused, or even freed entirely. The PyFrameObject is smart enough to copy the data elsewhere (into itself) when this happens, but the new design means that there is no obvious way for a third-party library to "reactivate" a frame in a way analogous to assigning to the old tstate->frame member.

While I'm pretty sure that we don't officially support this "feature", it's probably used often enough that we should at least brainstorm a workaround (if not an unstable C-API function) for affected projects. I suspect that a potential solution likely involves creating an entirely new InterpreterFrame the normal way, and copying the PyFrameObject's InterpreterFrame data into it? Not sure what would happen if the old InterpreterFrame was still alive on the data stack, though...

In any case, it probably makes sense to discuss here with affected library maintainers.
History
Date User Action Args
2021-12-15 20:55:31brandtbuchersetrecipients: + brandtbucher, gvanrossum, Mark.Shannon, pablogsal
2021-12-15 20:55:31brandtbuchersetmessageid: <1639601731.02.0.904150269203.issue46090@roundup.psfhosted.org>
2021-12-15 20:55:31brandtbucherlinkissue46090 messages
2021-12-15 20:55:30brandtbuchercreate