Skip to content

Conversation

Yun-Kim
Copy link
Contributor

@Yun-Kim Yun-Kim commented Jan 12, 2023

Description

#4511 added support for Python 3.11 for the profiler, but missed some PyFrameObject-related upgrades required to be compatible with Python 3.11, most notably in the stack collector's traceback module. Specifically, PyFrameObjects and its member values are now lazily created/computed, which means we can no longer directly access its member values.
According to https://docs.python.org/3/whatsnew/3.11.html#pyframeobject-3-11-hiding, we need to use get functions to access its member values.

Checklist

Motivation

Design

Testing strategy

Relevant issue(s)

Testing strategy

Reviewer Checklist

  • Title is accurate.
  • Description motivates each change.
  • No unnecessary changes were introduced in this PR.
  • Avoid breaking API changes unless absolutely necessary.
  • Tests provided or description of manual testing performed is included in the code or PR.
  • Release note has been added and follows the library release note guidelines, or else changelog/no-changelog label added.
  • All relevant GitHub issues are correctly linked.
  • Backports are identified and tagged with Mergifyio.

@Yun-Kim Yun-Kim force-pushed the yunkim/profiler-3-11-fix branch from a73455a to afb2b8e Compare January 12, 2023 19:53
@Yun-Kim Yun-Kim force-pushed the yunkim/profiler-3-11-fix branch from afb2b8e to 3bd4a59 Compare January 12, 2023 19:54
Copy link
Contributor Author

@Yun-Kim Yun-Kim left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@P403n1x87 At first glance it looks like it's only the _traceback.pyx module that works with PyFrameObjects, but to be fair this is the only obvious fix relating to Python 3.11. Would love your feedback/second look 🙇

@Yun-Kim Yun-Kim requested a review from P403n1x87 January 12, 2023 20:14
@Yun-Kim Yun-Kim force-pushed the yunkim/profiler-3-11-fix branch 9 times, most recently from cb63bdd to d5eb8c6 Compare January 17, 2023 21:41
@Yun-Kim Yun-Kim force-pushed the yunkim/profiler-3-11-fix branch from d5eb8c6 to 0004bd1 Compare January 17, 2023 21:45
lineno = PyFrame_GetLineNumber(<PyFrameObject*> frame)
lineno = 0 if lineno is None else lineno
frames.append(((<object>code).co_filename, lineno, (<object>code).co_name, _extract_class_name(frame)))
frame = <object>PyFrame_GetBack(<PyFrameObject*> frame)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PyFrame_GetBack() returns a strong reference. Should I be calling Py_XDECREF(frame) even though we are iterating through these references?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the frame isn't actually needed anymore after L114 right? since we are creating/returning a list of tuples?

does the frame getting GC'd cause co_filename/co_name/etc to also get GC'd? are we appropriately incref/decref-ing those references?

frames.append(((<object>code).co_filename, lineno, (<object>code).co_name, _extract_class_name(<object>pyframe)))
Py_XDECREF(<PyObject*>code)
pyframe = PyFrame_GetBack(pyframe)
# FIXME: Where to Py_XDECREF(cframe)?
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/cframe/pyframe/ ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the catch!

I am looking for some suggestions on where to call Py_XDECREF(pyframe) though. Since PyFrame_GetBack(pyframe) returns a strong reference of the PyFrameObject*, should I be decrementing the refcount for every time we call PyFrame_GetBack(pyframe)? But since we're using the result of the PyFrame_GetBack() in the while loop, I don't think I can decrement the refcount without interfering with the rest of the function.

Copy link
Contributor

@P403n1x87 P403n1x87 Jan 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Py_XDECREF(pyframe) has to be called every time you are done with that particular pyframe reference, so within the loop, but before overwriting the variable's value. The cast to <object> is taking care of ref counting when passing values around in Cython, so as long as our ref counting for when we invoke the C API directly is correct we should be good.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you might need to do something like:

cdef PyFrameObject* cur_frame = pyframe
pyframe = PyFrame_GetBack(cur_frame)
Py_XDECREF(cur_frame)

? and then a final Py_XDECREF(pyframe) after the while ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this makes sense. Trying that now.

Copy link
Contributor

@P403n1x87 P403n1x87 Jan 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would have thought that

Py_XDECREF(pyframe)
pyframe = PyFrame_GetBack(pyframe)

is enough, since we are manipulating Python objects and hence we're holding the GIL. But @brettlangdon's suggestion works too.

