Skip to content

Commit

Permalink
fix(profiler): version gate python 3.11 changes to stack collector (#…
Browse files Browse the repository at this point in the history
…4448)

From #4125, two sections in the stack collector were modified to reflect Python 3.11 changes. However, those changes are not the exact same logic as the former code, including version gating and exception representation. I'm specifically applying these changes only if Python 3.11 or higher are being run. Otherwise, it is being reverted to what it was prior to #4125.

While I'm unsure what is exactly causing the issue, we saw an issue (only when the profiler was activated) when running dogweb CI where tests involving sqlalchemy failed on setup with sessions becoming immediately inactive before any queries were run. Furthermore, we saw failures in asyncpg framework tests and major memory/CPU usage spikes when #4125 was merged into 1.x, both of which went away with this fix.

(cherry picked from commit 6bc6ff1)
  • Loading branch information
Yun-Kim authored and mergify[bot] committed Nov 3, 2022
1 parent 40111cb commit 324026b
Showing 1 changed file with 16 additions and 12 deletions.
28 changes: 16 additions & 12 deletions ddtrace/profiling/collector/stack.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -240,22 +240,26 @@ cdef collect_threads(thread_id_ignore_list, thread_time, thread_span_links) with
tstate = PyInterpreterState_ThreadHead(interp)
while tstate:
# The frame can be NULL
# Python 3.9 added helper function to public C API to access PyFrameObject from tstate,
# Python 3.11 moved PyFrameObject to internal C API and cannot be directly accessed from tstate
IF PY_MINOR_VERSION >= 9:
IF PY_MINOR_VERSION >= 11:
frame = PyThreadState_GetFrame(tstate)
if frame:
running_threads[tstate.thread_id] = <object>frame
exc_info = _PyErr_GetTopmostException(tstate)
if exc_info and exc_info.exc_value:
# Python 3.11 removed exc_type, exc_traceback from exception representations,
# can instead derive exc_type and exc_traceback from remaining exc_value field
exc_type = Py_TYPE(exc_info.exc_value)
exc_tb = PyException_GetTraceback(exc_info.exc_value)
if exc_type and exc_tb:
current_exceptions[tstate.thread_id] = (<object>exc_type, <object>exc_tb)
ELSE:
frame = tstate.frame
if frame:
running_threads[tstate.thread_id] = <object>frame
exc_info = _PyErr_GetTopmostException(tstate)
if exc_info and exc_info.exc_value:
# Python 3.11 removed exc_type, exc_traceback from exception representations, can instead
# derive exc_type and exc_traceback from remaining exc_value field
exc_type = Py_TYPE(exc_info.exc_value)
exc_tb = PyException_GetTraceback(exc_info.exc_value)
if exc_type and exc_tb:
current_exceptions[tstate.thread_id] = (<object>exc_type, <object>exc_tb)
if frame:
running_threads[tstate.thread_id] = <object>frame
exc_info = _PyErr_GetTopmostException(tstate)
if exc_info and exc_info.exc_type and exc_info.exc_traceback:
current_exceptions[tstate.thread_id] = (<object>exc_info.exc_type, <object>exc_info.exc_traceback)
tstate = PyThreadState_Next(tstate)

interp = PyInterpreterState_Next(interp)
Expand Down

0 comments on commit 324026b

Please sign in to comment.