I am trying to create the __reduce__
method for a C extension type for Python I implemented so it become pickable
. I have already done it with other types, but for some reason in this case I am receiving a Segment Fault.
Here is the minimal reproducible example:
main.c
#define PY_SSIZE_T_CLEAN
#include <Python.h>
typedef struct
{
PyObject_HEAD unsigned char attr1;
unsigned char attr2;
unsigned char attr3;
} SomeObject;
static int SomeObject__init(SomeObject *self, PyObject *args, PyObject *kwds)
{
static char *kwlist[] = {"attr1", "attr2", "attr3", NULL};
if (!PyArg_ParseTupleAndKeywords(args, kwds, "bbb", kwlist, &self->attr1,
&self->attr2, &self->attr3))
{
return -1;
}
return 0;
}
static PyObject *SomeObject__reduce(SomeObject *self, PyObject *Py_UNUSED(ignored))
{
return Py_BuildValue("O(BBB)N", Py_TYPE(self), self->attr1, self->attr2, self->attr3,
Py_None);
}
static PyMethodDef SomeObject__methods[] = {
{
.ml_name = "__reduce__",
.ml_meth = (PyCFunction)SomeObject__reduce,
.ml_flags = METH_NOARGS,
},
};
static PyTypeObject SomeType = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "somemodule.SomeObject",
.tp_basicsize = sizeof(SomeObject),
.tp_itemsize = 0,
.tp_flags = Py_TPFLAGS_DEFAULT,
.tp_methods = SomeObject__methods,
.tp_init = (initproc)SomeObject__init,
.tp_new = PyType_GenericNew,
};
static PyModuleDef somemodule = {
PyModuleDef_HEAD_INIT,
.m_name = "somemodule",
.m_size = -1,
};
PyMODINIT_FUNC
PyInit_somemodule(void)
{
if (PyType_Ready(&SomeType) < 0)
return NULL;
PyObject *m = PyModule_Create(&somemodule);
if (m == NULL)
return NULL;
Py_INCREF(&SomeType);
if (PyModule_AddObject(m, "Some", (PyObject *)&SomeType) < 0)
{
Py_DECREF(&SomeType);
Py_DECREF(m);
return NULL;
}
return m;
}
setup.py
from setuptools import setup, Extension
setup(
name="somemodule",
version="0.1.0",
ext_modules=[Extension("somemodule", ["main.c"])]
)
demo.py
import somemodule
somemodule.Some(12, 12, 12).__reduce__()
Here is the GDB output and backtrace:
GDB Output
$ gdb /home/xlurio/Playground/minimum-SIGSEGV/venv/bin/python -ex "run \"/home/xlurio/Playground/minimum-SIGSEGV/demo.py\""
Program received signal SIGSEGV, Segmentation fault.
0x000000000058da02 in PyUnicode_FromFormatV ()
(gdb) bt
#0 0x000000000058da02 in PyUnicode_FromFormatV ()
#1 0x000000000055cbaf in PyErr_Format ()
#2 0x00000000004d2924 in ?? ()
#3 0x00007ffff7fbe252 in PyInit_somemodule () at main.c:57
#4 0x0000000000685b4e in _PyImport_LoadDynamicModuleWithSpec ()
#5 0x0000000000686661 in ?? ()
#6 0x00000000005c52f0 in ?? ()
#7 0x00000000005f61c8 in PyVectorcall_Call ()
--Type <RET> for more, q to quit, c to continue without paging--
#8 0x0000000000571917 in _PyEval_EvalFrameDefault ()
#9 0x0000000000569cea in _PyEval_EvalCodeWithName ()
#10 0x00000000005f6a13 in _PyFunction_Vectorcall ()
#11 0x0000000000570ac2 in _PyEval_EvalFrameDefault ()
#12 0x00000000005f6836 in _PyFunction_Vectorcall ()
#13 0x000000000056bbdf in _PyEval_EvalFrameDefault ()
#14 0x00000000005f6836 in _PyFunction_Vectorcall ()
#15 0x000000000056b9fd in _PyEval_EvalFrameDefault ()
--Type <RET> for more, q to quit, c to continue without paging--
#16 0x00000000005f6836 in _PyFunction_Vectorcall ()
#17 0x000000000056b9fd in _PyEval_EvalFrameDefault ()
#18 0x00000000005f6836 in _PyFunction_Vectorcall ()
#19 0x000000000056b9fd in _PyEval_EvalFrameDefault ()
#20 0x00000000005f6836 in _PyFunction_Vectorcall ()
#21 0x00000000005f3c41 in ?? ()
#22 0x00000000005f40a8 in _PyObject_CallMethodIdObjArgs ()
#23 0x0000000000552f1c in PyImport_ImportModuleLevelObject ()
--Type <RET> for more, q to quit, c to continue without paging--
#24 0x000000000056ddd5 in _PyEval_EvalFrameDefault ()
#25 0x0000000000569cea in _PyEval_EvalCodeWithName ()
#26 0x000000000068e7b7 in PyEval_EvalCode ()
#27 0x0000000000680001 in ?? ()
#28 0x000000000068007f in ?? ()
#29 0x0000000000680121 in ?? ()
#30 0x0000000000680db7 in PyRun_SimpleFileExFlags ()
#31 0x00000000006b8122 in Py_RunMain ()
--Type <RET> for more, q to quit, c to continue without paging--
#32 0x00000000006b84ad in Py_BytesMain ()
#33 0x00007ffff7de4083 in __libc_start_main (main=0x4ef1e0 <main>, argc=2, argv=0x7fffffffd998, init=<optimized out>,
fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fffffffd988) at ../csu/libc-start.c:308
#34 0x00000000005fb39e in _start ()