bpo-38631: Avoid Py_FatalError() in handle_legacy_finalizers() (GH-17266)

* Rename _PyGC_Initialize() to _PyGC_InitializeRuntime()
* Add _PyGC_Init(): initialize _PyRuntime.gc.garbage list
* Call _PyGC_Init() before _PyTypes_Init()
This commit is contained in:
Victor Stinner 2019-11-20 01:18:11 +01:00 committed by GitHub
parent e0cd8aa70a
commit 444b39bb64
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 32 additions and 12 deletions

View File

@ -57,6 +57,7 @@ extern PyStatus _Py_HashRandomization_Init(const PyConfig *);
extern PyStatus _PyTypes_Init(void);
extern PyStatus _PyImportZip_Init(PyThreadState *tstate);
extern PyStatus _PyGC_Init(struct pyruntimestate *runtime);
/* Various internal finalizers */

View File

@ -144,7 +144,7 @@ struct _gc_runtime_state {
Py_ssize_t long_lived_pending;
};
PyAPI_FUNC(void) _PyGC_Initialize(struct _gc_runtime_state *);
PyAPI_FUNC(void) _PyGC_InitializeRuntime(struct _gc_runtime_state *);
/* Set the memory allocator of the specified domain to the default.

View File

@ -25,6 +25,7 @@
#include "Python.h"
#include "pycore_context.h"
#include "pycore_initconfig.h"
#include "pycore_object.h"
#include "pycore_pymem.h"
#include "pycore_pystate.h"
@ -129,7 +130,7 @@ static PyObject *gc_str = NULL;
#define GEN_HEAD(state, n) (&(state)->generations[n].head)
void
_PyGC_Initialize(struct _gc_runtime_state *state)
_PyGC_InitializeRuntime(struct _gc_runtime_state *state)
{
state->enabled = 1; /* automatic collection enabled? */
@ -151,6 +152,21 @@ _PyGC_Initialize(struct _gc_runtime_state *state)
state->permanent_generation = permanent_generation;
}
PyStatus
_PyGC_Init(_PyRuntimeState *runtime)
{
struct _gc_runtime_state *state = &runtime->gc;
if (state->garbage == NULL) {
state->garbage = PyList_New(0);
if (state->garbage == NULL) {
return _PyStatus_NO_MEMORY();
}
}
return _PyStatus_OK();
}
/*
_gc_prev values
---------------
@ -905,13 +921,9 @@ handle_legacy_finalizers(struct _gc_runtime_state *state,
PyGC_Head *finalizers, PyGC_Head *old)
{
assert(!PyErr_Occurred());
assert(state->garbage != NULL);
PyGC_Head *gc = GC_NEXT(finalizers);
if (state->garbage == NULL) {
state->garbage = PyList_New(0);
if (state->garbage == NULL)
Py_FatalError("gc couldn't create gc.garbage list");
}
for (; gc != finalizers; gc = GC_NEXT(gc)) {
PyObject *op = FROM_GC(gc);

View File

@ -558,9 +558,16 @@ pycore_create_interpreter(_PyRuntimeState *runtime,
static PyStatus
pycore_init_types(void)
pycore_init_types(_PyRuntimeState *runtime)
{
PyStatus status = _PyTypes_Init();
PyStatus status;
status = _PyGC_Init(runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
status = _PyTypes_Init();
if (_PyStatus_EXCEPTION(status)) {
return status;
}
@ -683,7 +690,7 @@ pyinit_config(_PyRuntimeState *runtime,
config = &tstate->interp->config;
*tstate_p = tstate;
status = pycore_init_types();
status = pycore_init_types(runtime);
if (_PyStatus_EXCEPTION(status)) {
return status;
}
@ -1447,7 +1454,7 @@ new_interpreter(PyThreadState **tstate_p)
}
config = &interp->config;
status = pycore_init_types();
status = pycore_init_types(runtime);
/* XXX The following is lax in error checking */
PyObject *modules = PyDict_New();

View File

@ -58,7 +58,7 @@ _PyRuntimeState_Init_impl(_PyRuntimeState *runtime)
runtime->open_code_userdata = open_code_userdata;
runtime->audit_hook_head = audit_hook_head;
_PyGC_Initialize(&runtime->gc);
_PyGC_InitializeRuntime(&runtime->gc);
_PyEval_Initialize(&runtime->ceval);
PyPreConfig_InitPythonConfig(&runtime->preconfig);