mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-22 05:05:11 +00:00
fix rare GC issue during type creation (fixes #277)
This commit is contained in:
parent
c075997617
commit
dc4d7493b3
@ -13,9 +13,10 @@ Breaking changes queued for v2.0.0 (Not yet released)
|
||||
|
||||
* Remove ``handle.call()`` method
|
||||
|
||||
1.9.0 (Not yet released)
|
||||
1.8.1 (July 12, 2016)
|
||||
----------------------
|
||||
* Queued changes: ``py::eval*``, map indexing suite, documentation for indexing suites.
|
||||
* Fixed a rare but potentially very severe issue when the garbage collector ran
|
||||
during pybind11 type creation.
|
||||
|
||||
1.8.0 (June 14, 2016)
|
||||
----------------------
|
||||
|
@ -525,8 +525,40 @@ protected:
|
||||
pybind11_fail("generic_type: type \"" + std::string(rec->name) +
|
||||
"\" is already registered!");
|
||||
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
object name(PYBIND11_FROM_STRING(rec->name), false);
|
||||
object scope_module;
|
||||
if (rec->scope) {
|
||||
scope_module = (object) rec->scope.attr("__module__");
|
||||
if (!scope_module)
|
||||
scope_module = (object) rec->scope.attr("__name__");
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
/* Qualified names for Python >= 3.3 */
|
||||
object scope_qualname;
|
||||
if (rec->scope)
|
||||
scope_qualname = (object) rec->scope.attr("__qualname__");
|
||||
object ht_qualname;
|
||||
if (scope_qualname) {
|
||||
ht_qualname = object(PyUnicode_FromFormat(
|
||||
"%U.%U", scope_qualname.ptr(), name.ptr()), false);
|
||||
} else {
|
||||
ht_qualname = name;
|
||||
}
|
||||
#endif
|
||||
std::string full_name = (scope_module ? ((std::string) scope_module.str() + "." + rec->name)
|
||||
: std::string(rec->name));
|
||||
|
||||
char *tp_doc = nullptr;
|
||||
if (rec->doc) {
|
||||
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
||||
Python will free this later on) */
|
||||
size_t size = strlen(rec->doc) + 1;
|
||||
tp_doc = (char *) PyObject_MALLOC(size);
|
||||
memcpy((void *) tp_doc, rec->doc, size);
|
||||
}
|
||||
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
||||
|
||||
if (!type_holder || !name)
|
||||
@ -540,36 +572,18 @@ protected:
|
||||
internals.registered_types_cpp[tindex] = tinfo;
|
||||
internals.registered_types_py[type] = tinfo;
|
||||
|
||||
object scope_module;
|
||||
if (rec->scope) {
|
||||
scope_module = (object) rec->scope.attr("__module__");
|
||||
if (!scope_module)
|
||||
scope_module = (object) rec->scope.attr("__name__");
|
||||
}
|
||||
|
||||
std::string full_name = (scope_module ? ((std::string) scope_module.str() + "." + rec->name)
|
||||
: std::string(rec->name));
|
||||
/* Basic type attributes */
|
||||
type->ht_type.tp_name = strdup(full_name.c_str());
|
||||
type->ht_type.tp_basicsize = (ssize_t) rec->instance_size;
|
||||
type->ht_type.tp_base = (PyTypeObject *) rec->base_handle.ptr();
|
||||
rec->base_handle.inc_ref();
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
/* Qualified names for Python >= 3.3 */
|
||||
object scope_qualname;
|
||||
if (rec->scope)
|
||||
scope_qualname = (object) rec->scope.attr("__qualname__");
|
||||
if (scope_qualname) {
|
||||
type->ht_qualname = PyUnicode_FromFormat(
|
||||
"%U.%U", scope_qualname.ptr(), name.ptr());
|
||||
} else {
|
||||
type->ht_qualname = name.ptr();
|
||||
name.inc_ref();
|
||||
}
|
||||
#endif
|
||||
type->ht_name = name.release().ptr();
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
type->ht_qualname = ht_qualname.release().ptr();
|
||||
#endif
|
||||
|
||||
/* Supported protocols */
|
||||
type->ht_type.tp_as_number = &type->as_number;
|
||||
type->ht_type.tp_as_sequence = &type->as_sequence;
|
||||
@ -590,13 +604,7 @@ protected:
|
||||
#endif
|
||||
type->ht_type.tp_flags &= ~Py_TPFLAGS_HAVE_GC;
|
||||
|
||||
if (rec->doc) {
|
||||
/* Allocate memory for docstring (using PyObject_MALLOC, since
|
||||
Python will free this later on) */
|
||||
size_t size = strlen(rec->doc) + 1;
|
||||
type->ht_type.tp_doc = (char *) PyObject_MALLOC(size);
|
||||
memcpy((void *) type->ht_type.tp_doc, rec->doc, size);
|
||||
}
|
||||
type->ht_type.tp_doc = tp_doc;
|
||||
|
||||
if (PyType_Ready(&type->ht_type) < 0)
|
||||
pybind11_fail("generic_type: PyType_Ready failed!");
|
||||
@ -620,17 +628,21 @@ protected:
|
||||
|
||||
if (ob_type == &PyType_Type) {
|
||||
std::string name_ = std::string(ht_type.tp_name) + "__Meta";
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
object ht_qualname(PyUnicode_FromFormat(
|
||||
"%U__Meta", ((object) attr("__qualname__")).ptr()), false);
|
||||
#endif
|
||||
object name(PYBIND11_FROM_STRING(name_.c_str()), false);
|
||||
object type_holder(PyType_Type.tp_alloc(&PyType_Type, 0), false);
|
||||
if (!type_holder || !name)
|
||||
pybind11_fail("generic_type::metaclass(): unable to create type object!");
|
||||
|
||||
auto type = (PyHeapTypeObject*) type_holder.ptr();
|
||||
type->ht_name = name.release().ptr();
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 3
|
||||
/* Qualified names for Python >= 3.3 */
|
||||
type->ht_qualname = PyUnicode_FromFormat(
|
||||
"%U__Meta", ((object) attr("__qualname__")).ptr());
|
||||
type->ht_qualname = ht_qualname.release().ptr();
|
||||
#endif
|
||||
type->ht_type.tp_name = strdup(name_.c_str());
|
||||
type->ht_type.tp_base = ob_type;
|
||||
|
Loading…
Reference in New Issue
Block a user