Hi Musbur,

While python-dev is specifically for core development, the "specific interest group" mailing lists are for both change proposals and existing usage questions.

I've cc'ed capi-sig on this reply.

Cheers,
Nick.

On Sat., 4 Apr. 2020, 2:02 am Musbur, <musbur@posteo.org> wrote:
Hello,

(I've asked this question before on python-list but only got scarce
and ultimately unhelpful answers. Although this isn't about Python
development itself, I'm assuming that there is more CPython
knowledge on this list than on the other, so please bear with me.)

I've written a C extension module, each defining a class
(called Series and CLHist, respectively). I can import both modules in
Python and use the classes. Everything works fine, also according to
valgrind.

Now I want to return a Series instance directly from a CLHist
method, and that immediately crashes Python with a segfault.

Here's a bit of code and just the _new, _init, and _finalize methods
which I've sprinkled with debugging code. When I instantiate a Series
object from Python, I see output from all three methods. When I call
pyseries_new() from C, none of the three functions are called and it
crashes.

At some point I thought maybe I should call PyType_Ready() from the C
side before instantiating Series. In a "standard" (system) Python
installation, it printed the desired debugging output and crashed
later. Under a debugging Python installation I built it outputs
nothing except an interesting post-mortem "Fatal Python error: UNREF
invalid object" (see below).

Here's my C code with the boilerplate stuff left out.

typedef struct {
    PyObject_HEAD
    struct clh_series *series;
} Series;

static PyObject *Series_new(PyTypeObject *type,
        PyObject *args, PyObject *kw) {
    Series *self;

    self = (Series *) type->tp_alloc(type, 0);
    fprintf(stderr, "Series_new(%p)\n", self);
    self->series = NULL;
    return (PyObject*)self;
}

static int Series_init(Series *self, PyObject *args, PyObject *kw) {
    fprintf(stderr, "Series_init(%p)\n", self);
    self->series = NULL;
    return 0;
}

static void Series_finalize(PyObject *self) {
    fprintf(stderr, "Series_finalize(%p)\n", self);
    clh_series_free(((Series*)self)->series);
}

/* To create a new Series object directly from C */
PyObject *pyseries_new(struct clh_series *series) {
    Series *pyseries;

    pyseries = PyObject_New(Series, &series_type);
    PyObject_Init((PyObject *)pyseries, &series_type);
    pyseries->series = series;
    return (PyObject *) pyseries;
}

Here's the debugging output:

* ob
object  : <refcnt 0 at 0x7f1a4e2f97a8>
type    : tuple
refcount: 0
address : 0x7f1a4e2f97a8
* op->_ob_prev->_ob_next
object  : <_Series object at 0x7f1a4e2ee9d0>
type    : _Series
refcount: 1
address : 0x7f1a4e2ee9d0
* op->_ob_next->_ob_prev
object  : <refcnt 0 at 0x7f1a4e2f97a8>
type    : tuple
refcount: 0
address : 0x7f1a4e2f97a8
Fatal Python error: UNREF invalid object
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-leave@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/ILMRMQ64P7H6KHH2BZQPDYGXW773MOII/
Code of Conduct: http://python.org/psf/codeofconduct/