Skip to content

Commit

Permalink
pythongh-108634: init_interpreter() returns Py_Status
Browse files Browse the repository at this point in the history
* Replace Py_FatalError() with PyStatus in init_interpreter().
* init_runtime() cannot be called with _initialized=1: add an
  assertion in the caller.
  • Loading branch information
vstinner committed Sep 1, 2023
1 parent 3edcf74 commit 6e8ba06
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 15 deletions.
2 changes: 1 addition & 1 deletion Include/internal/pycore_initconfig.h
Expand Up @@ -22,7 +22,7 @@ struct pyruntimestate;
#endif

#define _PyStatus_OK() \
(PyStatus){._type = _PyStatus_TYPE_OK,}
(PyStatus){._type = _PyStatus_TYPE_OK}
/* other fields are set to 0 */
#define _PyStatus_ERR(ERR_MSG) \
(PyStatus){ \
Expand Down
2 changes: 1 addition & 1 deletion Include/internal/pycore_object.h
Expand Up @@ -182,7 +182,7 @@ _PyType_HasFeature(PyTypeObject *type, unsigned long feature) {

extern void _PyType_InitCache(PyInterpreterState *interp);

extern void _PyObject_InitState(PyInterpreterState *interp);
extern PyStatus _PyObject_InitState(PyInterpreterState *interp);
extern void _PyObject_FiniState(PyInterpreterState *interp);
extern bool _PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj);

Expand Down
5 changes: 3 additions & 2 deletions Objects/object.c
Expand Up @@ -2034,7 +2034,7 @@ PyObject _Py_NotImplementedStruct = {
};


void
PyStatus
_PyObject_InitState(PyInterpreterState *interp)
{
#ifdef Py_TRACE_REFS
Expand All @@ -2048,9 +2048,10 @@ _PyObject_InitState(PyInterpreterState *interp)
_Py_hashtable_hash_ptr, _Py_hashtable_compare_direct,
NULL, NULL, &alloc);
if (REFCHAIN(interp) == NULL) {
Py_FatalError("_PyObject_InitState() memory allocation failure");
return _PyStatus_NO_MEMORY();
}
#endif
return _PyStatus_OK();
}

void
Expand Down
33 changes: 22 additions & 11 deletions Python/pystate.c
Expand Up @@ -426,13 +426,11 @@ init_runtime(_PyRuntimeState *runtime,
Py_ssize_t unicode_next_index,
PyThread_type_lock locks[NUMLOCKS])
{
if (runtime->_initialized) {
Py_FatalError("runtime already initialized");
}
assert(!runtime->preinitializing &&
!runtime->preinitialized &&
!runtime->core_initialized &&
!runtime->initialized);
assert(!runtime->preinitializing);
assert(!runtime->preinitialized);
assert(!runtime->core_initialized);
assert(!runtime->initialized);
assert(!runtime->_initialized);

runtime->open_code_hook = open_code_hook;
runtime->open_code_userdata = open_code_userdata;
Expand Down Expand Up @@ -476,6 +474,7 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
// Py_Initialize() must be running again.
// Reset to _PyRuntimeState_INIT.
memcpy(runtime, &initial, sizeof(*runtime));
assert(!runtime->_initialized);
}

if (gilstate_tss_init(runtime) != 0) {
Expand Down Expand Up @@ -647,14 +646,14 @@ free_interpreter(PyInterpreterState *interp)
main interpreter. We fix those fields here, in addition
to the other dynamically initialized fields.
*/
static void
static PyStatus
init_interpreter(PyInterpreterState *interp,
_PyRuntimeState *runtime, int64_t id,
PyInterpreterState *next,
PyThread_type_lock pending_lock)
{
if (interp->_initialized) {
Py_FatalError("interpreter already initialized");
return _PyStatus_ERR("interpreter already initialized");
}

assert(runtime != NULL);
Expand All @@ -675,7 +674,10 @@ init_interpreter(PyInterpreterState *interp,
memcpy(&interp->obmalloc.pools.used, temp, sizeof(temp));
}

_PyObject_InitState(interp);
PyStatus status = _PyObject_InitState(interp);
if (_PyStatus_EXCEPTION(status)) {
return status;
}

_PyEval_InitState(interp, pending_lock);
_PyGC_InitState(&interp->gc);
Expand All @@ -701,6 +703,7 @@ init_interpreter(PyInterpreterState *interp,
}
interp->f_opcode_trace_set = false;
interp->_initialized = 1;
return _PyStatus_OK();
}

PyInterpreterState *
Expand Down Expand Up @@ -772,7 +775,15 @@ PyInterpreterState_New(void)
}
interpreters->head = interp;

init_interpreter(interp, runtime, id, old_head, pending_lock);
PyStatus status = init_interpreter(interp, runtime,
id, old_head, pending_lock);
if (_PyStatus_EXCEPTION(status)) {
const char *err_msg = status.err_msg;
if (!err_msg) {
err_msg = "failed to initialize the interpreter";
}
Py_FatalError(err_msg);
}

HEAD_UNLOCK(runtime);
return interp;
Expand Down

0 comments on commit 6e8ba06

Please sign in to comment.