Skip to content

Commit faf2bde

Browse files
committed
Deregister any Python-extended prototypes on exit.
When Python exits, remove any Python-extended objects from the C++ registry. This avoids crash due to deallocation of Python objects in the C++ registry with Python already kaput. Replace the reference counting hack that was used to avoid the crash before.
1 parent 3b46596 commit faf2bde

3 files changed

Lines changed: 94 additions & 1 deletion

File tree

diffpy/srreal/_cleanup.py

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
#!/usr/bin/env python
2+
##############################################################################
3+
#
4+
# diffpy.srreal Complex Modeling Initiative
5+
# (c) 2016 Brookhaven Science Associates,
6+
# Brookhaven National Laboratory.
7+
# All rights reserved.
8+
#
9+
# File coded by: Pavol Juhas
10+
#
11+
# See AUTHORS.txt for a list of people who contributed.
12+
# See LICENSE.txt for license information.
13+
#
14+
##############################################################################
15+
16+
17+
"""\
18+
Cancel registration of Python-extended C++ classes when Python exits.
19+
20+
Note
21+
----
22+
Python finishes before the shared library libdiffpy, but the registry of
23+
class prototypes is implemented in libdiffpy. Any Python-extended classes
24+
thus need to be removed from the registry prior to Python exit.
25+
26+
This module is not intended for direct use. It is used implicitly within
27+
a call of _registerThisType.
28+
"""
29+
30+
31+
import weakref
32+
33+
34+
# Routine to be used from srreal_ext module ----------------------------------
35+
36+
def registerForCleanUp(obj):
37+
"""Remember to clean up the specified prototype at Python exit.
38+
39+
Parameters
40+
----------
41+
obj : wrapped class that has class registry
42+
This is an object being added to the C++ registry of prototypes.
43+
If active at Python exit, the associated string type will be
44+
removed from the class registry.
45+
46+
No return value.
47+
"""
48+
_cleanup_handler.add(obj)
49+
return
50+
51+
# ----------------------------------------------------------------------------
52+
53+
class _DerivedClassesCleanUpHandler(object):
54+
55+
def __init__(self):
56+
self._references = set()
57+
return
58+
59+
60+
def add(self, obj):
61+
wr = weakref.ref(obj)
62+
self._references.add(wr)
63+
return
64+
65+
66+
def __del__(self):
67+
while self._references:
68+
wr = self._references.pop()
69+
obj = wr()
70+
if obj is not None:
71+
obj._deregisterType(obj.type())
72+
return
73+
74+
# end of class _DerivedClassesCleanUpHandler
75+
76+
77+
# create singleton instance of the cleanup handler
78+
_cleanup_handler = _DerivedClassesCleanUpHandler()
79+
del _DerivedClassesCleanUpHandler
80+
81+
82+
# End of file.

srrealmodule/srreal_registry.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,13 @@ namespace srrealmodule {
2323

2424
using namespace boost::python;
2525

26+
void register_for_cleanup(PyObject* pobj)
27+
{
28+
object obj(borrowed(pobj));
29+
object reg = import("diffpy.srreal._cleanup").attr("registerForCleanUp");
30+
reg(obj);
31+
}
32+
2633

2734
/// get dictionary of Python-defined docstrings for the cls class.
2835
object get_registry_docstrings(object& cls)

srrealmodule/srreal_registry.hpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424

2525
namespace srrealmodule {
2626

27+
/// helper for remembering instances of Python-derived class.
28+
void register_for_cleanup(PyObject*);
29+
30+
2731
/// template class for handling Python Wrapper classes in C++ class registry
2832
template <class T>
2933
class wrapper_registry_configurator
@@ -55,7 +59,7 @@ class wrapper_registry_configurator
5559
void setup(TSharedPtr ptr) const
5660
{
5761
assert(mcptr && mcptr == ptr.get());
58-
::boost::python::incref(mpyptr);
62+
register_for_cleanup(mpyptr);
5963
mcptr = 0;
6064
mpyptr = 0;
6165
}

0 commit comments

Comments
 (0)