@Yun-Kim Yun-Kim force-pushed the yunkim/profiler-3-11-fix branch from d5b0a33 to 0f9e710 Compare January 20, 2023 20:02
Yun-Kim added a commit that referenced this pull request Jan 24, 2023
…ect (#4952)

## Description
As #4895 has not been merged yet and we don't want to block the 1.8
release any longer, this PR adds a release note entry publishing the
known issue of the profiler running in Python 3.11 with the new
`PyFrameObject` opaque struct changes.

<!-- If this is a breaking change, explain why it is necessary. Breaking
changes must append `!` after the type/scope. See
https://ddtrace.readthedocs.io/en/stable/contributing.html for more
details. -->

## Checklist
- [ ] Followed the [library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines)
when writing a release note.
- [ ] Add additional sections for `feat` and `fix` pull requests.
- [ ] [Library
documentation](https://github.com/DataDog/dd-trace-py/tree/1.x/docs)
and/or [Datadog's documentation
site](https://github.com/DataDog/documentation/) is updated. Link to doc
PR in description.

<!-- Copy and paste the relevant snippet based on the type of pull
request -->

<!-- START feat -->

## Motivation
<!-- Expand on why the change is required, include relevant context for
reviewers -->

## Design 
<!-- Include benefits from the change as well as possible drawbacks and
trade-offs -->

## Testing strategy
<!-- Describe the automated tests and/or the steps for manual testing.

<!-- END feat -->

<!-- START fix -->

## Relevant issue(s)
<!-- Link the pull request to any issues related to the fix. Use
keywords for links to automate closing the issues once the pull request
is merged. -->

## Testing strategy
<!-- Describe any added regression tests and/or the manual testing
performed. -->

<!-- END fix -->

## Reviewer Checklist
- [ ] Title is accurate.
- [ ] Description motivates each change.
- [ ] No unnecessary changes were introduced in this PR.
- [ ] Avoid breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes unless absolutely necessary.
- [ ] Tests provided or description of manual testing performed is
included in the code or PR.
- [ ] Release note has been added and follows the [library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines),
or else `changelog/no-changelog` label added.
- [ ] All relevant GitHub issues are correctly linked.
- [ ] Change contains telemetry where appropriate (logs, metrics, etc.).
- [ ] Telemetry is meaningful, actionable and does not have the
potential to leak sensitive data.
@Yun-Kim Yun-Kim mentioned this pull request Jan 25, 2023
emmettbutler pushed a commit that referenced this pull request Jan 30, 2023
…ect (#4952)

## Description
As #4895 has not been merged yet and we don't want to block the 1.8
release any longer, this PR adds a release note entry publishing the
known issue of the profiler running in Python 3.11 with the new
`PyFrameObject` opaque struct changes.

<!-- If this is a breaking change, explain why it is necessary. Breaking
changes must append `!` after the type/scope. See
https://ddtrace.readthedocs.io/en/stable/contributing.html for more
details. -->

## Checklist
- [ ] Followed the [library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines)
when writing a release note.
- [ ] Add additional sections for `feat` and `fix` pull requests.
- [ ] [Library
documentation](https://github.com/DataDog/dd-trace-py/tree/1.x/docs)
and/or [Datadog's documentation
site](https://github.com/DataDog/documentation/) is updated. Link to doc
PR in description.

<!-- Copy and paste the relevant snippet based on the type of pull
request -->

<!-- START feat -->

## Motivation
<!-- Expand on why the change is required, include relevant context for
reviewers -->

## Design 
<!-- Include benefits from the change as well as possible drawbacks and
trade-offs -->

## Testing strategy
<!-- Describe the automated tests and/or the steps for manual testing.

<!-- END feat -->

<!-- START fix -->

## Relevant issue(s)
<!-- Link the pull request to any issues related to the fix. Use
keywords for links to automate closing the issues once the pull request
is merged. -->

## Testing strategy
<!-- Describe any added regression tests and/or the manual testing
performed. -->

<!-- END fix -->

## Reviewer Checklist
- [ ] Title is accurate.
- [ ] Description motivates each change.
- [ ] No unnecessary changes were introduced in this PR.
- [ ] Avoid breaking
[API](https://ddtrace.readthedocs.io/en/stable/versioning.html#interfaces)
changes unless absolutely necessary.
- [ ] Tests provided or description of manual testing performed is
included in the code or PR.
- [ ] Release note has been added and follows the [library release note
guidelines](https://ddtrace.readthedocs.io/en/stable/contributing.html#Release-Note-Guidelines),
or else `changelog/no-changelog` label added.
- [ ] All relevant GitHub issues are correctly linked.
- [ ] Change contains telemetry where appropriate (logs, metrics, etc.).
- [ ] Telemetry is meaningful, actionable and does not have the
potential to leak sensitive data.
@Yun-Kim
Copy link
Contributor Author

Yun-Kim commented Feb 3, 2023

@P403n1x87 Closing this PR until we can confirm that the issue persists after #5019, in which case I'll reopen this.

@Yun-Kim Yun-Kim closed this Feb 3, 2023
@Yun-Kim Yun-Kim deleted the yunkim/profiler-3-11-fix branch April 4, 2023 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants