Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subclass introspection from Python causes segfault #240

Closed
pganssle opened this issue Sep 28, 2018 · 8 comments
Closed

Subclass introspection from Python causes segfault #240

pganssle opened this issue Sep 28, 2018 · 8 comments

Comments

@pganssle
Copy link
Member

pganssle commented Sep 28, 2018

馃悰 Bug Reports

If you declare a Python class as such:

#![feature(specialization)]

use pyo3::prelude::*;
use pyo3::types::PyTzInfo;

#[pyclass(extends=PyTzInfo)]
pub struct TzClass {}

#[pymodinit]
fn foo(_py: Python, m: &PyModule) -> PyResult<()> {
    m.add_class::<TzClass>()?;
}

Then attempt to to do anything that accesses __class__, e.g.:

repr(foo.TzClass())
foo.TzClass().__class__

It will cause a segmentation fault in the interpreter.

PR adding a test for this and with more details: #239.

@konstin konstin added the bug label Sep 28, 2018
@kngwyu
Copy link
Member

kngwyu commented Sep 29, 2018

Just curious, I tried

    m.add_class::<PyTzInfo>()?;

and got

>>> import rustapi_module.datetime as rdt
>>> rdt.PyTzInfo().__class__
<class 'datetime.tzinfo'>

So, it looks not a datetime FFI problem, but our generated code has some problems.

@kngwyu
Copy link
Member

kngwyu commented Sep 29, 2018

>>> rdt.TzClass().__class__.self
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'rustapi_module.datetime.TzClass' has no attribute 'self'
>>> rdt.TzClass().__repr__()
fish: 'python' terminated by signal SIGSEGV (Address boundary error)

looks SIGSEGV happens in __repr__.

@pganssle
Copy link
Member Author

