python / python/cpython

profiling.sampling incorrectly handles base_frame and native frame as the first frame

Abierto
#157,605 6 comentarios 0 reacciones 0 asignados Ver en GitHub

Nadie ha tomado este issue todavía.

extension-modules topic-profiling type-bug
Lenguaje dominante
Python
Estrellas
77.2k
Forks
35.9k
Métricas de merge de PR
Métricas de PR pendientes

Descripción

Bug description

profiling.sampling does not correctly handle some frame chains whose first frame is not a Python frame.

There are two cases:

  1. The first frame is base_frame

    A native thread can retain a Python thread state while waiting in C code, with no Python functions executing. Its frame chain contains only the base_frame sentinel.

    The sampler skips this sentinel and then raises:

    RuntimeError: Failed to parse initial frame in chain

  2. The first frame is a native frame

    When the first frame in the chain is a native frame, the sampler does not correctly handle it as the initial frame and may report the frame chain as invalid instead of adding a <native> frame.

In both cases, the failure can cause the entire sampling call to fail, so valid Python stacks from other threads are also lost.

Reproduction

Case 1: base_frame as the first frame

Create a pthread that registers and detaches a Python thread state:

PyGILState_STATE state = PyGILState_Ensure();
PyThreadState *saved = PyEval_SaveThread();

/* Wait on a pthread condition variable while the parent samples. */

/* Cleanup after sampling. */
PyEval_RestoreThread(saved);
PyGILState_Release(state);

Keep the main thread inside a Python function and sample the child process from its parent:

unwinder = _remote_debugging.RemoteUnwinder(
    pid, all_threads=True, cache_frames=False,
)
unwinder.get_stack_trace()

tachyon-empty-native-repro.zip

  • Reproduces with frame caching both enabled and disabled.
Case 2: Native frame as the first frame

Construct a frame chain whose current frame is a native frame and whose previous frame leads to base_frame.

When native-frame collection is enabled, sampling this thread currently fails to correctly handle the native frame as the first frame.

Expected behavior

The sampler should correctly handle both cases:

  1. If the first frame is base_frame, treat it as a valid empty Python stack.
  2. If the first frame is a native frame, add a <native> frame to the returned stack and continue walking the frame chain.

A special frame state in one thread should not cause the entire sampling operation to fail or prevent valid stacks from other threads from being returned.

Suspected cause

process_frame_chain() does not correctly handle cases where the first frame does not contain a parseable Python frame, including base_frame and native frames.

These cases can be incorrectly treated as a broken initial frame chain.

Environment

Linux, CPython 3.15.0rc2+dev free-threaded build and current main.

Linked PRs
  • gh-157817

Guía de contribución

Abrir la guía de contribución

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Línea de trabajo

Comienza rastreando process_frame_chain(), centrándote en cómo maneja base_frame y un frame nativo como primer frame. Usa la reproducción proporcionada con pthread y el escenario de frame nativo para ejercitar ambos caminos. Se considera terminado cuando base_frame produce una pila de Python vacía válida, los frames nativos añaden un frame y un hilo especial no descarta las pilas válidas de otros hilos.

Escrito por el modelo de indexación a partir del texto del issue.

Evaluación

Stack tecnológico
c, python
Área
performance
Tipo de issue
Error
Dificultad
4/5
Tiempo estimado
3-5 días
Estado de actividad
Activo
Claridad
Bastante claro
Aptitud para principiantes
55/100

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.