@@ -512,60 +512,78 @@ _interp_call_pack(PyThreadState *tstate, struct interp_call *call,
512512}
513513
514514static int
515- _make_call (struct interp_call * call , PyObject * * p_result )
515+ _interp_call_unpack (struct interp_call * call ,
516+ PyObject * * p_func , PyObject * * p_args , PyObject * * p_kwargs )
516517{
517- assert (call != NULL && call -> func != NULL );
518- int res = -1 ;
519- PyObject * args = NULL ;
520- PyObject * kwargs = NULL ;
521- PyObject * resobj = NULL ;
522518 // Unpack the func.
523519 PyObject * func = _PyXIData_NewObject (call -> func );
524520 if (func == NULL ) {
525521 return -1 ;
526522 }
527523 // Unpack the args.
524+ PyObject * args ;
528525 if (call -> args == NULL ) {
529526 args = PyTuple_New (0 );
530527 if (args == NULL ) {
531- goto finally ;
528+ Py_DECREF (func );
529+ return -1 ;
532530 }
533531 }
534532 else {
535533 args = _PyXIData_NewObject (call -> args );
536534 if (args == NULL ) {
537- goto finally ;
535+ Py_DECREF (func );
536+ return -1 ;
538537 }
539538 assert (PyTuple_Check (args ));
540539 }
541540 // Unpack the kwargs.
541+ PyObject * kwargs = NULL ;
542542 if (call -> kwargs != NULL ) {
543543 kwargs = _PyXIData_NewObject (call -> kwargs );
544544 if (kwargs == NULL ) {
545- goto finally ;
545+ Py_DECREF (func );
546+ Py_DECREF (args );
547+ return -1 ;
546548 }
547549 assert (PyDict_Check (kwargs ));
548550 }
549- // Make the call.
550- resobj = PyObject_Call (func , args , kwargs );
551- if (resobj == NULL ) {
552- goto finally ;
551+ * p_func = func ;
552+ * p_args = args ;
553+ * p_kwargs = kwargs ;
554+ return 0 ;
555+ }
556+
557+ static int
558+ _make_call (struct interp_call * call , PyObject * * p_result , int * p_badtarget )
559+ {
560+ assert (call != NULL && call -> func != NULL );
561+
562+ PyObject * func , * args , * kwargs ;
563+ if (_interp_call_unpack (call , & func , & args , & kwargs ) < 0 ) {
564+ * p_badtarget = 1 ;
565+ return -1 ;
553566 }
554- * p_result = resobj ;
555- res = 0 ;
567+ * p_badtarget = 0 ;
556568
557- finally :
569+ // Make the call.
570+ PyObject * resobj = PyObject_Call (func , args , kwargs );
558571 Py_DECREF (func );
559572 Py_XDECREF (args );
560573 Py_XDECREF (kwargs );
561- return res ;
574+ if (resobj == NULL ) {
575+ return -1 ;
576+ }
577+ * p_result = resobj ;
578+ return 0 ;
562579}
563580
564581static int
565- _run_script (_PyXIData_t * script , PyObject * ns )
582+ _run_script (_PyXIData_t * script , PyObject * ns , int * p_badtarget )
566583{
567584 PyObject * code = _PyXIData_NewObject (script );
568585 if (code == NULL ) {
586+ * p_badtarget = 1 ;
569587 return -1 ;
570588 }
571589 PyObject * result = PyEval_EvalCode (code , ns , ns );
@@ -581,6 +599,7 @@ _run_script(_PyXIData_t *script, PyObject *ns)
581599struct run_result {
582600 PyObject * result ;
583601 PyObject * excinfo ;
602+ int badtarget ;
584603};
585604
586605static void
@@ -601,6 +620,7 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
601620 return -1 ;
602621 }
603622 _PyXI_session_result result = {0 };
623+ int badtarget = 0 ;
604624
605625 // Prep and switch interpreters.
606626 if (_PyXI_Enter (session , interp , shareables , & result ) < 0 ) {
@@ -617,12 +637,12 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
617637 if (mainns == NULL ) {
618638 goto finally ;
619639 }
620- res = _run_script (script , mainns );
640+ res = _run_script (script , mainns , & badtarget );
621641 }
622642 else {
623643 assert (call != NULL );
624644 PyObject * resobj ;
625- res = _make_call (call , & resobj );
645+ res = _make_call (call , & resobj , & badtarget );
626646 if (res == 0 ) {
627647 (void )_PyXI_Preserve (session , "resobj" , resobj );
628648 Py_DECREF (resobj );
@@ -635,9 +655,11 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
635655 _PyXI_FreeSession (session );
636656 if (res < 0 ) {
637657 runres -> excinfo = result .excinfo ;
658+ runres -> badtarget = badtarget ;
638659 }
639660 else if (result .excinfo != NULL ) {
640661 runres -> excinfo = result .excinfo ;
662+ runres -> badtarget = badtarget ;
641663 res = -1 ;
642664 }
643665 else {
@@ -1042,6 +1064,31 @@ unwrap_not_shareable(PyThreadState *tstate)
10421064 _PyErr_SetRaisedException (tstate , exc );
10431065}
10441066
1067+ static PyObject *
1068+ _handle_script_error (_PyXIData_t * script , struct run_result * runres )
1069+ {
1070+ if (runres -> excinfo == NULL ) {
1071+ assert (PyErr_Occurred ());
1072+ assert (!runres -> badtarget );
1073+ return NULL ;
1074+ }
1075+ assert (!PyErr_Occurred ());
1076+ if (!runres -> badtarget ) {
1077+ return runres -> excinfo ;
1078+ }
1079+ PyObject * code = _PyXIData_NewObject (script );
1080+ if (code != NULL ) {
1081+ // Either the problem is intermittent or only affects subinterpreters.
1082+ // This is highly unlikely.
1083+ return runres -> excinfo ;
1084+ }
1085+ assert (PyErr_Occurred ());
1086+ PyThreadState * tstate = _PyThreadState_GET ();
1087+ unwrap_not_shareable (tstate );
1088+ Py_DECREF (runres -> excinfo );
1089+ return NULL ;
1090+ }
1091+
10451092static PyObject *
10461093interp_exec (PyObject * self , PyObject * args , PyObject * kwds )
10471094{
@@ -1080,7 +1127,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
10801127 _PyXIData_Release (& xidata );
10811128 if (res < 0 ) {
10821129 assert ((runres .excinfo == NULL ) != (PyErr_Occurred () == NULL ));
1083- return runres . excinfo ;
1130+ return _handle_script_error ( & xidata , & runres ) ;
10841131 }
10851132 Py_RETURN_NONE ;
10861133#undef FUNCNAME
@@ -1144,7 +1191,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11441191 _PyXIData_Release (& xidata );
11451192 if (res < 0 ) {
11461193 assert ((runres .excinfo == NULL ) != (PyErr_Occurred () == NULL ));
1147- return runres . excinfo ;
1194+ return _handle_script_error ( & xidata , & runres ) ;
11481195 }
11491196 Py_RETURN_NONE ;
11501197#undef FUNCNAME
@@ -1207,7 +1254,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
12071254 _PyXIData_Release (& xidata );
12081255 if (res < 0 ) {
12091256 assert ((runres .excinfo == NULL ) != (PyErr_Occurred () == NULL ));
1210- return runres . excinfo ;
1257+ return _handle_script_error ( & xidata , & runres ) ;
12111258 }
12121259 Py_RETURN_NONE ;
12131260#undef FUNCNAME
@@ -1222,6 +1269,32 @@ are not supported. Methods and other callables are not supported either.\n\
12221269\n\
12231270(See " MODULE_NAME_STR ".exec()." );
12241271
1272+ static int
1273+ handle_call_error (struct interp_call * call , struct run_result * runres )
1274+ {
1275+ if (runres -> excinfo == NULL ) {
1276+ assert (PyErr_Occurred ());
1277+ assert (!runres -> badtarget );
1278+ return -1 ;
1279+ }
1280+ assert (!PyErr_Occurred ());
1281+ if (!runres -> badtarget ) {
1282+ return 0 ;
1283+ }
1284+
1285+ PyObject * func , * args , * kwargs ;
1286+ if (_interp_call_unpack (call , & func , & args , & kwargs ) == 0 ) {
1287+ // Either the problem is intermittent or only affects subinterpreters.
1288+ // This is highly unlikely.
1289+ return 0 ;
1290+ }
1291+ assert (PyErr_Occurred ());
1292+ PyThreadState * tstate = _PyThreadState_GET ();
1293+ unwrap_not_shareable (tstate );
1294+ Py_CLEAR (runres -> excinfo );
1295+ return -1 ;
1296+ }
1297+
12251298static PyObject *
12261299interp_call (PyObject * self , PyObject * args , PyObject * kwds )
12271300{
@@ -1259,11 +1332,9 @@ interp_call(PyObject *self, PyObject *args, PyObject *kwds)
12591332 PyObject * res_and_exc = NULL ;
12601333 struct run_result runres = {0 };
12611334 if (_run_in_interpreter (tstate , interp , NULL , & call , NULL , & runres ) < 0 ) {
1262- if (runres .excinfo == NULL ) {
1263- assert (_PyErr_Occurred (tstate ));
1335+ if (handle_call_error (& call , & runres ) < 0 ) {
12641336 goto finally ;
12651337 }
1266- assert (!_PyErr_Occurred (tstate ));
12671338 }
12681339 assert (runres .result == NULL || runres .excinfo == NULL );
12691340 res_and_exc = Py_BuildValue ("OO" ,
0 commit comments