@kngwyu Seems like it's either specific to the fact that it's a subclass or specific to being a subclass of PyTzInfo, because repr works fine for rustapi_module.othermod.ModClass (see #241).

@pganssle
Copy link
Member Author

Same thing happens if the argument to extends is PyDateTime or PyDict, so it seems to be a general problem with subclassing.

@kngwyu kngwyu added the hard label Oct 1, 2018
@joar
Copy link
Contributor

joar commented Oct 12, 2018

Another subclass-related segfault is #220

@kngwyu
Copy link
Member

kngwyu commented Nov 8, 2018

got a gdb backtrace

(gdb) file python
Reading symbols from python...(no debugging symbols found)...done.
(gdb) run minitest.py
Starting program: /home/mio_h/Programs/pyo3/examples/rustapi_module/.tox/py/bin/python minitest.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/usr/lib/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7b222a0 in ?? () from /usr/lib/libpython3.7m.so.1.0
(gdb) bt
#0  0x00007ffff7b222a0 in ?? () from /usr/lib/libpython3.7m.so.1.0
#1  0x00007ffff7aaba77 in ?? () from /usr/lib/libpython3.7m.so.1.0
#2  0x00007ffff7b7eb76 in PyObject_Repr () from /usr/lib/libpython3.7m.so.1.0
#3  0x00007ffff7b6f118 in _PyMethodDef_RawFastCallKeywords ()
   from /usr/lib/libpython3.7m.so.1.0
#4  0x00007ffff7b6f461 in _PyCFunction_FastCallKeywords ()
   from /usr/lib/libpython3.7m.so.1.0
#5  0x00007ffff7bdea75 in _PyEval_EvalFrameDefault ()
   from /usr/lib/libpython3.7m.so.1.0
#6  0x00007ffff7b28879 in _PyEval_EvalCodeWithName ()
   from /usr/lib/libpython3.7m.so.1.0
#7  0x00007ffff7b297a4 in PyEval_EvalCodeEx ()
   from /usr/lib/libpython3.7m.so.1.0
#8  0x00007ffff7b297cc in PyEval_EvalCode () from /usr/lib/libpython3.7m.so.1.0
#9  0x00007ffff7c521e4 in ?? () from /usr/lib/libpython3.7m.so.1.0
#10 0x00007ffff7c536ee in PyRun_FileExFlags ()
   from /usr/lib/libpython3.7m.so.1.0
#11 0x00007ffff7c56c45 in PyRun_SimpleFileExFlags ()
   from /usr/lib/libpython3.7m.so.1.0
#12 0x00007ffff7c58f43 in ?? () from /usr/lib/libpython3.7m.so.1.0
#13 0x00007ffff7c5914c in _Py_UnixMain () from /usr/lib/libpython3.7m.so.1.0
#14 0x00007ffff7db7223 in __libc_start_main () from /usr/lib/libc.so.6
#15 0x000055555555505e in _start ()

with minitest.py

import rustapi_module.datetime as rdt

if __name__ == "__main__":
    tzi = rdt.TzClass()
    assert tzi.__class__ == rdt.TzClass
    assert repr(tzi) == "TzClass()"

@kngwyu
Copy link
Member

kngwyu commented Nov 8, 2018

I checked that PyObjectAlloc::dealloc is called but PyObjectAlloc::alloc isn't called, when executing
EDITED: it looks intended behavior

import rustapi_module.datetime as rdt

if __name__ == "__main__":
    tzi = rdt.TzClass()
    assert tzi.__class__ == rdt.TzClass

So maybe it's because we don't call init_type for super class when subclassing?

@kngwyu
Copy link
Member

kngwyu commented Nov 9, 2018

More precise backtrace with python3.8 debug build

Program received signal SIGSEGV, Segmentation fault.
0x0000555555611e74 in type_qualname (
    type=type@entry=0x7ffff76361d8 <<rustapi_module::TzClass as pyo3::typeob::PyTypeInfo>::type_object::TYPE_OBJECT>, context=context@entry=0x0)
    at ../Objects/typeobject.c:424
424	        Py_INCREF(et->ht_qualname);
(gdb) bt
#0  0x0000555555611e74 in type_qualname (
    type=type@entry=0x7ffff76361d8 <<rustapi_module::TzClass as pyo3::typeob::PyTypeInfo>::type_object::TYPE_OBJECT>, context=context@entry=0x0)
    at ../Objects/typeobject.c:424
#1  0x00005555556120d3 in object_repr (self=0x7ffff77f52c0)
    at ../Objects/typeobject.c:3751
#2  0x000055555560ae2d in object_str (self=<optimized out>)
    at ../Objects/typeobject.c:3774
#3  0x00005555555f7b74 in PyObject_Str (v=0x7ffff77f52c0)
    at ../Objects/object.c:525
#4  0x0000555555657de5 in unicode_new (type=<optimized out>, 
    args=<optimized out>, kwds=<optimized out>)
    at ../Objects/unicodeobject.c:14974
#5  0x0000555555613315 in type_call (type=0x5555558635a0 <PyUnicode_Type>, 
    args=0x7ffff76e95f0, kwds=0x0) at ../Objects/typeobject.c:929
#6  0x00005555555c0b93 in _PyObject_FastCallKeywords (
    callable=callable@entry=0x5555558635a0 <PyUnicode_Type>, 
    stack=stack@entry=0x55555595e570, nargs=nargs@entry=1, 
    kwnames=kwnames@entry=0x0) at ../Objects/call.c:199
#7  0x0000555555679596 in call_function (kwnames=0x0, oparg=<optimized out>, 
    pp_stack=<synthetic pointer>) at ../Python/ceval.c:4626
#8  _PyEval_EvalFrameDefault (f=0x55555595e3f0, throwflag=<optimized out>)
    at ../Python/ceval.c:3200
--Type <RET> for more, q to quit, c to continue without paging--
#9  0x000055555566d6ab in PyEval_EvalFrameEx (f=f@entry=0x55555595e3f0, 
    throwflag=throwflag@entry=0) at ../Python/ceval.c:536
