Skip to content

Commit 3d9645b

Browse files
ericsnowcurrentlywarsaw
authored andcommitted
pythongh-98608: Stop Treating All Errors from _Py_NewInterpreterFromConfig() as Fatal (pythongh-102657)
Prior to this change, errors in _Py_NewInterpreterFromConfig() were always fatal. Instead, callers should be able to handle such errors and keep going. That's what this change supports. (This was an oversight in the original implementation of _Py_NewInterpreterFromConfig().) Note that the existing [fatal] behavior of the public Py_NewInterpreter() is preserved. python#98608
1 parent 973798f commit 3d9645b

File tree

6 files changed

+27
-17
lines changed

6 files changed

+27
-17
lines changed

Include/cpython/initconfig.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ PyAPI_FUNC(PyStatus) PyStatus_Exit(int exitcode);
2525
PyAPI_FUNC(int) PyStatus_IsError(PyStatus err);
2626
PyAPI_FUNC(int) PyStatus_IsExit(PyStatus err);
2727
PyAPI_FUNC(int) PyStatus_Exception(PyStatus err);
28+
PyAPI_FUNC(PyObject *) _PyErr_SetFromPyStatus(PyStatus status);
2829

2930
/* --- PyWideStringList ------------------------------------------------ */
3031

Include/cpython/pylifecycle.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,5 +62,6 @@ PyAPI_FUNC(int) _Py_CoerceLegacyLocale(int warn);
6262
PyAPI_FUNC(int) _Py_LegacyLocaleDetected(int warn);
6363
PyAPI_FUNC(char *) _Py_SetLocaleFromEnv(int category);
6464

65-
PyAPI_FUNC(PyThreadState *) _Py_NewInterpreterFromConfig(
66-
const _PyInterpreterConfig *);
65+
PyAPI_FUNC(PyStatus) _Py_NewInterpreterFromConfig(
66+
PyThreadState **tstate_p,
67+
const _PyInterpreterConfig *config);

Include/internal/pycore_initconfig.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,6 @@ struct pyruntimestate;
4444
#define _PyStatus_UPDATE_FUNC(err) \
4545
do { (err).func = _PyStatus_GET_FUNC(); } while (0)
4646

47-
PyObject* _PyErr_SetFromPyStatus(PyStatus status);
48-
4947
/* --- PyWideStringList ------------------------------------------------ */
5048

5149
#define _PyWideStringList_INIT (PyWideStringList){.length = 0, .items = NULL}

Modules/_testcapimodule.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1538,15 +1538,19 @@ run_in_subinterp_with_config(PyObject *self, PyObject *args, PyObject *kwargs)
15381538
.allow_daemon_threads = allow_daemon_threads,
15391539
.check_multi_interp_extensions = check_multi_interp_extensions,
15401540
};
1541-
substate = _Py_NewInterpreterFromConfig(&config);
1542-
if (substate == NULL) {
1541+
PyStatus status = _Py_NewInterpreterFromConfig(&substate, &config);
1542+
if (PyStatus_Exception(status)) {
15431543
/* Since no new thread state was created, there is no exception to
15441544
propagate; raise a fresh one after swapping in the old thread
15451545
state. */
15461546
PyThreadState_Swap(mainstate);
1547+
_PyErr_SetFromPyStatus(status);
1548+
PyObject *exc = PyErr_GetRaisedException();
15471549
PyErr_SetString(PyExc_RuntimeError, "sub-interpreter creation failed");
1550+
_PyErr_ChainExceptions1(exc);
15481551
return NULL;
15491552
}
1553+
assert(substate != NULL);
15501554
r = PyRun_SimpleStringFlags(code, &cflags);
15511555
Py_EndInterpreter(substate);
15521556

Modules/_xxsubinterpretersmodule.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -526,15 +526,20 @@ interp_create(PyObject *self, PyObject *args, PyObject *kwds)
526526
? (_PyInterpreterConfig)_PyInterpreterConfig_INIT
527527
: (_PyInterpreterConfig)_PyInterpreterConfig_LEGACY_INIT;
528528
// XXX Possible GILState issues?
529-
PyThreadState *tstate = _Py_NewInterpreterFromConfig(&config);
529+
PyThreadState *tstate = NULL;
530+
PyStatus status = _Py_NewInterpreterFromConfig(&tstate, &config);
530531
PyThreadState_Swap(save_tstate);
531-
if (tstate == NULL) {
532+
if (PyStatus_Exception(status)) {
532533
/* Since no new thread state was created, there is no exception to
533534
propagate; raise a fresh one after swapping in the old thread
534535
state. */
536+
_PyErr_SetFromPyStatus(status);
537+
PyObject *exc = PyErr_GetRaisedException();
535538
PyErr_SetString(PyExc_RuntimeError, "interpreter creation failed");
539+
_PyErr_ChainExceptions1(exc);
536540
return NULL;
537541
}
542+
assert(tstate != NULL);
538543
PyInterpreterState *interp = PyThreadState_GetInterpreter(tstate);
539544
PyObject *idobj = _PyInterpreterState_GetIDObject(interp);
540545
if (idobj == NULL) {

Python/pylifecycle.c

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2065,22 +2065,23 @@ new_interpreter(PyThreadState **tstate_p, const _PyInterpreterConfig *config)
20652065
return status;
20662066
}
20672067

2068-
PyThreadState *
2069-
_Py_NewInterpreterFromConfig(const _PyInterpreterConfig *config)
2068+
PyStatus
2069+
_Py_NewInterpreterFromConfig(PyThreadState **tstate_p,
2070+
const _PyInterpreterConfig *config)
20702071
{
2071-
PyThreadState *tstate = NULL;
2072-
PyStatus status = new_interpreter(&tstate, config);
2073-
if (_PyStatus_EXCEPTION(status)) {
2074-
Py_ExitStatusException(status);
2075-
}
2076-
return tstate;
2072+
return new_interpreter(tstate_p, config);
20772073
}
20782074

20792075
PyThreadState *
20802076
Py_NewInterpreter(void)
20812077
{
2078+
PyThreadState *tstate = NULL;
20822079
const _PyInterpreterConfig config = _PyInterpreterConfig_LEGACY_INIT;
2083-
return _Py_NewInterpreterFromConfig(&config);
2080+
PyStatus status = _Py_NewInterpreterFromConfig(&tstate, &config);
2081+
if (_PyStatus_EXCEPTION(status)) {
2082+
Py_ExitStatusException(status);
2083+
}
2084+
return tstate;
20842085
}
20852086

20862087
/* Delete an interpreter and its last thread. This requires that the

0 commit comments

Comments
 (0)