Skip to content

Commit

Permalink
bpo-44895: Introduce PYTHONDUMPREFSFILE variable for refcount dumping (
Browse files Browse the repository at this point in the history
  • Loading branch information
corona10 authored Aug 17, 2021
1 parent 96346cb commit c2c857b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 0 deletions.
9 changes: 9 additions & 0 deletions Doc/using/cmdline.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
1 change: 1 addition & 0 deletions Include/cpython/initconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
9 changes: 9 additions & 0 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
Expand Down
20 changes: 20 additions & 0 deletions Python/pylifecycle.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand All @@ -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) {
Expand Down

0 comments on commit c2c857b

Please sign in to comment.