]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-44895: Introduce PYTHONDUMPREFSFILE variable for refcount dumping (GH-27767)
authorDong-hee Na <donghee.na92@gmail.com>
Tue, 17 Aug 2021 15:52:50 +0000 (15:52 +0000)
committerGitHub <noreply@github.com>
Tue, 17 Aug 2021 15:52:50 +0000 (00:52 +0900)
Doc/using/cmdline.rst
Include/cpython/initconfig.h
Misc/NEWS.d/next/Core and Builtins/2021-08-14-20-13-21.bpo-44895.Ic9m90.rst [new file with mode: 0644]
Python/initconfig.c
Python/pylifecycle.c

index 9e391604a1a59df56e418a7571f65f27b05ad4c2..7ebc34f47fc39b3592c5d82cb6d9d92069ac3f3a 100644 (file)
@@ -975,3 +975,12 @@ Debug-mode variables
    shutting down the interpreter.
 
    Need Python configured with the :option:`--with-trace-refs` build option.
+
+.. envvar:: PYTHONDUMPREFSFILE=FILENAME
+
+   If set, Python will dump objects and reference counts still alive
+   after shutting down the interpreter into a file called *FILENAME*.
+
+   Need Python configured with the :option:`--with-trace-refs` build option.
+
+   .. versionadded:: 3.11
index 5f03b8c57f8bc82f18f6914ed9c7cacacb45bbb3..22ad0f14e58004cdc560456883e68abc68670880 100644 (file)
@@ -143,6 +143,7 @@ typedef struct PyConfig {
     int no_debug_ranges;
     int show_ref_count;
     int dump_refs;
+    wchar_t *dump_refs_file;
     int malloc_stats;
     wchar_t *filesystem_encoding;
     wchar_t *filesystem_errors;
diff --git a/Misc/NEWS.d/next/Core and Builtins/2021-08-14-20-13-21.bpo-44895.Ic9m90.rst b/Misc/NEWS.d/next/Core and Builtins/2021-08-14-20-13-21.bpo-44895.Ic9m90.rst
new file mode 100644 (file)
index 0000000..d369ac7
--- /dev/null
@@ -0,0 +1,2 @@
+A debug variable :envvar:`PYTHONDUMPREFSFILE` is added for creating a dump file
+which is generated by :option:`--with-trace-refs`. Patch by Dong-hee Na.
index d328f227cead2582638236f981efe284decb1b0e..61cd0e6213ed17bf81ce34c2d2b771c9d1d08230 100644 (file)
@@ -898,6 +898,7 @@ _PyConfig_Copy(PyConfig *config, const PyConfig *config2)
     COPY_ATTR(no_debug_ranges);
     COPY_ATTR(show_ref_count);
     COPY_ATTR(dump_refs);
+    COPY_ATTR(dump_refs_file);
     COPY_ATTR(malloc_stats);
 
     COPY_WSTR_ATTR(pycache_prefix);
@@ -1701,6 +1702,14 @@ config_read_env_vars(PyConfig *config)
         config->malloc_stats = 1;
     }
 
+    if (config->dump_refs_file == NULL) {
+        status = CONFIG_GET_ENV_DUP(config, &config->dump_refs_file,
+                                    L"PYTHONDUMPREFSFILE", "PYTHONDUMPREFSFILE");
+        if (_PyStatus_EXCEPTION(status)) {
+            return status;
+        }
+    }
+
     if (config->pythonpath_env == NULL) {
         status = CONFIG_GET_ENV_DUP(config, &config->pythonpath_env,
                                     L"PYTHONPATH", "PYTHONPATH");
index eeaf20b4617a2095bc6702199e509f5435870a4a..f3b6b0ac68a1ea98d8ac7589d72dc16cdffad859 100644 (file)
@@ -1737,6 +1737,7 @@ Py_FinalizeEx(void)
 #endif
 #ifdef Py_TRACE_REFS
     int dump_refs = tstate->interp->config.dump_refs;
+    wchar_t *dump_refs_file = tstate->interp->config.dump_refs_file;
 #endif
 #ifdef WITH_PYMALLOC
     int malloc_stats = tstate->interp->config.malloc_stats;
@@ -1835,9 +1836,22 @@ Py_FinalizeEx(void)
      * Alas, a lot of stuff may still be alive now that will be cleaned
      * up later.
      */
+
+    FILE *dump_refs_fp = NULL;
+    if (dump_refs_file != NULL) {
+        dump_refs_fp = _Py_wfopen(dump_refs_file, L"w");
+        if (dump_refs_fp == NULL) {
+            fprintf(stderr, "PYTHONDUMPREFSFILE: cannot create file: %ls\n", dump_refs_file);
+        }
+    }
+
     if (dump_refs) {
         _Py_PrintReferences(stderr);
     }
+
+    if (dump_refs_fp != NULL) {
+        _Py_PrintReferences(dump_refs_fp);
+    }
 #endif /* Py_TRACE_REFS */
 
     finalize_interp_clear(tstate);
@@ -1848,9 +1862,15 @@ Py_FinalizeEx(void)
      * An address can be used to find the repr of the object, printed
      * above by _Py_PrintReferences.
      */
+
     if (dump_refs) {
         _Py_PrintReferenceAddresses(stderr);
     }
+
+    if (dump_refs_fp != NULL) {
+        _Py_PrintReferenceAddresses(dump_refs_fp);
+        fclose(dump_refs_fp);
+    }
 #endif /* Py_TRACE_REFS */
 #ifdef WITH_PYMALLOC
     if (malloc_stats) {