Skip to content

Segfault in 3.13 when calling PyEval_SetTrace from a thread with no Python frames #121814

Closed
@godlygeek

Description

@godlygeek

Bug report

Bug description:

Given a setup.py with:

from setuptools import Extension
from setuptools import setup

setup(
    name="testext",
    version="0.0",
    ext_modules=[
        Extension("testext", language="c++", sources=["testext.cpp"]),
    ],
    zip_safe=False,
)

and a testext.cpp with:

#define PY_SSIZE_T_CLEAN
#include <Python.h>

#include <assert.h>
#include <pthread.h>
#include <unistd.h>

int tracefunc(PyObject *, PyFrameObject *, int, PyObject *)
{
    return 0;
}

void*
thread_body(void*)
{
    PyGILState_STATE gilstate = PyGILState_Ensure();
    PyEval_SetTrace(&tracefunc, Py_None);
    PyGILState_Release(gilstate);
    return NULL;
}

PyObject*
trace_in_thread(PyObject*, PyObject*)
{
    pthread_t thread;
    int ret = pthread_create(&thread, NULL, &thread_body, NULL);
    assert(0 == ret);

    Py_BEGIN_ALLOW_THREADS
    ret = pthread_join(thread, NULL);
    assert(0 == ret);
    Py_END_ALLOW_THREADS

    Py_RETURN_NONE;
}

static PyMethodDef methods[] = {
        {"trace_in_thread", trace_in_thread, METH_NOARGS, "Call PyEval_SetTrace in a thread"},
        {NULL, NULL, 0, NULL},
};

static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "testext", "", -1, methods};

PyMODINIT_FUNC
PyInit_testext(void)
{
    return PyModule_Create(&moduledef);
}

doing:

python3.13 -m pip install .
python3.13 -c 'import testext; testext.trace_in_thread()'

gives a segmentation fault, because of this code in _PyEval_SetTrace:

PyFrameObject* frame = PyEval_GetFrame();
if (frame->f_trace_opcodes) {

This reproducer enters _PyEval_SetTrace with no Python frames on the stack, and so PyEval_GetFrame returns a null pointer and frame->f_trace_opcodes dereferences it. It seems that this needs to be guarded:

        PyFrameObject* frame = PyEval_GetFrame();
        if (frame && frame->f_trace_opcodes) {

CPython versions tested on:

3.13

Operating systems tested on:

Linux

Linked PRs

Metadata

Metadata

Assignees

No one assigned

    Labels

    type-bugAn unexpected behavior, bug, or error

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions