Skip to content

Commit d66eadb

Browse files
Add _PyXI_session_result.
1 parent d2ed756 commit d66eadb

File tree

3 files changed

+140
-109
lines changed

3 files changed

+140
-109
lines changed

Include/internal/pycore_crossinterp.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -350,17 +350,19 @@ typedef struct xi_session _PyXI_session;
350350
PyAPI_FUNC(_PyXI_session *) _PyXI_NewSession(void);
351351
PyAPI_FUNC(void) _PyXI_FreeSession(_PyXI_session *);
352352

353+
typedef struct {
354+
PyObject *excinfo;
355+
} _PyXI_session_result;
356+
353357
PyAPI_FUNC(int) _PyXI_Enter(
354358
_PyXI_session *session,
355359
PyInterpreterState *interp,
356-
PyObject *nsupdates);
357-
PyAPI_FUNC(void) _PyXI_Exit(_PyXI_session *session);
360+
PyObject *nsupdates,
361+
_PyXI_session_result *);
362+
PyAPI_FUNC(int) _PyXI_Exit(_PyXI_session *, _PyXI_session_result *);
358363

359364
PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace(_PyXI_session *);
360365

361-
PyAPI_FUNC(PyObject *) _PyXI_ApplyCapturedException(_PyXI_session *session);
362-
PyAPI_FUNC(int) _PyXI_HasCapturedException(_PyXI_session *session);
363-
364366

365367
/*************/
366368
/* other API */

Modules/_interpretersmodule.c

Lines changed: 32 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ _run_script(_PyXIData_t *script, PyObject *ns)
441441
static int
442442
_exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
443443
_PyXIData_t *script, PyObject *shareables,
444-
PyObject **p_excinfo)
444+
_PyXI_session_result *result)
445445
{
446446
assert(!_PyErr_Occurred(tstate));
447447
_PyXI_session *session = _PyXI_NewSession();
@@ -450,19 +450,9 @@ _exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
450450
}
451451

452452
// Prep and switch interpreters.
453-
if (_PyXI_Enter(session, interp, shareables) < 0) {
454-
if (_PyErr_Occurred(tstate)) {
455-
// If an error occured at this step, it means that interp
456-
// was not prepared and switched.
457-
_PyXI_FreeSession(session);
458-
return -1;
459-
}
460-
// Now, apply the error from another interpreter:
461-
PyObject *excinfo = _PyXI_ApplyCapturedException(session);
462-
if (excinfo != NULL) {
463-
*p_excinfo = excinfo;
464-
}
465-
assert(PyErr_Occurred());
453+
if (_PyXI_Enter(session, interp, shareables, result) < 0) {
454+
// If an error occured at this step, it means that interp
455+
// was not prepared and switched.
466456
_PyXI_FreeSession(session);
467457
return -1;
468458
}
@@ -476,20 +466,7 @@ _exec_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
476466

477467
finally:
478468
// Clean up and switch back.
479-
_PyXI_Exit(session);
480-
481-
// Propagate any exception out to the caller.
482-
assert(!PyErr_Occurred());
483-
if (res < 0) {
484-
PyObject *excinfo = _PyXI_ApplyCapturedException(session);
485-
if (excinfo != NULL) {
486-
*p_excinfo = excinfo;
487-
}
488-
}
489-
else {
490-
assert(!_PyXI_HasCapturedException(session));
491-
}
492-
469+
(void)_PyXI_Exit(session, result);
493470
_PyXI_FreeSession(session);
494471
return res;
495472
}
@@ -841,21 +818,23 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
841818
}
842819

843820
// Prep and switch interpreters, including apply the updates.
844-
if (_PyXI_Enter(session, interp, updates) < 0) {
845-
if (!PyErr_Occurred()) {
846-
_PyXI_ApplyCapturedException(session);
847-
assert(PyErr_Occurred());
848-
}
849-
else {
850-
assert(!_PyXI_HasCapturedException(session));
851-
}
821+
if (_PyXI_Enter(session, interp, updates, NULL) < 0) {
852822
_PyXI_FreeSession(session);
853823
return NULL;
854824
}
855825

856826
// Clean up and switch back.
857-
_PyXI_Exit(session);
827+
assert(!PyErr_Occurred());
828+
int res = _PyXI_Exit(session, NULL);
858829
_PyXI_FreeSession(session);
830+
assert(res == 0);
831+
if (res < 0) {
832+
// unreachable
833+
if (!PyErr_Occurred()) {
834+
PyErr_SetString(PyExc_RuntimeError, "unresolved error");
835+
}
836+
return NULL;
837+
}
859838

860839
Py_RETURN_NONE;
861840
}
@@ -917,12 +896,12 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
917896
return NULL;
918897
}
919898

920-
PyObject *excinfo = NULL;
921-
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &excinfo);
899+
_PyXI_session_result result = {0};
900+
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &result);
922901
_PyXIData_Release(&xidata);
923902
if (res < 0) {
924-
assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
925-
return excinfo;
903+
assert((result.excinfo == NULL) != (PyErr_Occurred() == NULL));
904+
return result.excinfo;
926905
}
927906
Py_RETURN_NONE;
928907
#undef FUNCNAME
@@ -980,12 +959,12 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
980959
return NULL;
981960
}
982961

983-
PyObject *excinfo = NULL;
984-
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &excinfo);
962+
_PyXI_session_result result = {0};
963+
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &result);
985964
_PyXIData_Release(&xidata);
986965
if (res < 0) {
987-
assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
988-
return excinfo;
966+
assert((result.excinfo == NULL) != (PyErr_Occurred() == NULL));
967+
return result.excinfo;
989968
}
990969
Py_RETURN_NONE;
991970
#undef FUNCNAME
@@ -1042,12 +1021,12 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
10421021
return NULL;
10431022
}
10441023

1045-
PyObject *excinfo = NULL;
1046-
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &excinfo);
1024+
_PyXI_session_result result = {0};
1025+
int res = _exec_in_interpreter(tstate, interp, &xidata, shared, &result);
10471026
_PyXIData_Release(&xidata);
10481027
if (res < 0) {
1049-
assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
1050-
return excinfo;
1028+
assert((result.excinfo == NULL) != (PyErr_Occurred() == NULL));
1029+
return result.excinfo;
10511030
}
10521031
Py_RETURN_NONE;
10531032
#undef FUNCNAME
@@ -1103,12 +1082,12 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
11031082
return NULL;
11041083
}
11051084

1106-
PyObject *excinfo = NULL;
1107-
int res = _exec_in_interpreter(tstate, interp, &xidata, NULL, &excinfo);
1085+
_PyXI_session_result result = {0};
1086+
int res = _exec_in_interpreter(tstate, interp, &xidata, NULL, &result);
11081087
_PyXIData_Release(&xidata);
11091088
if (res < 0) {
1110-
assert((excinfo == NULL) != (PyErr_Occurred() == NULL));
1111-
return excinfo;
1089+
assert((result.excinfo == NULL) != (PyErr_Occurred() == NULL));
1090+
return result.excinfo;
11121091
}
11131092
Py_RETURN_NONE;
11141093
#undef FUNCNAME

0 commit comments

Comments
 (0)