-
Notifications
You must be signed in to change notification settings - Fork 50
Add support for 3.14 #230
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
base: main
Are you sure you want to change the base?
Add support for 3.14 #230
Conversation
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #230 +/- ##
==========================================
- Coverage 82.66% 82.27% -0.40%
==========================================
Files 46 46
Lines 6249 6286 +37
Branches 458 461 +3
==========================================
+ Hits 5166 5172 +6
- Misses 1083 1114 +31
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
11a287b
to
5ba15bf
Compare
edb3a62
to
ac5ef67
Compare
Signed-off-by: Peter Bierma <zintensitydev@gmail.com>
We don't want to publish any wheels for Python 3.14 betas, since ABI stability isn't guaranteed until the release candidates. Signed-off-by: Matt Wozniski <godlygeek@gmail.com>
@ZeroIntensity I've managed to get CI working for 3.14 in #237, and rebased this PR on top of those changes. After getting CI running, there are quite a few failing tests here. Would you mind taking a look and trying to fix things? At a glance, all of the failures seem to be related to reading local variables from Python 3.14 processes. |
Will take a look soon. |
@godlygeek Is CI setting up 3.14b0, or 3.14 straight off the CPython repo? Mark changed the tag bits for stackrefs a few days ago, so that could definitely be screwing things up. |
CI is using 3.14.0 beta 1 |
Sorry for the delay! I can't reproduce the CI failures locally on 3.14b1, but I can reproduce off CPython main, and changing the bits doesn't seem to fix it. How sure are we that it's 3.14b1? |
Pretty close to 100%... The failing run logs:
as well as
and
I guess there's some small chance that |
Beta 2 is out anyway, I guess. Since I can repro on that, let's switch to it. |
Indeed, if I rerun the failing CI job it now uses beta2 - seems like actions/setup-python now supports it. And with beta2 there's a bunch more failures - 118 tests fail, instead of the previous 18 failures. So it definitely does seem like something changed between beta1 and beta2 that we'll need to adjust for. |
There's definitely the stackref bits, but not too sure what else changed. Will investigate tomorrow. |
That must be python/cpython#134286 - adding the offset of the thread-local bytecode offsets to |
Oh, yeah, that'd do it! |
Hmm, fixing that and changing the stackref bits didn't seem to fix it. Everything is failing with I am seeing this on the tests though: |
Hm, neither - the test suite by default will test debugging every version of the Python interpreter it can find. If you want to test with only the Python version that you're running pytest with, you can But if pystack running under 3.14 fails to successfully debug Python applications running under 3.13, that would mean that things are broken in such a way that the offsets for 3.13 are wrong as well, not just the offsets for 3.14... that's concerning... |
Push your changes and I can take a look tomorrow, if you don't beat me to figuring it out. Did you notice there were two changes to the debug offsets in python/cpython#134286 - adding Does anything interesting get logged if you |
The most interesting thing is:
|
You'll kick yourself: your latest commit, eb5c104, changes the layout of the |
Ugh, yeah, that fixed a lot of the failures. On the remaining failures, I'm seeing these two warnings:
|
python/cpython@1822f33 affected the debug offsets, too. Adding those gets us back down to 18 failing tests - probably the same ones that were failing with beta 1... All of the failing tests are reading local variables. |
Seems like that's just because the locals are now PyStackRef's too, and so we need to mask off the low bits. |
PyTupleObject now includes a cached hash. Adjust our heuristics about how to find the items inside a tuple.
Thanks! Looks like we're down to 2 failed tests. |
PyTupleObject now includes a cached hash. Adjust our heuristics about how to find the items inside a tuple.
I took another swing at dealing with the layout changes to |
Which objects does pystack need to know the layout of? Free-threaded objects have a lot of internal layout changes. |
ints, floats, strings, bytes, dicts, lists, tuples, code objects, frames, and a handful of others. The first issue I tracked down is that the diff --git a/src/pystack/_pystack/process.cpp b/src/pystack/_pystack/process.cpp
index b48a225..8c3715c 100644
--- a/src/pystack/_pystack/process.cpp
+++ b/src/pystack/_pystack/process.cpp
@@ -540,10 +540,10 @@ AbstractProcessManager::getStringFromAddress(remote_addr_t addr) const
<< addr;
Structure<py_unicode_v> unicode(shared_from_this(), addr);
- Python3::_PyUnicode_State state = unicode.getField(&py_unicode_v::o_state);
- if (state.kind != 1 || state.compact != 1) {
- throw InvalidRemoteObject();
- }
+ //Python3::_PyUnicode_State state = unicode.getField(&py_unicode_v::o_state);
+ //if (state.kind != 1 || state.compact != 1) {
+ // throw InvalidRemoteObject();
+ //}
len = unicode.getField(&py_unicode_v::o_length);
buffer.resize(len); That'll lead to problems if there's any non-ASCII strings, but we can circle back to that later. After applying that diff, I get a segfault (!!) in code that you changed in diff --git a/src/pystack/_pystack/pycode.cpp b/src/pystack/_pystack/pycode.cpp
index fc490e3..874fa25 100644
--- a/src/pystack/_pystack/pycode.cpp
+++ b/src/pystack/_pystack/pycode.cpp
@@ -133,6 +133,7 @@ getLocationInfo(
tlbc_entries + sizeof(tlbc_size),
tlbc_size * sizeof(uintptr_t),
vec.data());
+ LOG(DEBUG) << "tlbc_index=" << tlbc_index << " tlbc_size=" << tlbc_size;
uintptr_t code_adaptive_actual = vec[tlbc_index];
ptrdiff_t addrq =
(reinterpret_cast<uint16_t*>(last_instruction_index) prints this out right before the crash:
Both of those look wrong, but it's not crashing on the first frame it processes, it's crashing on the 6th... Ah, it looks like we're trying to get the code object for a shim frame, which is just nonsense. This patch fixes that: diff --git a/src/pystack/_pystack/pyframe.cpp b/src/pystack/_pystack/pyframe.cpp
index 3b81beb..6276952 100644
--- a/src/pystack/_pystack/pyframe.cpp
+++ b/src/pystack/_pystack/pyframe.cpp
@@ -29,10 +29,10 @@ FrameObject::FrameObject(
if (d_is_shim) {
LOG(DEBUG) << "Skipping over a shim frame inserted by the interpreter";
next_frame_no = frame_no;
+ } else {
+ d_code = getCode(manager, frame);
}
- d_code = getCode(manager, frame);
-
auto prev_addr = frame.getField(&py_frame_v::o_back);
LOG(DEBUG) << std::hex << std::showbase << "Previous frame address: " << prev_addr;
if (prev_addr) { OK, so with those patches applied, things seem to actually work, but we will need to refactor things to allow for a different unicode state layout in free threaded vs non free threaded. |
IIRC, dictionaries have a different layout in FT vs non-FT too. |
Looks like any differences there are covered by the debug offsets. After making the two fixes I identified yesterday (not trying to extract code objects from shim frames, and handling the state flags of We do probably need to add some more tests to prove that the thread-local bytecode stuff is working properly, though. I doubt that any of our existing tests force specialization in a non-main thread. |
It shouldn't matter what thread it's in, right? As long as PyStack is testing for specializations, then it should be covering the TLBC code. |
The main thread's TLBC pointer points to the co_adaptive in the code object. If we're only testing in the main thread, there's no proof that we're not just using the bytecode for the main thread unconditionally. In other words, we need a test that fails without your changes to use the thread-local bytecode array, and succeeds with them. |
Issue number of the reported bug or feature request: #229