title: Sequence of object cleanup and functions called by atexit in Python module
body: <p>I am integrating a legacy C++ library with Python using boost-python. The legacy library has some global initialization and then the classes in it use application wide data. I need to ensure that the shutdown function of the legacy library is called after all wrapped objects are destroyed and thought this might be achieved by registering a shutdown function using atexit. However, I found that the wrapped objects are being cleaned up after atexit calls the shutdown function, causing multiple segfaults within the legacy library!</p>
  
  <p>I can achieve the desired behavior by calling del on the wrapped objects before exiting, but was hoping to leave deletion to Python. I have checked out the red warning box in the <a href="https://docs.python.org/2/reference/datamodel.html#object.__del__" rel="nofollow">documentation of object.<strong>__del__</strong></a>, and am wondering if my ideal world is unreachable.</p>
  
  <p>Any suggestions for ensuring a shutdown method is called after all objects are cleaned up when wrapping legacy code in a python module?</p>
  
  <p>Some platform details in case they are important:</p>
  
  <ul>
  <li>Python 2.7.2</li>
  <li>Visual Studio 2013</li>
  <li>64-bit build</li>
  </ul>
  
  <p>Minimal code:</p>
  
  <pre><code>#include &lt;iostream&gt;
  #include &lt;boost/python.hpp&gt;
  
  using namespace std;
  
  namespace legacy
  {
      void initialize() { cout &lt;&lt; "legacy::initialize" &lt;&lt; endl; }
      void shutdown() { cout &lt;&lt; "legacy::shutdown" &lt;&lt; endl; }
  
      class Test
      {
      public:
          Test();
          virtual ~Test();
      };
  
      Test::Test() { }
      Test::~Test() { cout &lt;&lt; "legacy::Test::~Test" &lt;&lt; endl; }
  }
  
  BOOST_PYTHON_MODULE(legacy)
  {
      using namespace boost::python;
      legacy::initialize();
      class_&lt;legacy::Test&gt;("Test");
      def("_finalize", &amp;legacy::shutdown);
      object atexit = object(handle&lt;&gt;(PyImport_ImportModule("atexit")));
      object finalize = scope().attr("_finalize");
      atexit.attr("register")(finalize);
  }
  </code></pre>
  
  <p>Once compiled, this can be run using python with the following input and outputs being displayed:</p>
  
  <blockquote>
    <p>>>> import legacy<br>
    legacy::initialize<br>
    >>> test = legacy.Test()<br>
    >>> ^Z<br>
    legacy::shutdown<br>
    legacy::Test::~Test</p>
  </blockquote>