Commit 6bf992a1 authored by Victor Stinner's avatar Victor Stinner Committed by GitHub

bpo-32030: Add pymain_get_global_config() (#4735)

* Py_Main() now starts by reading Py_xxx configuration variables to
  only work on its own private structure, and then later writes back
  the configuration into these variables.
* Replace Py_GETENV() with pymain_get_env_var() which ignores empty
  variables.
* Add _PyCoreConfig.dump_refs
* Add _PyCoreConfig.malloc_stats
* _PyObject_DebugMallocStats() is now responsible to check if debug
  hooks are installed. The function returns 1 if stats were written,
  or 0 if the hooks are disabled. Mark _PyMem_PymallocEnabled() as
  static.
parent 672b6baa
......@@ -109,7 +109,7 @@ PyAPI_FUNC(Py_ssize_t) _Py_GetAllocatedBlocks(void);
/* Macros */
#ifdef WITH_PYMALLOC
#ifndef Py_LIMITED_API
PyAPI_FUNC(void) _PyObject_DebugMallocStats(FILE *out);
PyAPI_FUNC(int) _PyObject_DebugMallocStats(FILE *out);
#endif /* #ifndef Py_LIMITED_API */
#endif
......
......@@ -24,10 +24,6 @@ PyAPI_FUNC(int) _PyMem_SetupAllocators(const char *opt);
/* Try to get the allocators name set by _PyMem_SetupAllocators(). */
PyAPI_FUNC(const char*) _PyMem_GetAllocatorsName(void);
#ifdef WITH_PYMALLOC
PyAPI_FUNC(int) _PyMem_PymallocEnabled(void);
#endif
/* Track an allocated memory block in the tracemalloc module.
Return 0 on success, return -1 on error (failed to allocate memory to store
the trace).
......
......@@ -36,6 +36,8 @@ typedef struct {
int import_time; /* -X importtime */
int show_ref_count; /* -X showrefcount */
int show_alloc_count; /* -X showalloccount */
int dump_refs; /* PYTHONDUMPREFS */
int malloc_stats; /* PYTHONMALLOCSTATS */
} _PyCoreConfig;
#define _PyCoreConfig_INIT (_PyCoreConfig){.use_hash_seed = -1}
......@@ -111,7 +113,7 @@ typedef struct _is {
PyObject *after_forkers_child;
#endif
} PyInterpreterState;
#endif
#endif /* !Py_LIMITED_API */
/* State unique per thread */
......@@ -133,7 +135,7 @@ typedef int (*Py_tracefunc)(PyObject *, struct _frame *, int, PyObject *);
#define PyTrace_C_EXCEPTION 5
#define PyTrace_C_RETURN 6
#define PyTrace_OPCODE 7
#endif
#endif /* Py_LIMITED_API */
#ifdef Py_LIMITED_API
typedef struct _ts PyThreadState;
......@@ -238,7 +240,7 @@ typedef struct _ts {
/* XXX signal handlers should also be here */
} PyThreadState;
#endif
#endif /* !Py_LIMITED_API */
PyAPI_FUNC(PyInterpreterState *) PyInterpreterState_New(void);
......@@ -363,7 +365,7 @@ PyAPI_FUNC(int) PyGILState_Check(void);
Return NULL before _PyGILState_Init() is called and after _PyGILState_Fini()
is called. */
PyAPI_FUNC(PyInterpreterState *) _PyGILState_GetInterpreterStateUnsafe(void);
#endif
#endif /* !Py_LIMITED_API */
/* The implementation of sys._current_frames() Returns a dict mapping
......
This diff is collapsed.
......@@ -379,7 +379,7 @@ _PyMem_DebugEnabled(void)
return (_PyObject.malloc == _PyMem_DebugMalloc);
}
int
static int
_PyMem_PymallocEnabled(void)
{
if (_PyMem_DebugEnabled()) {
......@@ -2467,10 +2467,17 @@ pool_is_in_list(const poolp target, poolp list)
/* Print summary info to "out" about the state of pymalloc's structures.
* In Py_DEBUG mode, also perform some expensive internal consistency
* checks.
*
* Return 0 if the memory debug hooks are not installed or no statistics was
* writen into out, return 1 otherwise.
*/
void
int
_PyObject_DebugMallocStats(FILE *out)
{
if (!_PyMem_PymallocEnabled()) {
return 0;
}
uint i;
const uint numclasses = SMALL_REQUEST_THRESHOLD >> ALIGNMENT_SHIFT;
/* # of pools, allocated blocks, and free blocks per class index */
......@@ -2603,6 +2610,7 @@ _PyObject_DebugMallocStats(FILE *out)
total += printone(out, "# bytes lost to quantization", quantization);
total += printone(out, "# bytes lost to arena alignment", arena_alignment);
(void)printone(out, "Total", total);
return 1;
}
#endif /* #ifdef WITH_PYMALLOC */
......@@ -1103,6 +1103,10 @@ Py_FinalizeEx(void)
tstate = PyThreadState_GET();
interp = tstate->interp;
/* Copy the core config to be able to use it even
after PyInterpreterState_Delete() */
_PyCoreConfig core_config = interp->core_config;
/* Remaining threads (e.g. daemon threads) will automatically exit
after taking the GIL (in PyEval_RestoreThread()). */
_PyRuntime.finalizing = tstate;
......@@ -1186,7 +1190,7 @@ Py_FinalizeEx(void)
_PyHash_Fini();
#ifdef Py_REF_DEBUG
if (interp->core_config.show_ref_count) {
if (core_config.show_ref_count) {
_PyDebug_PrintTotalRefs();
}
#endif
......@@ -1197,8 +1201,9 @@ Py_FinalizeEx(void)
* Alas, a lot of stuff may still be alive now that will be cleaned
* up later.
*/
if (Py_GETENV("PYTHONDUMPREFS"))
if (core_config.dump_refs) {
_Py_PrintReferences(stderr);
}
#endif /* Py_TRACE_REFS */
/* Clear interpreter state and all thread states. */
......@@ -1260,14 +1265,13 @@ Py_FinalizeEx(void)
* An address can be used to find the repr of the object, printed
* above by _Py_PrintReferences.
*/
if (Py_GETENV("PYTHONDUMPREFS"))
if (core_config.dump_refs) {
_Py_PrintReferenceAddresses(stderr);
}
#endif /* Py_TRACE_REFS */
#ifdef WITH_PYMALLOC
if (_PyMem_PymallocEnabled()) {
char *opt = Py_GETENV("PYTHONMALLOCSTATS");
if (opt != NULL && *opt != '\0')
_PyObject_DebugMallocStats(stderr);
if (core_config.malloc_stats) {
_PyObject_DebugMallocStats(stderr);
}
#endif
......
......@@ -1368,8 +1368,7 @@ static PyObject *
sys_debugmallocstats(PyObject *self, PyObject *args)
{
#ifdef WITH_PYMALLOC
if (_PyMem_PymallocEnabled()) {
_PyObject_DebugMallocStats(stderr);
if (_PyObject_DebugMallocStats(stderr)) {
fputc('\n', stderr);
}
#endif
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment