profiling.sampling incorrectly handles base_frame and native frame as the first frame
Ninguém assumiu esta issue ainda.
- Linguagem predominante
- Python
- Estrelas
- 77.2k
- Forks
- 35.9k
- Métricas de merge de PRs
- Métricas de PR pendentes
Descrição
Bug description
profiling.sampling does not correctly handle some frame chains whose first frame is not a Python frame.
There are two cases:
-
The first frame is
base_frameA 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_framesentinel.The sampler skips this sentinel and then raises:
RuntimeError: Failed to parse initial frame in chain -
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:
- If the first frame is
base_frame, treat it as a valid empty Python stack. - 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
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Direção de pesquisa
Comece rastreando process_frame_chain(), concentrando-se em como ele lida com base_frame e um frame nativo como o primeiro frame. Use a reprodução fornecida com pthread e o cenário de frame nativo para exercitar os dois caminhos. A tarefa estará concluída quando base_frame produzir uma pilha Python vazia válida, os frames nativos adicionarem um frame e uma thread especial não descartar pilhas válidas de outras threads.
Escrita pelo modelo de indexação a partir do texto da issue.
Avaliação
- Stack de tecnologia
- c, python
- Domínio
- performance
- Tipo de issue
- Bug
- Dificuldade
- 4/5
- Tempo estimado
- 3-5 dias
- Status de atividade
- Ativa
- Clareza
- Razoavelmente clara
- Facilidade para iniciantes
- 55/100