#10 0x000055555566e16e in _PyEval_EvalCodeWithName (_co=0x7ffff769e040, 
    globals=<optimized out>, locals=<optimized out>, args=<optimized out>, 
    argcount=argcount@entry=0, kwnames=0x0, kwargs=0x0, kwcount=0, kwstep=2, 
    defs=0x0, defcount=0, kwdefs=0x0, closure=0x0, name=0x0, qualname=0x0)
    at ../Python/ceval.c:3951
#11 0x000055555566e346 in PyEval_EvalCodeEx (_co=_co@entry=0x7ffff769e040, 
    globals=globals@entry=0x7ffff772b440, locals=locals@entry=0x7ffff772b440, 
    args=args@entry=0x0, argcount=argcount@entry=0, kws=kws@entry=0x0, 
    kwcount=0, defs=0x0, defcount=0, kwdefs=0x0, closure=0x0)
    at ../Python/ceval.c:3980
#12 0x000055555566e374 in PyEval_EvalCode (co=co@entry=0x7ffff769e040, 
    globals=globals@entry=0x7ffff772b440, locals=locals@entry=0x7ffff772b440)
    at ../Python/ceval.c:513
#13 0x00005555556b0587 in run_mod (mod=mod@entry=0x5555559763a0, 
    filename=filename@entry=0x7ffff771b350, 
    globals=globals@entry=0x7ffff772b440, locals=locals@entry=0x7ffff772b440, 
    flags=flags@entry=0x7fffffffd9e4, arena=arena@entry=0x7ffff7704940)
    at ../Python/pythonrun.c:1031
#14 0x00005555556b34f5 in PyRun_FileExFlags (fp=fp@entry=0x555555974e10, 
    filename_str=filename_str@entry=0x7ffff77048b0 "minitest.py", 
    start=start@entry=257, globals=globals@entry=0x7ffff772b440, 
--Type <RET> for more, q to quit, c to continue without paging--
    locals=locals@entry=0x7ffff772b440, closeit=closeit@entry=1, 
    flags=0x7fffffffd9e4) at ../Python/pythonrun.c:984
#15 0x00005555556b3885 in PyRun_SimpleFileExFlags (fp=fp@entry=0x555555974e10, 
    filename=<optimized out>, filename@entry=0x7ffff77048b0 "minitest.py", 
    closeit=closeit@entry=1, flags=flags@entry=0x7fffffffd9e4)
    at ../Python/pythonrun.c:425
#16 0x00005555556b3a60 in PyRun_AnyFileExFlags (fp=fp@entry=0x555555974e10, 
    filename=0x7ffff77048b0 "minitest.py", closeit=closeit@entry=1, 
    flags=flags@entry=0x7fffffffd9e4) at ../Python/pythonrun.c:84
#17 0x00005555555af9e7 in pymain_run_file (pymain=pymain@entry=0x7fffffffda50, 
    config=config@entry=0x5555558f8638, cf=cf@entry=0x7fffffffd9e4)
    at ../Modules/main.c:1159
#18 0x00005555555aff98 in pymain_run_python (
    pymain=pymain@entry=0x7fffffffda50, interp=0x5555558f85b0)
    at ../Modules/main.c:1607
#19 0x00005555555b1d94 in pymain_main (pymain=pymain@entry=0x7fffffffda50)
    at ../Modules/main.c:1755
#20 0x00005555555b1eb5 in _Py_UnixMain (argc=<optimized out>, 
    argv=<optimized out>) at ../Modules/main.c:1792
#21 0x00005555555ae6a2 in main (argc=<optimized out>, argv=<optimized out>)
    at ../Programs/python.c:15

@kngwyu kngwyu mentioned this issue Nov 9, 2018
konstin added a commit that referenced this issue Nov 11, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants