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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault adding class object to module. #320

Closed
derekdreery opened this issue Jan 5, 2019 · 5 comments
Closed

Segfault adding class object to module. #320

derekdreery opened this issue Jan 5, 2019 · 5 comments
Assignees
Labels

Comments

@derekdreery
Copy link

🌍 Environment

  • Your operating system and version: Linux: 4.18.16-arch1-1-ARCH
  • Your python version: 3.7.1
  • How did you install python (e.g. apt or pyenv)? Did you use a virtualenv?: arch-linux (no venv)
  • Your rust version (rustc --version):
  • Are you using the latest pyo3 version?: git-master

💥 Reproducing

#![feature(specialization)]

use pyo3::prelude::*;

/// Main entry point - set up modules, functions, etc.
#[pymodule]
fn libbug(_: Python, m: &PyModule) -> PyResult<()> {
    m.add("Foo", A { kind: 0 })?;
    Ok(())
}

#[pyclass]
#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct A {
    kind: u32,
}

Import the .so -> segfault (somewhat intermittent).

@kngwyu kngwyu added the bug label Jan 5, 2019
@kngwyu
Copy link
Member

kngwyu commented Jan 5, 2019

Thanks for reporting!
I think it's a design mistake...
This implementation is used when m.add(A {}) is called, but we can't use as_ptr before we call into_object.
So to fix this bug is relatively easy, but I think we have to rethink pyclass design.

  1. We can't know a struct is in a python heap(and has ob_refcnt and ob_type), or not. Is it proper design? Ideally we should use different types for python-allocated items, though it's far from current design.
  2. For pyclass, currently IntoPyObject actually allocates in python heap and copies its data. So I think Into prefix is not suitable.

@athre0z
Copy link
Contributor

athre0z commented Jan 10, 2019

I think you're on the right track there @kngwyu. This design issue is probably also closely related to #308. The ToPyObject implementation generated by the proc macro has the same issue.

@derekdreery
Copy link
Author

Do you have any ideas of how to fix this? I'm happy to help implement if possible.

@konstin
Copy link
Member

konstin commented Jan 22, 2019

I fear it's a bit complex to fix. Basically, we need to properly differentiate between instances of pyclass structs that can be wrapped in a python object, but aren't, and types that are python objects (i.e. they are/have a *mut PyObject). I think the bug is we assume that our instance is the latter while it is the former in the the pyclass implementation:

impl ::pyo3::ToPyObject for #cls {
fn to_object(&self, py: ::pyo3::Python) -> ::pyo3::PyObject {
use ::pyo3::python::ToPyPointer;
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}
impl ::pyo3::ToPyPointer for #cls {
fn as_ptr(&self) -> *mut ::pyo3::ffi::PyObject {
unsafe {
{self as *const _ as *mut u8}
.offset(-<#cls as ::pyo3::typeob::PyTypeInfo>::OFFSET) as *mut ::pyo3::ffi::PyObject
}
}
}
impl<'a> ::pyo3::ToPyObject for &'a mut #cls {
fn to_object(&self, py: ::pyo3::Python) -> ::pyo3::PyObject {
use ::pyo3::python::ToPyPointer;
unsafe { ::pyo3::PyObject::from_borrowed_ptr(py, self.as_ptr()) }
}
}

If I'm not wrong, we need to remove those &self methods on the pyclass instances and instead start to allow IntoPyObject where currently ToPyObject is required.

@kngwyu kngwyu self-assigned this Feb 1, 2019
@kngwyu
Copy link
Member

kngwyu commented Feb 1, 2019

@konstin
I'm planning to implement reference wrappers PyRef and PyRefMut.
They're just wrappers of &T and &mut T, but we can retrieve *mut ffi::PyObject from them.
Just &T where T: PyTypeInfo doesn't mean we can retrieve python object, since we can't know they're already copied to python heap or not.
What do you think about this idea?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants