python: Prevent Python wrappers from deleting SimObjects
authorAndreas Sandberg <andreas.sandberg@arm.com>
Tue, 9 May 2017 18:28:47 +0000 (19:28 +0100)
committerAndreas Sandberg <andreas.sandberg@arm.com>
Mon, 22 May 2017 17:15:09 +0000 (17:15 +0000)
The PyBind wrappers could potentially delete SimObjects if they don't
have any references. This is not desirable since there could be
pointers to such objects within the C++ world. This problem doesn't
normally occur since Python typically holds a pointer to the root node
as long as the simulator is running.

Prevent SimObject and Param deletion by using a PyBind-prescribed
unique_ptr with a dummy deleter as the pointer wrapper for the Python
world.

Change-Id: Ied14602c9ee69a083a69c5dae1b5fcf8efb4548a
Signed-off-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Curtis Dunham <curtis.dunham@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/3224
Reviewed-by: Gabe Black <gabeblack@google.com>
src/python/m5/SimObject.py
src/python/pybind11/core.cc

index 569142e344b67b2af640ef92cb84cc73c5a3fc2d..baeef73d9fb4ee8f020d0bec5cce86f5dec7efc4 100644 (file)
@@ -701,10 +701,13 @@ module_init(py::module &m_internal)
 ''')
         code.indent()
         if cls._base:
-            code('py::class_<${cls}Params, ${{cls._base.type}}Params>(m, ' \
-                 '"${cls}Params")')
+            code('py::class_<${cls}Params, ${{cls._base.type}}Params, ' \
+                 'std::unique_ptr<${{cls}}Params, py::nodelete>>(' \
+                 'm, "${cls}Params")')
         else:
-            code('py::class_<${cls}Params>(m, "${cls}Params")')
+            code('py::class_<${cls}Params, ' \
+                 'std::unique_ptr<${cls}Params, py::nodelete>>(' \
+                 'm, "${cls}Params")')
 
         code.indent()
         if not hasattr(cls, 'abstract') or not cls.abstract:
@@ -729,10 +732,13 @@ module_init(py::module &m_internal)
                 cls.cxx_bases
         if bases:
             base_str = ", ".join(bases)
-            code('py::class_<${{cls.cxx_class}}, ${base_str}>(m, ' \
-                 '"${py_class_name}")')
+            code('py::class_<${{cls.cxx_class}}, ${base_str}, ' \
+                 'std::unique_ptr<${{cls.cxx_class}}, py::nodelete>>(' \
+                 'm, "${py_class_name}")')
         else:
-            code('py::class_<${{cls.cxx_class}}>(m, "${py_class_name}")')
+            code('py::class_<${{cls.cxx_class}}, ' \
+                 'std::unique_ptr<${{cls.cxx_class}}, py::nodelete>>(' \
+                 'm, "${py_class_name}")')
         code.indent()
         for exp in cls.cxx_exports:
             exp.export(code, cls.cxx_class)
index 7ad45b40868f832a692db050749a7442af71793e..159b19f9d415d34c822bdaeec62408d08b52cf0d 100644 (file)
@@ -132,7 +132,8 @@ init_serialize(py::module &m_native)
 {
     py::module m = m_native.def_submodule("serialize");
 
-    py::class_<Serializable>(m, "Serializable")
+    py::class_<Serializable, std::unique_ptr<Serializable, py::nodelete>>(
+        m, "Serializable")
         ;
 
     py::class_<CheckpointIn>(m, "CheckpointIn")
@@ -165,7 +166,7 @@ init_range(py::module &m_native)
         .def("isSubset", &AddrRange::isSubset)
         ;
 
-    // We need to make vectors of AddrRange opaque to avoid weird
+    // We need to make vectors of AddrRange opaque to avoid weird
     // memory allocation issues in PyBind's STL wrappers.
     py::bind_vector<std::vector<AddrRange>>(m, "AddrRangeVector");