[Python-checkins] cpython: Closes #19831: Stop tracemalloc later at Python shutdown to be able to use

victor.stinner python-checkins at python.org
Sun Dec 1 10:05:58 CET 2013


http://hg.python.org/cpython/rev/cc8953ea3c7e
changeset:   87676:cc8953ea3c7e
user:        Victor Stinner <victor.stinner at gmail.com>
date:        Sun Dec 01 10:03:26 2013 +0100
summary:
  Closes #19831: Stop tracemalloc later at Python shutdown to be able to use
tracemalloc in objects destructor

Replace atexit handler with an harcoded C function _PyTraceMalloc_Fini().

files:
  Modules/_tracemalloc.c |  77 +++--------------------------
  Python/pythonrun.c     |   5 +
  2 files changed, 15 insertions(+), 67 deletions(-)


diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -9,7 +9,6 @@
 
 /* Forward declaration */
 static void tracemalloc_stop(void);
-static int tracemalloc_atexit_register(void);
 static void* raw_malloc(size_t size);
 static void raw_free(void *ptr);
 
@@ -36,9 +35,6 @@
         TRACEMALLOC_FINALIZED
     } initialized;
 
-    /* atexit handler registered? */
-    int atexit_registered;
-
     /* Is tracemalloc tracing memory allocations?
        Variable protected by the GIL */
     int tracing;
@@ -46,7 +42,7 @@
     /* limit of the number of frames in a traceback, 1 by default.
        Variable protected by the GIL. */
     int max_nframe;
-} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 0, 1};
+} tracemalloc_config = {TRACEMALLOC_NOT_INITIALIZED, 0, 1};
 
 #if defined(TRACE_RAW_MALLOC) && defined(WITH_THREAD)
 /* This lock is needed because tracemalloc_free() is called without
@@ -802,9 +798,6 @@
         return 0;
     }
 
-    if (tracemalloc_atexit_register() < 0)
-        return -1;
-
     assert(1 <= max_nframe && max_nframe <= MAX_NFRAME);
     tracemalloc_config.max_nframe = max_nframe;
 
@@ -1140,65 +1133,6 @@
     return traceback_to_pyobject(trace.traceback, NULL);
 }
 
-static PyObject*
-tracemalloc_atexit(PyObject *self)
-{
-#ifdef WITH_THREAD
-    assert(PyGILState_Check());
-#endif
-    tracemalloc_deinit();
-    Py_RETURN_NONE;
-}
-
-static PyMethodDef atexit_method = {
-    "_atexit", (PyCFunction)tracemalloc_atexit, METH_NOARGS, NULL};
-
-static int
-tracemalloc_atexit_register(void)
-{
-    PyObject *method = NULL, *atexit = NULL, *func = NULL;
-    PyObject *result;
-    int ret = -1;
-
-    if (tracemalloc_config.atexit_registered)
-        return 0;
-    tracemalloc_config.atexit_registered = 1;
-
-    /* private functions */
-    method = PyCFunction_New(&atexit_method, NULL);
-    if (method == NULL)
-        goto done;
-
-    atexit = PyImport_ImportModule("atexit");
-    if (atexit == NULL) {
-        if (!PyErr_Warn(PyExc_ImportWarning,
-                       "atexit module is missing: "
-                       "cannot automatically disable tracemalloc at exit"))
-        {
-            PyErr_Clear();
-            return 0;
-        }
-        goto done;
-    }
-
-    func = PyObject_GetAttrString(atexit, "register");
-    if (func == NULL)
-        goto done;
-
-    result = PyObject_CallFunction(func, "O", method);
-    if (result == NULL)
-        goto done;
-    Py_DECREF(result);
-
-    ret = 0;
-
-done:
-    Py_XDECREF(method);
-    Py_XDECREF(func);
-    Py_XDECREF(atexit);
-    return ret;
-}
-
 PyDoc_STRVAR(tracemalloc_start_doc,
     "start(nframe: int=1)\n"
     "\n"
@@ -1439,3 +1373,12 @@
     return tracemalloc_start(nframe);
 }
 
+void
+_PyTraceMalloc_Fini(void)
+{
+#ifdef WITH_THREAD
+    assert(PyGILState_Check());
+#endif
+    tracemalloc_deinit();
+}
+
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -106,6 +106,7 @@
 extern void _PyFaulthandler_Fini(void);
 extern void _PyHash_Fini(void);
 extern int _PyTraceMalloc_Init(void);
+extern int _PyTraceMalloc_Fini(void);
 
 #ifdef WITH_THREAD
 extern void _PyGILState_Init(PyInterpreterState *, PyThreadState *);
@@ -642,6 +643,10 @@
     PyGC_Collect();
 #endif
 
+    /* Disable tracemalloc after all Python objects have been destroyed,
+       so it is possible to use tracemalloc in objects destructor. */
+    _PyTraceMalloc_Fini();
+
     /* Destroy the database used by _PyImport_{Fixup,Find}Extension */
     _PyImport_Fini();
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list