Skip to content
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

Make it easier to traverse the frame stack for third party tools. #100987

Open
markshannon opened this issue Jan 12, 2023 · 49 comments
Open

Make it easier to traverse the frame stack for third party tools. #100987

markshannon opened this issue Jan 12, 2023 · 49 comments
Assignees
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement

Comments

@markshannon
Copy link
Member

markshannon commented Jan 12, 2023

Profilers and debuggers need to traverse the frame stack, but the layout of the stack is an internal implementation detail.
However can make some limited promises to make porting tools between Python versions a bit easier.

In order to traverse the stack, the offset of the previous pointer needs to be known. To understand the frame, more information is needed.

@pablogsal
@Yhg1s
expressed interest in this.

Linked PRs

@markshannon markshannon added the type-feature A feature request or enhancement label Jan 12, 2023
@markshannon
Copy link
Member Author

Initially, I propose to refactor the PyInterpreterFrame struct such that it starts:

typedef struct _PyInterpreterFrame {
    PyCodeObject *f_code;
    struct _PyInterpreterFrame *previous;
    ...

Currently f_code must be a code object, but we could generalize it to allow other objects.
For example, the shim frame inserted on entry to _PyEval_EvalFrameDefault could have that field set to None indicating it should be skipped in tracebacks, etc.

The order of f_code and previous doesn't really matter, but have f_code first makes #100719 a bit simpler

@pablogsal pablogsal self-assigned this Jan 12, 2023
@pablogsal
Copy link
Member

Let me collect some feedback from maintainers of debuggers and profilers and will comment here the requirements so we can think of solutions.

markshannon added a commit that referenced this issue Feb 13, 2023
…improvement. (GH-100988)

Refactor _PyInterpreterFrame a bit, to assist generator improvement.
carljm added a commit to carljm/cpython that referenced this issue Feb 13, 2023
* main:
  pythongh-101810: Remove duplicated st_ino calculation (pythonGH-101811)
  pythongh-92547: Purge sqlite3_enable_shared_cache() detection from configure (python#101873)
  pythonGH-100987: Refactor `_PyInterpreterFrame` a bit, to assist generator improvement. (pythonGH-100988)
  pythonGH-87849: Simplify stack effect of SEND and specialize it for generators and coroutines. (pythonGH-101788)
  Correct trivial grammar in reset_mock docs (python#101861)
  pythongh-101845: pyspecific: Fix i18n for availability directive (pythonGH-101846)
  pythongh-89792: Limit test_tools freeze test build parallelism based on the number of cores (python#101841)
  pythongh-85984: Utilize new "winsize" functions from termios in pty tests. (python#101831)
  pythongh-89792: Prevent test_tools from copying 1000M of "source" in freeze test (python#101837)
  Fix typo in test_fstring.py (python#101823)
  pythonGH-101797: allocate `PyExpat_CAPI` capsule on heap (python#101798)
  pythongh-101390: Fix docs for `imporlib.util.LazyLoader.factory` to properly call it a class method (pythonGH-101391)
@markshannon
Copy link
Member Author

@pablogsal Any feedback?

@markshannon
Copy link
Member Author

We can further improve traversal of the _PyInterpreterFrame for debugging and introspection by allowing C extensions to create frames without the rigmarole of creating a code object.

We should rename the f_code field to f_executable, and allow any object.

typedef struct _PyVMFrame {
    PyObject *f_executable;
    struct _PyVMFrame *previous;
} PyVMFrame;

Although tools and the VM should tolerate any object, we should in practice only allow a few classes:

  • CodeObject: Implies that the PyVMFrame is a full _PyInterpreterFrame. Only the VM should make this kind of frame
  • Builtin function, method descriptor, slot wrapper, etc. The frame represents a call to the given object.
  • None: Internal shim. Tools should skip this frame.
  • Tuple: First three items should be name, filename, flags where flags determine the meaning of additional entries.

The tuple form is for tools like Cython, Nanobind, etc. Creating a tuple of strs and ints is much simpler and faster than creating a fake code object.

C extension can link themselves into the frame stack at the cost of about 4 memory writes, and 3 reads:

    PyVMFrame frame;
    frame.previous = tstate->current_frame.frame;
    frame.f_executable = &EXECUTABLE_OBJECT;
    tstate->current_frame.frame = &frame;
    /* body of function goes here */
    tstate->current_frame.frame = frame.previous;

We can do this for builtins functions by modifying the vectorcall function assigned to the builtin function/method descriptor.
We would need to benchmark this to see the performance impact, but it will be much cheaper than sys.activate_stack_trampoline()

@pablogsal
Copy link
Member

@pablogsal Any feedback?

I have reached out again to tool authors, give me a couple of days to gather comments. Apologies for the delay

@markshannon
Copy link
Member Author

No problem.

markshannon added a commit that referenced this issue Mar 13, 2023
…PyEval_EvalFrameDefault`. (#102640)

* Rename local variables, names and consts, from the interpeter loop. Will allow non-code objects in frames for better introspection of C builtins and extensions.

* Remove unused dummy variables.
carljm added a commit to carljm/cpython that referenced this issue Mar 14, 2023
* main: (50 commits)
  pythongh-102674: Remove _specialization_stats from Lib/opcode.py (python#102685)
  pythongh-102660: Handle m_copy Specially for the sys and builtins Modules (pythongh-102661)
  pythongh-102354: change python3 to python in docs examples (python#102696)
  pythongh-81057: Add a CI Check for New Unsupported C Global Variables (pythongh-102506)
  pythonGH-94851: check unicode consistency of static strings in debug mode (python#102684)
  pythongh-100315: clarification to `__slots__` docs. (python#102621)
  pythonGH-100227: cleanup initialization of global interned dict (python#102682)
  doc: Remove a duplicate 'versionchanged' in library/asyncio-task (pythongh-102677)
  pythongh-102013: Add PyUnstable_GC_VisitObjects (python#102014)
  pythonGH-102670: Use sumprod() to simplify, speed up, and improve accuracy of statistics functions (pythonGH-102649)
  pythongh-102627: Replace address pointing toward malicious web page (python#102630)
  pythongh-98831: Use DECREF_INPUTS() more (python#102409)
  pythongh-101659: Avoid Allocation for Shared Exceptions in the _xxsubinterpreters Module (pythongh-102659)
  pythongh-101524: Fix the ChannelID tp_name (pythongh-102655)
  pythongh-102069: Fix `__weakref__` descriptor generation for custom dataclasses (python#102075)
  pythongh-98169 dataclasses.astuple support DefaultDict (python#98170)
  pythongh-102650: Remove duplicate include directives from multiple source files (python#102651)
  pythonGH-100987: Don't cache references to the names and consts array in `_PyEval_EvalFrameDefault`. (python#102640)
  pythongh-87092: refactor assemble() to a number of separate functions, which do not need the compiler struct (python#102562)
  pythongh-102192: Replace PyErr_Fetch/Restore etc by more efficient alternatives (python#102631)
  ...
@itamarst
Copy link

@benfred -^

@markshannon
Copy link
Member Author

I've made a branch that adds "lightweight" frames (just a pointer to a "code" object and a link pointer), and inserts one for each call to a builtin function in the interpreter. The performance impact is negligible and all builtin function and class calls are present in the frame stack.

Branch: https://github.com/python/cpython/compare/main...faster-cpython:cpython:allow-non-python-frames?expand=1

Performance: https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20230315-3.12.0a6%2B-3e2c3ab/bm-20230315-linux-x86_64-faster%252dcpython-allow_non_python_fra-3.12.0a6%2B-3e2c3ab-vs-base.png

@pablogsal
Copy link
Member

I've made a branch that adds "lightweight" frames (just a pointer to a "code" object and a link pointer), and inserts one for each call to a builtin function in the interpreter. The performance impact is negligible and all builtin function and class calls are present in the frame stack.

Branch: https://github.com/python/cpython/compare/main...faster-cpython:cpython:allow-non-python-frames?expand=1

Performance: https://github.com/faster-cpython/benchmarking-public/blob/main/results/bm-20230315-3.12.0a6%2B-3e2c3ab/bm-20230315-linux-x86_64-faster%252dcpython-allow_non_python_fra-3.12.0a6%2B-3e2c3ab-vs-base.png

We still need the concept of entry frames for tools that merge native and python stacks. Why do you removed _PyFrame_IsEntryFrame in your branch?

@markshannon
Copy link
Member Author

It's a proof of concept, it was easier to remove _PyFrame_IsEntryFrame than re-implement it.
_PyFrame_IsEntryFrame can be added back, if necessary.

@pablogsal
Copy link
Member

It's a proof of concept, it was easier to remove _PyFrame_IsEntryFrame than re-implement it. _PyFrame_IsEntryFrame can be added back, if necessary.

👍

@carljm
Copy link
Contributor

carljm commented Mar 17, 2023

We are also very interested in this proposal from the Cinder JIT perspective.

One difference I see with our use case compared to what the draft PR so far aims to support is that we would like to be able to link in "minimal frames" that are still considered "complete": they are fetched by _PyFrame_GetFirstComplete() and can be materialized into a full PyFrameObject. (In the draft PR here, only _PyInterpreterFrame frames are considered "complete".) We don't want to constantly keep a _PyInterpreterFrame (localsplus contents) up to date while the JIT is running (this is expensive), so we'd need to get some kind of callback to reify our minimal frame into a PyFrameObject on-demand (i.e. some hook into _PyFrame_GetFrameObject).

In the tuple form of f_executable, could there be a well-known bit-flag in the third element that tells the interpreter "this should be considered a 'complete' frame, and the next word in its struct is a function pointer that will take the VMFrame struct and return a PyFrameObject."?

@pablogsal
Copy link
Member

We should rename the f_code field to f_executable, and allow any object.

In general the feedback is that this will make introspection tool much harder to implement. Currently the fact that this can only be a code object makes it very easy to traverse the frame stack. If you allow any Python object it makes it harder or in some cases even impossible.

If we restrict this to a finite set of possibilities, it still makes it much harder but if we add some kind of enumeration to the frame that tells the tool what's going to be there it makes it a bit easier.

In general I don't think that this proposal helps introspection tools, it actually makes the implementation harder and less efficient because more pointers need to be copied and more logic needs to be included.

@pablogsal
Copy link
Member

Some comments from authors:

I feel it won't be too easy to decipher the type of the object remotely. This would likely increase the number of private structures that we need to copy over from Python headers to parse this information (e.g. tuples), making things more complex. Of course one could just try treating the object as a PyCodeObject and check for failures, but this would now imply a potential loss of captured information, unless all the other object types that can appear here are also handled. Perhaps an extra int field that specifies the type of the object being passed with f_executable might help in this direction, to some extent. But perhaps one simplification that depends on a positive answer to the following question could be adopted: is the value f_executable crucial for the actual execution, or is it just added to carry the frame's metadata (e.g. filename, function name, line number, ...)? If that is added just for the metadata, perhaps that could be added directly to the _PyVMFrame structure in the form of extra fields? There could be a core set of fields that are common to all object types (filename, function qualname, location data), plus a generic PyObject reference that can be consumed easily by in-process tools. However, I can see the downside being that the cost would probably end up being slightly more than just 4 W and 3 R operations in general.

@pablogsal
Copy link
Member

In general the sentiment is that the more regular the structure is, the easier is for profilers and debuggers to traverse the stack. The more variations and python-isms (as in, using PyObject* instead of C structs) the harder it makes for these tools to properly traverse the stack, which goes against (partially) what we are trying to do here

@markshannon
Copy link
Member Author

Feedback from who? Which operations for which tools become harder?
It is hard to take vague and anonymous feedback seriously.

No one is forcing tools to handle all possible frames. They can skip frames that have "executable" objects other than code objects. The presence of additional information that tools ignore cannot be worse than that information not being present in the first place.
Add not all tools will ignore it; the PR already give better tracebacks in the faulthandler module.

In general the sentiment is that the more regular the structure is, the easier is for profilers and debuggers to traverse the stack. The more variations and python-isms (as in, using PyObject* instead of C structs) the harder it makes for these tools to properly traverse the stack, which goes against (partially) what we are trying to do here

Two fields, one pointing to the next frame, and one pointing to the executable object, seems quite regular to me.
Traversal of the stack is trivial. Just follow the previous pointer.

@markshannon
Copy link
Member Author

It might be informative to compare this with adding perf support:

  • Adding perf frames causes a slowdown of 8%. The PR above has negligible performance impact.
  • This works on Windows and any machine that does not have perf installed.
  • It works with PEP 523 or PEP 669.

Fidget-Spinner pushed a commit to Fidget-Spinner/cpython that referenced this issue Mar 27, 2023
… in `_PyEval_EvalFrameDefault`. (python#102640)

* Rename local variables, names and consts, from the interpeter loop. Will allow non-code objects in frames for better introspection of C builtins and extensions.

* Remove unused dummy variables.
@pablogsal
Copy link
Member

pablogsal commented Mar 27, 2023

Feedback from who?

Authors of profilers and debuggers. For now authors of Austin, py-spy, scygraph and fil, and myself (memray/pystack). I collected feedback from them but if you prefer that they comment here directly individually I can also ask for that.

Which operations for which tools become harder?

Getting the Python stack from a remote process reading memory.

It might be informative to compare this with adding perf support:

Informative how? perf support is optional, it doesn't affect profiling or debugging tools other than allowing perf to work and it doesn't collide with this work. I am failing to see the argument here. This issue is called "Make it easier to traverse the frame stack for third party tools" and we are literally discussing changes that will achieve the opposite for some tools, not sure how the perf support is involved.

@markshannon
Copy link
Member Author

if you prefer that they comment here directly individually I can also ask for that.

Yes, please.

perf support is optional

Is it really? In that case let's drop it now before it causes trouble for 3.13.
We aren't going to support perf in any future JIT compiler.

@markshannon
Copy link
Member Author

Let's make it clear. The choice isn't between the proposed ABI and the status quo. The choice is between a well defined, if minimal, ABI and no ABI guarantees whatsoever.
The _PyInterpreterFrame struct is internal and will change.

For example, we need to insert frames for shims at the exit from __init__ functions in order to inline them. We might want to do the same for calls to __setitem__ and __setattr__ as well. Create code objects for these shims is a waste of effort.
We might want to replace calls to tuple with a surrogate that constructs the tuple in bytecode. We will want to have the tuple object as the "executable", so that the frame stack looks the same.

And don't forget the producers of frames, as well as the consumers.
JIT compilers may want to insert frames. Cinder does. I suspect we won't, but we might.
Cython and pybind11 may want to insert frames, if not all the time, at least if an error occurs. Creating fake code objects is unnecessary overhead.

If the ABI I'm suggesting is not a good one, then you need to suggest a better one.

I am failing to see the argument here (Contrasting with perf support)

The purpose of adding perf support is that tools can see the mixed C/Python stack.
perf support does that by faking Python frames on the C stack. I propose adding frames for C callables (and other things) to the Python stack.
Adding it to the Python stack means that it is easily accessible to in-process tools, and with very low overhead.
Adding to the C stack requires support for the native debugging format and ABI, and has a large cost.

@pablogsal
Copy link
Member

pablogsal commented Mar 27, 2023

So it doesn't mean optional for us and we are stuck with it?
In that case it needs a PEP.

The feature has landed already in 3.12 and is already released in alpha. I respect your position but I disagree with it. I suggest that if you want to discuss this, we can do it in a more real-time channel other than a GitHub issue.

@pablogsal
Copy link
Member

tighter the restrictions, the easier it is for introspection tools. The looser the restrictions, the easier it is for producers of frame.

Refocusing the discussion on the original issue at hand. I think that if we add some kind of metadata to the frame that tells the tool what kind of frame is this (so basically what's going to be in the "f_executable" field, that's already a win. As you mention, tools may want to skip some of these frames if it cannot be handled.

On the other hand if we support simple structs or simple Python objects (as opposed to custom classes or even dictionaries) in f_executable that's also a win.

Additionally, I would like if we keep the current structure as preserved as possible (with this I mean that most frames will have a f_executable that points to a well-defined code object.

Also, I think having these fields as you propose:

typedef struct _PyInterpreterFrame {
    PyCodeObject *f_code;
    struct _PyInterpreterFrame *previous;
    ...

is a big win as tools don't need to update these definitions every single time.

@markshannon
Copy link
Member Author

The "f_executable" field is its own metadata, as Python objects are self-describing.
Additional data adds bulk to the frame, and slows down frame creation.

We can restrict the number of classes that are officially supported. If "f_executable" object is one of those, then tools can use that information. It is something else, they can just ignore it.

In the minimal case of just supporting code objects:

while (frame);
   if (frame->f_executable->ob_type == &PyCode_Type) {
       do_stuff_with_frame(frame);
   }
   frame = frame->previous;
}

As for what should be supported:

  • Code objects
  • Classes
  • Builtin functions
  • Method descriptors
  • (name, filename, lineno) tuples.
  • (Maybe other C callables, like slot wrappers)*

I'd like to get rid of slot wrappers and other oddities and merge them into builtin functions, but that's another issue.

The VM might create frames for other objects, but tools should ignore them.

@pablogsal
Copy link
Member

The "f_executable" field is its own metadata, as Python objects are self-describing. Additional data adds bulk to the frame, and slows down frame creation.

We can restrict the number of classes that are officially supported. If "f_executable" object is one of those, then tools can use that information. It is something else, they can just ignore it.

In the minimal case of just supporting code objects:

I understand, but this makes life for inspection tools harder because it forces to copy much more stuff (the class and the name at least) instead of inspecting an enum. I would like to have what is in f_executable in the frame object. I understand that you don't but I want to state that I do :)

As for what should be supported:

  • Code objects
  • Classes
  • Builtin functions
  • Method descriptors
  • (name, filename, lineno) tuples.
  • (Maybe other C callables, like slot wrappers)*

I see what you are coming from, but allowing all these things is going to make implementing these tools a nightmare because supporting all these possibilities is a lot. I would like to restrict this list to just simple stuff like tuples, code objects and maybe some c-like struct that can be used for more exotic stuff. This is basically what you said here:

The tighter the restrictions, the easier it is for introspection tools. The looser the restrictions, the easier it is for producers of frame.

I am advocating for much tighter restrictions, but I understand that's not the direction that you want to go and I respect that.

@carljm
Copy link
Contributor

carljm commented Mar 27, 2023

We could use a tagged pointer in f_executable to provide an easy-to-read "flag" indicating the frame type without adding any additional bulk to frames, and not much extra cost to frame creation. This is what Cinder shadowframes does today: https://github.com/facebookincubator/cinder/blob/cinder/3.10/Include/internal/pycore_shadow_frame_struct.h#L42-L60

In the minimal form, we can leave the low bit 0 to indicate "normal frame, pointer to code object" (then there is also zero overhead in normal interpreter frame creation) and set it to 1 to mean "pointer to something new and different." Then existing tools that want to just handle normal code objects like they already do only need a single bit test to discard frames they don't want to deal with.

There are another two bits we could play with if we want to provide streamlined indication of any other common cases (builtin function, tuple form, maybe?).

I hope we can make life easier for existing inspection tools by making it really easy to detect the common cases they want to care about, but I also hope (from the Cinder JIT perspective) that at least one of the valid options for f_executable is "extensible". E.g. if(name, filename, lineo) tuple is allowed, that it's also valid to have a longer tuple carrying additional payload, with the first three elements interpreted as name, filename, lineo.

@carljm
Copy link
Contributor

carljm commented Mar 27, 2023

Classes

I'm curious, why would we want frames to hold a pointer to a class (I assume while executing the class body?) rather than to the code object of the class body?

@markshannon
Copy link
Member Author

I'm curious, why would we want frames to hold a pointer to a class

class C: pass

c = C()  # This is a call to a class

@markshannon
Copy link
Member Author

@pablogsal
Is checking for five or six distinct values, rather than two or three that big a deal?
Also, why is comparing to an address a problem, whereas comparing to an int is not?
frame->f_kind == CODE+OBJECT_KIND is a 32 bit comparison.
frame->f_executable == &PyCode_Type is a 64 bit comparison.
Fetching the address of PyCode_Type will need the symbol table, but you'll need that anyway.

@markshannon
Copy link
Member Author

@carlmjm
I don't see the value in tagging bits. The tag you propose holds no additional information, as the same value can be got with the simple comparison f_executable == &PyCodeObject

@pablogsal
Copy link
Member

pablogsal commented Mar 28, 2023

Fetching the address of PyCode_Type will need the symbol table, but you'll need that anyway.

Not necessarily. These tools need to work sometimes with stripped binaries or core files and requiring the symbol table there can be a huge pain compared with just checking against an integer, as we are vendoring the headers anyway. In particular, as an example (please don't focus too much on this) in core files is a huge pain because the address may not be in the core if is in the .rodata segment.


Currently, once you get the frame, you access the f_code pointer and you KNOW is a code object so once you have the layout for it (because we vendor the headers) you know how to extract the function name and the filename.

If we have an integer in the frame that tells what f_executable will have, then we can compare against it directly and know what we are going to find. No extra information or copies are required.

If we need to compare with something now we require:

  • Copy the pointers/structures of all the possible types that can be (that is PyCode_Type and the same for tuples, functions...). This is already problematic because they may not be in the core OR we may not have symbols so we may be unable to locate them even in a live process.
  • Once you find the address of PyCode_Type and friends, you need to relocate to find the real address. Quite simple to do, but is more operations.
  • If we allow random classes then the tools are unable to even compare against pointers because we don't even know where they are

But an enum describing what it contains allows us to KNOW what the pointer will contain and for instance be super sure that the pointer is some custom stuff that we won't be able to understand instead of having to "guess" based on "oh, this pointer is not one of the ones we know about (code, tuples...))

@markshannon
Copy link
Member Author

I appreciate that having extra information will make life easier for a few tool authors, but it might make things a little bit slower for very many Python users.

How do you get the frame without any symbols?

If we allow random classes...

Any class outside of the fixed set (whatever that ends up being) should be ignored, so no "random" classes.

@pablogsal
Copy link
Member

pablogsal commented Mar 28, 2023

How do you get the frame without any symbols?

Find the interpreter state and having the headers vendor so we know the offsets to the pointers in every struct and we know what we are going to find because at the moment is fully determined. The interpreter state can be found because we (cpython) place the runtime structure in its own section so it can be found without symbols:

__attribute__ ((section (".PyRuntime")))

Although this is technically not needed because it can be found by finding the cycle interpreter state <-> thread state by scanning the bss which is what py-spy does.

@carljm
Copy link
Contributor

carljm commented Mar 28, 2023

I don't see the value in tagging bits. The tag you propose holds no additional information, as the same value can be got with the simple comparison f_executable == &PyCodeObject

Sure, if you have &PyCodeObject available.

Tagging bits could "make life easier for a few tool authors" in the scenarios @pablogsal is mentioning without "making things slower for very many Python users."

EDIT: also, it's not f_executable == &PyCodeObject, it's f_executable->ob_type == &PyCodeObject, so it's adding an extra pointer chase for every frame also.

@markshannon
Copy link
Member Author

Tagging might solve the performance issue. But we need to support 32bit machines, so we only have 2 bits to play with, which is not enough.

@markshannon
Copy link
Member Author

If tools can find the runtime, then we can put an array of pointers there. No runtime overhead at the cost of ~40 bytes.

PyObject *callable_types[] = {
   &PyCode_Type,
   ...
};

@pablogsal
Copy link
Member

If tools can find the runtime, then we can put an array of pointers there.

That would be an acceptable compromise I think.

@markshannon
Copy link
Member Author

OK, let's go with that then.

FTR, one other reason not to use an enum is this: what happens when the enumeration and the executable don't match?
We can be fairly sure it won't happen in our code, but it would be an easy mistake to make in third-party code.

By allowing objects of any class, but designating a small set of "approved" classes, the system is much more robust.

@markshannon
Copy link
Member Author

@pablogsal
Where should the array go, exactly?

@markshannon
Copy link
Member Author

@carljm

I hope we can make life easier for existing inspection tools by making it really easy to detect the common cases they want to care about, but I also hope (from the Cinder JIT perspective) that at least one of the valid options for f_executable is "extensible". E.g. if(name, filename, lineo) tuple is allowed, that it's also valid to have a longer tuple carrying additional payload, with the first three elements interpreted as name, filename, lineo.

I don't see a problem with that.
Tools should check the length of the tuple before extracting the contents, for safety.
We could allow any length array, specifying only that the first three elements, if they exist, should be the name, filename and line number.
("foo",) and ("foo", "foo.py", 121, "special-data-34.8") should both be acceptable.

@pablogsal Would this be OK, or is this too complex for your tastes?

@P403n1x87
Copy link
Contributor

Some comments from authors:

I feel it won't be too easy to decipher the type of the object remotely. This would likely increase the number of private structures that we need to copy over from Python headers to parse this information (e.g. tuples), making things more complex. Of course one could just try treating the object as a PyCodeObject and check for failures, but this would now imply a potential loss of captured information, unless all the other object types that can appear here are also handled. Perhaps an extra int field that specifies the type of the object being passed with f_executable might help in this direction, to some extent. But perhaps one simplification that depends on a positive answer to the following question could be adopted: is the value f_executable crucial for the actual execution, or is it just added to carry the frame's metadata (e.g. filename, function name, line number, ...)? If that is added just for the metadata, perhaps that could be added directly to the _PyVMFrame structure in the form of extra fields? There could be a core set of fields that are common to all object types (filename, function qualname, location data), plus a generic PyObject reference that can be consumed easily by in-process tools. However, I can see the downside being that the cost would probably end up being slightly more than just 4 W and 3 R operations in general.

This would be me, maintainer of Austin. For context, Austin uses system calls like process_vm_readv to read memory out of process.

@P403n1x87
Copy link
Contributor

How do you get the frame without any symbols?

Austin uses symbols to locate _PyRuntime, but if those are not available, there is a fallback on BSS scan to locate something that looks like _PyRuntime or an interpreter state. So symbols are not strictly required (but good to have of course!).

@P403n1x87
Copy link
Contributor

Apologies if I slightly derail the conversation, but I wanted to express the following thought. Based on my experience with Austin, I would regard frame stack unwinding as just one aspect of the more general topic of observability into the Python VM. For example, one other thing that Austin tries to do is to sample the GC state to give an idea of how much CPU time is being spent on GC. Or detect who is holding the GIL to give a better estimate of RSS allocations. Therefore, I would tend to view frame stacks as just a part of what can be observed out of process. So the way I see a tool like Austin extracting this information in the future is by looking into an "observability entry point", much like _PyRuntime, but specifically engineered for out-of-process tools. From there one can rely on an ever growing (in an ideally backwards-compatible fashion) list of things one can observe, e.g.

.section _PyRuntimeStateABI

runtime_state {
  interpreter_state {
    thread_count: int,
    threads: [{
      top_frame: { ... },
      ....,
    ]
  },
  gc_state: ...,
  gil_state: ...,
}

warsaw pushed a commit to warsaw/cpython that referenced this issue Apr 11, 2023
… in `_PyEval_EvalFrameDefault`. (python#102640)

* Rename local variables, names and consts, from the interpeter loop. Will allow non-code objects in frames for better introspection of C builtins and extensions.

* Remove unused dummy variables.
markshannon added a commit that referenced this issue Jun 14, 2023
…of an internal frame. (GH-105727)

* Add table describing possible executable classes for out-of-process debuggers.

* Remove shim code object creation code as it is no longer needed.

* Make lltrace a bit more robust w.r.t. non-standard frames.
TheShermanTanker added a commit to TheShermanTanker/cpython that referenced this issue Jun 14, 2023
commit 74c2422
Author: Guido van Rossum <guido@python.org>
Date:   Wed Jun 14 08:19:24 2023 -0700

    Update DSL docs for cases generator (python#105753)

    * Clarify things around goto error/ERROR_IF a bit
    * Remove docs for super-instructions
    * Add pseudo; fix heading markup

commit 1d857da
Author: Mark Shannon <mark@hotpy.org>
Date:   Wed Jun 14 16:15:08 2023 +0100

    pythonGH-77273: Better bytecodes for f-strings (pythonGH-6132)

commit 307bcea
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 17:00:40 2023 +0200

    xmlrpc.client uses datetime.datetime.isoformat() (python#105741)

    Reimplement _iso8601_format() using the datetime isoformat() method.
    Ignore the timezone.

    Co-Authored-by: Paul Ganssle <1377457+pganssle@users.noreply.github.com>

commit 7b1f0f2
Author: Alex Waygood <Alex.Waygood@Gmail.com>
Date:   Wed Jun 14 15:58:41 2023 +0100

    pythongh-105570: Deprecate unusual ways of creating empty TypedDicts (python#105780)

    Deprecate two methods of creating typing.TypedDict classes with 0 fields using the functional syntax: `TD = TypedDict("TD")` and `TD = TypedDict("TD", None)`. Both will be disallowed in Python 3.15. To create a TypedDict class with 0 fields, either use `class TD(TypedDict): pass` or `TD = TypedDict("TD", {})`.

commit d32e8d6
Author: TATHAGATA ROY <royzen9495@gmail.com>
Date:   Wed Jun 14 19:51:30 2023 +0530

    pythongh-105196: Fix indentations of section headings in C API docs (python#105672)

commit 4a113e2
Author: Alex Waygood <Alex.Waygood@Gmail.com>
Date:   Wed Jun 14 15:19:27 2023 +0100

    Typing docs: move the deprecated stuff below the non-deprecated stuff (python#105781)

commit 7199584
Author: Mark Shannon <mark@hotpy.org>
Date:   Wed Jun 14 13:46:37 2023 +0100

    pythonGH-100987: Allow objects other than code objects as the "executable" of an internal frame. (pythonGH-105727)

    * Add table describing possible executable classes for out-of-process debuggers.

    * Remove shim code object creation code as it is no longer needed.

    * Make lltrace a bit more robust w.r.t. non-standard frames.

commit ad56340
Author: Alex Waygood <Alex.Waygood@Gmail.com>
Date:   Wed Jun 14 13:38:49 2023 +0100

    pythongh-105566: Deprecate unusual ways of creating `typing.NamedTuple` classes (python#105609)

    Deprecate creating a typing.NamedTuple class using keyword arguments to denote the fields (`NT = NamedTuple("NT", x=int, y=str)`). This will be disallowed in Python 3.15. Use the class-based syntax or the functional syntax instead.

    Two methods of creating `NamedTuple` classes with 0 fields using the functional syntax are also deprecated, and will be disallowed in Python 3.15: `NT = NamedTuple("NT")` and `NT = NamedTuple("NT", None)`. To create a `NamedTuple` class with 0 fields, either use `class NT(NamedTuple): pass` or `NT = NamedTuple("NT", [])`.

commit fc8037d
Author: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Date:   Wed Jun 14 05:35:06 2023 -0700

    pythongh-104873: Add typing.get_protocol_members and typing.is_protocol (python#104878)

    Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>

commit ba516e7
Author: Kirill Podoprigora <kirill.bast9@mail.ru>
Date:   Wed Jun 14 15:17:12 2023 +0300

    pythongh-102541: Hide traceback in help prompt (pythongh-102614)

commit 0316063
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 12:30:22 2023 +0200

    gdb libpython.py: Remove compatibility code (python#105739)

    Remove compatibility code for Python 2 and early Python 3 versions.

    * Remove os_fsencode() reimplementation: use os.fsencode() directly.
      os.fsencode() was added to Python 3.2.
    * Remove references to Python 2 and "Python 3": just say "Python".
    * Remove outdated u'' string format: use '' instead.

commit e5d45b7
Author: Nikita Sobolev <mail@sobolevn.me>
Date:   Wed Jun 14 13:29:16 2023 +0300

    pythongh-105745: Fix open method of webbrowser.Konqueror (python#105746)

commit 67f69db
Author: Nikita Sobolev <mail@sobolevn.me>
Date:   Wed Jun 14 13:26:20 2023 +0300

    pythongh-105687: Remove deprecated objects from `re` module (python#105688)

commit fb655e0
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 12:12:25 2023 +0200

    _ctypes callbacks.c uses _Py_COMP_DIAG_IGNORE_DEPR_DECLS (python#105732)

    Replace #pragma with _Py_COMP_DIAG_PUSH,
    _Py_COMP_DIAG_IGNORE_DEPR_DECLS and _Py_COMP_DIAG_POP to ease Python
    maintenance. Also add a comment explaining why callbacks.c ignores a
    deprecation warning.

commit 5cdd5ba
Author: Jelle Zijlstra <jelle.zijlstra@gmail.com>
Date:   Wed Jun 14 00:26:48 2023 -0700

    tarfile: Fix positional-only syntax in docs (pythonGH-105770)

    The syntax used in the current docs (a / before any args) is invalid.

    I think the right approach is for the arguments to arbitrary
    filter functions to be treated as positional-only, meaning that users
    can supply filter functions with any names for the argument. tarfile.py
    only calls the filter function with positional arguments.

commit 6199fe3
Author: Eddie Elizondo <eduardo.elizondorueda@gmail.com>
Date:   Wed Jun 14 00:33:32 2023 -0400

    pythongh-105587: Remove assertion from `_PyStaticObject_CheckRefcnt` (python#105638)

commit dab5a3e
Author: Barney Gale <barney.gale@gmail.com>
Date:   Wed Jun 14 05:06:58 2023 +0100

    pythonGH-89812: Clean up pathlib tests. (python#104829)

    Clean up pathlib tests.

    Merge `PurePathTest` into `_BasePurePathTest`, and `PathTest` into
    `_BasePathTest`.

commit b95de96
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 05:34:11 2023 +0200

    pythongh-105751: test_ctypes avoids "from ctypes import *" (python#105768)

    Using "import *" prevents linters like pyflakes to detect undefined names
    (usually missing imports).

    Replace c_voidp with c_void_p.

commit 381a1dc
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 04:47:01 2023 +0200

    pythongh-105751: test_ctypes.test_numbers uses top level imports (python#105762)

    Moroever, c_ulonglong and c_bool are always available.

commit ac7b551
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 04:46:47 2023 +0200

    pythongh-105751: test_ctypes gets Windows attrs from ctypes (python#105758)

    test_ctypes now gets attributes specific to Windows from the ctypes
    module, rather than relying on "from ctypes import *".

    Attributes:

    * ctypes.FormatError
    * ctypes.WINFUNCTYPE
    * ctypes.WinError
    * ctypes.WinDLL
    * ctypes.windll
    * ctypes.oledll
    * ctypes.get_last_error()
    * ctypes.set_last_error()

commit b87d288
Author: Eric Snow <ericsnowcurrently@gmail.com>
Date:   Tue Jun 13 18:58:23 2023 -0600

    pythongh-105699: Use a Thread-Local Variable for PKGCONTEXT (pythongh-105740)

    This fixes a race during import. The existing _PyRuntimeState.imports.pkgcontext is shared between interpreters, and occasionally this would cause a crash when multiple interpreters were importing extensions modules at the same time.  To solve this we add a thread-local variable for the value.  We also leave the existing state (and infrequent race) in place for platforms that do not support thread-local variables.

commit fcf0647
Author: Eric Snow <ericsnowcurrently@gmail.com>
Date:   Tue Jun 13 18:39:18 2023 -0600

    pythongh-104812: Skip Pending Calls Tests if No Threading (pythongh-105761)

    This fixes the WASM buildbots.

commit b542972
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 02:33:00 2023 +0200

    pythongh-105387: Limited C API implements Py_INCREF() as func (python#105388)

    In the limited C API version 3.12, Py_INCREF() and Py_DECREF()
    functions are now implemented as opaque function calls to hide
    implementation details.

commit f3266c0
Author: zentarim <33746047+zentarim@users.noreply.github.com>
Date:   Wed Jun 14 02:45:47 2023 +0300

    pythonGH-104554: Add RTSPS support to `urllib/parse.py` (python#104605)

    * pythonGH-104554: Add RTSPS support to `urllib/parse.py`

    RTSPS is the permanent scheme defined in
    https://www.iana.org/assignments/uri-schemes/uri-schemes.xhtml
    alongside RTSP and RTSPU schemes.

    * 📜🤖 Added by blurb_it.

    ---------

    Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>

commit 4cefe3c
Author: Steve Dower <steve.dower@python.org>
Date:   Wed Jun 14 00:00:16 2023 +0100

    pythongh-105436: Ignore unrelated errors when checking empty env (pythonGH-105742)

commit 457a459
Author: Victor Stinner <vstinner@python.org>
Date:   Wed Jun 14 00:32:12 2023 +0200

    pythongh-98040: Fix importbench: use types.ModuleType() (python#105743)

    Replace removed imp.new_module(name) with types.ModuleType(name).

commit 757b402
Author: Eric Snow <ericsnowcurrently@gmail.com>
Date:   Tue Jun 13 15:02:19 2023 -0600

    pythongh-104812: Run Pending Calls in any Thread (pythongh-104813)

    For a while now, pending calls only run in the main thread (in the main interpreter).  This PR changes things to allow any thread run a pending call, unless the pending call was explicitly added for the main thread to run.

commit 4e80082
Author: Łukasz Langa <lukasz@langa.pl>
Date:   Tue Jun 13 20:44:27 2023 +0000

    pythongh-102613: Bump recursion limit to fix running test_pathlib under Coverage (python#105744)

commit be2779c
Author: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
Date:   Tue Jun 13 21:42:03 2023 +0100

    pythongh-105481: add flags to each instr in the opcode metadata table, to replace opcode.hasarg/hasname/hasconst (python#105482)

commit 2211454
Author: Victor Stinner <vstinner@python.org>
Date:   Tue Jun 13 20:16:26 2023 +0200

    pythongh-105733: Deprecate ctypes SetPointerType() and ARRAY() (python#105734)

commit b97e14a
Author: Eric Snow <ericsnowcurrently@gmail.com>
Date:   Tue Jun 13 11:08:32 2023 -0600

    pythongh-105603: Change the PyInterpreterConfig.own gil Field (pythongh-105620)

    We are changing it to be more flexible that a strict bool can be for possible future expanded used cases.

commit abfbab6
Author: Lysandros Nikolaou <lisandrosnik@gmail.com>
Date:   Tue Jun 13 17:18:11 2023 +0200

    pythongh-105718: Fix buffer allocation in tokenizer with readline (python#105728)

commit d0f1afd
Author: Victor Stinner <vstinner@python.org>
Date:   Tue Jun 13 13:49:36 2023 +0200

    pythongh-105373: Remove PyArg_Parse() deprecation (python#105394)

    There is no plan to deprecate PyArg_Parse().

    The deprecation was added as a comment in the C API documentation in
    2007 by commit 85eb8c1.

commit ed8217b
Author: Lysandros Nikolaou <lisandrosnik@gmail.com>
Date:   Tue Jun 13 12:39:29 2023 +0200

    pythongh-105713: Document that tokenize raises when mixing tabs/spaces (python#105723)

    * pythongh-105713: Document that tokenize raises when mixing tabs/spaces
    * Update Doc/whatsnew/3.12.rst

    Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com>

commit c3d2d64
Author: Mark Shannon <mark@hotpy.org>
Date:   Tue Jun 13 10:34:27 2023 +0100

    Fix magic number (pythonGH-105722)

commit 09ffa69
Author: Mark Shannon <mark@hotpy.org>
Date:   Tue Jun 13 09:51:05 2023 +0100

    pythonGH-105678: Split MAKE_FUNCTION into MAKE_FUNCTION and SET_FUNCTION_ATTRIBUTE (pythonGH-105680)

commit 217589d
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Tue Jun 13 10:38:01 2023 +0200

    pythongh-105375: Improve error handling in _Unpickler_SetInputStream() (python#105667)

    Prevent exceptions from possibly being overwritten in case of multiple
    failures.

commit 840d02f
Author: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Date:   Tue Jun 13 11:36:40 2023 +0530

    pythonGH-105684: Require `asyncio.Task` implementations to support `set_name` method (python#105685)

commit 829ac13
Author: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>
Date:   Tue Jun 13 11:11:34 2023 +0530

    pythonGH-104787: use bitfields in `_asyncio` (python#104788)

commit 8da9d1b
Author: Guido van Rossum <guido@python.org>
Date:   Mon Jun 12 14:55:15 2023 -0700

    pythongh-105540: Fix code generator tests (python#105707)

    This involves expanding PEEK, POKE and JUMPBY macros,
    and removing super and register tests (those features no longer exist).

commit ca3cc4b
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Mon Jun 12 23:35:07 2023 +0200

    pythongh-105375: Explicitly initialise all {Pickler,Unpickler}Object fields (python#105686)

    All fields must be explicitly initialised to prevent manipulation of
    uninitialised fields in dealloc.

    Align initialisation order with the layout of the object structs.

commit f0fb782
Author: Jay <74105438+weijay0804@users.noreply.github.com>
Date:   Tue Jun 13 04:29:02 2023 +0800

    pythongh-105331: Change `asyncio.sleep` to raise ``ValueError` for nan (python#105641)

    Co-authored-by: Guido van Rossum <gvanrossum@gmail.com>
    Co-authored-by: Kumar Aditya <59607654+kumaraditya303@users.noreply.github.com>

commit 9544948
Author: Guido van Rossum <guido@python.org>
Date:   Mon Jun 12 11:19:04 2023 -0700

    Remove support for legacy bytecode instructions (python#105705)

    (A legacy instruction is of the form `instr(FOOBAR)`,
    i.e. missing the `(... -- ...)` stack/cache effect annotation.)

commit b9e7dc7
Author: Guido van Rossum <guido@python.org>
Date:   Mon Jun 12 10:47:08 2023 -0700

    pythongh-105229: Remove syntactic support for super-instructions (python#105703)

    It will not be used again.

commit 4f7d3b6
Author: Dora203 <66343334+sku2000@users.noreply.github.com>
Date:   Tue Jun 13 00:14:55 2023 +0800

    pythongh-105436: The environment block should end with two null wchar_t values (pythonGH-105495)

commit 2b90796
Author: Petr Viktorin <encukou@gmail.com>
Date:   Mon Jun 12 17:45:49 2023 +0200

    pythongh-103968: PyType_FromMetaclass: Allow metaclasses with tp_new=NULL (pythonGH-105386)

commit 58f0bda
Author: Steve Dower <steve.dower@python.org>
Date:   Mon Jun 12 16:09:14 2023 +0100

    ARM64 clamping bug also exists in MSVC 14.35 (pythonGH-105679)

commit a8d69fe
Author: Nikita Sobolev <mail@sobolevn.me>
Date:   Mon Jun 12 11:47:56 2023 +0300

    pythongh-105673: Fix uninitialized warning in sysmodule.c (python#105674)

    In sys_add_xoption(), 'value' may be uninitialized for some error paths.

commit 58f5227
Author: Irit Katriel <1055913+iritkatriel@users.noreply.github.com>
Date:   Sun Jun 11 22:31:59 2023 +0100

    pythongh-105481: add pseudo-instructions to the bytecodes DSL (python#105506)

commit 20a56d8
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 22:18:46 2023 +0200

    pythongh-105375: Harden pyexpat initialisation (python#105606)

    Add proper error handling to add_errors_module() to prevent exceptions
    from possibly being overwritten.

commit 41cddc2
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 22:02:49 2023 +0200

    pythongh-105375: Improve error handling in the sys extension module (python#105611)

    In _PySys_AddXOptionWithError() and sys_add_xoption(),
    bail on first error to prevent exceptions from possibly being
    overwritten.

commit e8998e4
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 21:46:19 2023 +0200

    pythongh-105375: Improve error handling in _ctypes (python#105593)

    Prevent repeated PyLong_FromVoidPtr() from possibly overwriting the
    current exception.

commit 555be81
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 21:29:19 2023 +0200

    pythongh-105375: Improve error handling in PyUnicode_BuildEncodingMap() (python#105491)

    Bail on first error to prevent exceptions from possibly being overwritten.

commit 567d6ae
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 21:23:28 2023 +0200

    pythongh-105375: Improve PyErr_WarnExplicit() error handling (python#105610)

    Bail on first error to prevent exceptions from possibly being
    overwritten.

commit 3f7c081
Author: Samet YASLAN <sametyaslan@gmail.com>
Date:   Sun Jun 11 20:51:21 2023 +0200

    bpo-44185: Added close() to mock_open __exit__ (python#26902)

commit 18d16e9
Author: Tomas R <tomas.roun8@gmail.com>
Date:   Sun Jun 11 17:50:34 2023 +0200

    pythongh-102676: Add more convenience properties to `dis.Instruction` (python#103969)

    Adds start_offset, cache_offset, end_offset, baseopcode,
    baseopname, jump_target and oparg to dis.Instruction.

    Also slightly improves the disassembly output by allowing
    opnames to overflow into the space reserved for opargs.

commit 845e593
Author: litlighilit <97860435+litlighilit@users.noreply.github.com>
Date:   Sun Jun 11 22:06:42 2023 +0800

    Fix typo in configparser module docstring (python#105652)

    "zc.buildbot" -> "zc.buildout"

commit d4fa529
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 12:20:43 2023 +0200

    pythongh-105375: Improve error handling in the builtins extension module (python#105585)

commit c932f72
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 12:06:06 2023 +0200

    pythongh-105375: Improve _decimal error handling (python#105605)

    Fix a bug where an exception could end up being overwritten.

commit 16d4968
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 12:03:09 2023 +0200

    pythongh-105375: Harden _datetime initialisation (python#105604)

    Improve error handling so init bails on the first exception.

commit 35cff54
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 11:58:08 2023 +0200

    pythongh-105375: Improve array.array exception handling (python#105594)

    Fix a bug where 'tp_richcompare' could end up overwriting an exception.

commit 01f4230
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Sun Jun 11 11:56:32 2023 +0200

    pythongh-105375: Harden _ssl initialisation (python#105599)

    Add proper error handling to prevent reference leaks and overwritten
    exceptions.

commit cc87948
Author: Hugo van Kemenade <hugovk@users.noreply.github.com>
Date:   Sun Jun 11 12:17:35 2023 +0300

    pythongh-80480: Emit DeprecationWarning for array's 'u' type code (python#95760)

commit 3a314f7
Author: Gregory P. Smith <greg@krypto.org>
Date:   Sat Jun 10 12:09:20 2023 -0700

    pythongh-99108: Mention HACL\* in the hashlib docs. (python#105634)

commit 0d1d6ab
Author: Gregory P. Smith <greg@krypto.org>
Date:   Sat Jun 10 11:49:06 2023 -0700

    Cleanup and clarify our hashlib docs. (python#105624)

    Clarify and improve our hashlib docs. Now with 50% less mess!

commit d636d7d
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 23:53:33 2023 +0200

    pythongh-105375: Harden error handling in `_testcapi/heaptype.c` (python#105608)

    Bail on first error in heapctypesubclasswithfinalizer_finalize()

commit 33c92c4
Author: Nikita Sobolev <mail@sobolevn.me>
Date:   Sat Jun 10 00:48:54 2023 +0300

    pythongh-105375: Improve error handling in `zoneinfo` module (python#105586)

    Fix bugs where exceptions could end up being overwritten
    because of deferred error handling.

    Co-authored-by: Erlend E. Aasland <erlend.aasland@protonmail.com>

commit 91441bf
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 23:14:02 2023 +0200

    Docs: fix formatting in 2023-06-09-12-59-18 NEWS item (python#105607)

commit b047fa5
Author: Pablo Galindo Salgado <Pablogsal@gmail.com>
Date:   Fri Jun 9 21:39:01 2023 +0100

    pythongh-105549: Tokenize separately NUMBER and NAME tokens and allow 0-prefixed literals (python#105555)

commit 00b599a
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 22:35:03 2023 +0200

    pythongh-105375: Improve error handling in _elementtree (python#105591)

    Fix bugs where exceptions could end up being overwritten.

commit f668f73
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 22:07:47 2023 +0200

    pythongh-105375: Improve posix error handling (python#105592)

    Fix a bug where an IndexError could end up being overwritten.

commit eede1d2
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 21:57:25 2023 +0200

    pythongh-105375: Improve errnomodule error handling (python#105590)

    Bail immediately if an exception is set, to prevent exceptions from
    being overwritten.

commit 89aac6f
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 19:09:53 2023 +0200

    pythongh-105375: Improve _pickle error handling (python#105475)

    Error handling was deferred in some cases, which could potentially lead
    to exceptions being overwritten.

commit 6c832dd
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 18:55:53 2023 +0200

    pythongh-105375: Improve error handling in compiler_enter_scope() (python#105494)

commit d7f46bc
Author: Pablo Galindo Salgado <Pablogsal@gmail.com>
Date:   Fri Jun 9 17:01:26 2023 +0100

    pythongh-105564: Don't include artificial newlines in the line attribute of tokens (python#105565)

commit 1dd267a
Author: Pablo Galindo Salgado <Pablogsal@gmail.com>
Date:   Fri Jun 9 16:59:37 2023 +0100

    Clarify the supported cases in the tokenize module (python#105569)

commit 59f009e
Author: Ethan Furman <ethan@stoneleaf.us>
Date:   Fri Jun 9 08:56:05 2023 -0700

    pythongh-105497: [Enum] Fix Flag inversion when alias/mask members exist. (pythonGH-105542)

    When inverting a Flag member (or boundary STRICT), only consider other canonical flags; when inverting an IntFlag member (or boundary KEEP), also consider aliases.

commit 8e75592
Author: Alex Waygood <Alex.Waygood@Gmail.com>
Date:   Fri Jun 9 16:08:57 2023 +0100

    Miscellaneous improvements to the typing docs (python#105529)

    Mostly, these are changes so that we use shorter sentences and shorter paragraphs. In particular, I've tried to make the first sentence introducing each object in the typing API short and declarative.

commit b8fa7bd
Author: Erlend E. Aasland <erlend.aasland@protonmail.com>
Date:   Fri Jun 9 15:36:59 2023 +0200

    pythongh-105557: Remove duplicate sqlite3 test method (python#105558)

    test_func_return_too_large_int() was defined twice.
    Keep only the redefined method, as that also checks the tracebacks.

commit 9bf8d82
Author: Thomas Grainger <tagrain@gmail.com>
Date:   Fri Jun 9 14:29:09 2023 +0100

    pythongh-94924: support `inspect.iscoroutinefunction` in `create_autospec(async_def)` (python#94962)

    * support inspect.iscoroutinefunction in create_autospec(async_def)

    * test create_autospec with inspect.iscoroutine and inspect.iscoroutinefunction

    * test when create_autospec functions check their signature

commit 0f885ff
Author: Victor Stinner <vstinner@python.org>
Date:   Fri Jun 9 14:50:31 2023 +0200

    pythongh-105407: Remove unused imports (python#105554)
@iritkatriel iritkatriel added the interpreter-core (Objects, Python, Grammar, and Parser dirs) label Nov 27, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
interpreter-core (Objects, Python, Grammar, and Parser dirs) type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

6 participants