@@ -80,21 +80,11 @@ is_notshareable_raised(PyThreadState *tstate)
8080}
8181
8282static void
83- unwrap_not_shareable (PyThreadState * tstate )
83+ unwrap_not_shareable (PyThreadState * tstate , _PyXI_failure * failure )
8484{
85- if (!is_notshareable_raised (tstate )) {
86- return ;
87- }
88- PyObject * exc = _PyErr_GetRaisedException (tstate );
89- PyObject * cause = PyException_GetCause (exc );
90- if (cause != NULL ) {
91- Py_DECREF (exc );
92- exc = cause ;
85+ if (_PyXI_UnwrapNotShareableError (tstate , failure ) < 0 ) {
86+ _PyErr_Clear (tstate );
9387 }
94- else {
95- assert (PyException_GetContext (exc ) == NULL );
96- }
97- _PyErr_SetRaisedException (tstate , exc );
9888}
9989
10090
@@ -532,13 +522,30 @@ _interp_call_pack(PyThreadState *tstate, struct interp_call *call,
532522 return 0 ;
533523}
534524
525+ static void
526+ wrap_notshareable (PyThreadState * tstate , const char * label )
527+ {
528+ if (!is_notshareable_raised (tstate )) {
529+ return ;
530+ }
531+ assert (label != NULL && strlen (label ) > 0 );
532+ PyObject * cause = _PyErr_GetRaisedException (tstate );
533+ _PyXIData_FormatNotShareableError (tstate , "%s not shareable" , label );
534+ PyObject * exc = _PyErr_GetRaisedException (tstate );
535+ PyException_SetCause (exc , cause );
536+ _PyErr_SetRaisedException (tstate , exc );
537+ }
538+
535539static int
536540_interp_call_unpack (struct interp_call * call ,
537541 PyObject * * p_func , PyObject * * p_args , PyObject * * p_kwargs )
538542{
543+ PyThreadState * tstate = PyThreadState_Get ();
544+
539545 // Unpack the func.
540546 PyObject * func = _PyXIData_NewObject (call -> func );
541547 if (func == NULL ) {
548+ wrap_notshareable (tstate , "func" );
542549 return -1 ;
543550 }
544551 // Unpack the args.
@@ -553,6 +560,7 @@ _interp_call_unpack(struct interp_call *call,
553560 else {
554561 args = _PyXIData_NewObject (call -> args );
555562 if (args == NULL ) {
563+ wrap_notshareable (tstate , "args" );
556564 Py_DECREF (func );
557565 return -1 ;
558566 }
@@ -563,6 +571,7 @@ _interp_call_unpack(struct interp_call *call,
563571 if (call -> kwargs != NULL ) {
564572 kwargs = _PyXIData_NewObject (call -> kwargs );
565573 if (kwargs == NULL ) {
574+ wrap_notshareable (tstate , "kwargs" );
566575 Py_DECREF (func );
567576 Py_DECREF (args );
568577 return -1 ;
@@ -577,7 +586,7 @@ _interp_call_unpack(struct interp_call *call,
577586
578587static int
579588_make_call (struct interp_call * call ,
580- PyObject * * p_result , _PyXI_errcode * p_errcode )
589+ PyObject * * p_result , _PyXI_failure * failure )
581590{
582591 assert (call != NULL && call -> func != NULL );
583592 PyThreadState * tstate = _PyThreadState_GET ();
@@ -588,12 +597,10 @@ _make_call(struct interp_call *call,
588597 assert (func == NULL );
589598 assert (args == NULL );
590599 assert (kwargs == NULL );
591- * p_errcode = is_notshareable_raised (tstate )
592- ? _PyXI_ERR_NOT_SHAREABLE
593- : _PyXI_ERR_OTHER ;
600+ _PyXI_InitFailure (failure , _PyXI_ERR_OTHER , NULL );
601+ unwrap_not_shareable (tstate , failure );
594602 return -1 ;
595603 }
596- * p_errcode = _PyXI_ERR_NO_ERROR ;
597604
598605 // Make the call.
599606 PyObject * resobj = PyObject_Call (func , args , kwargs );
@@ -608,17 +615,17 @@ _make_call(struct interp_call *call,
608615}
609616
610617static int
611- _run_script (_PyXIData_t * script , PyObject * ns , _PyXI_errcode * p_errcode )
618+ _run_script (_PyXIData_t * script , PyObject * ns , _PyXI_failure * failure )
612619{
613620 PyObject * code = _PyXIData_NewObject (script );
614621 if (code == NULL ) {
615- * p_errcode = _PyXI_ERR_NOT_SHAREABLE ;
622+ _PyXI_InitFailure ( failure , _PyXI_ERR_NOT_SHAREABLE , NULL ) ;
616623 return -1 ;
617624 }
618625 PyObject * result = PyEval_EvalCode (code , ns , ns );
619626 Py_DECREF (code );
620627 if (result == NULL ) {
621- * p_errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION ;
628+ _PyXI_InitFailure ( failure , _PyXI_ERR_UNCAUGHT_EXCEPTION , NULL ) ;
622629 return -1 ;
623630 }
624631 assert (result == Py_None );
@@ -644,8 +651,14 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
644651 PyObject * shareables , struct run_result * runres )
645652{
646653 assert (!_PyErr_Occurred (tstate ));
654+ int res = -1 ;
655+ _PyXI_failure * failure = _PyXI_NewFailure ();
656+ if (failure == NULL ) {
657+ return -1 ;
658+ }
647659 _PyXI_session * session = _PyXI_NewSession ();
648660 if (session == NULL ) {
661+ _PyXI_FreeFailure (failure );
649662 return -1 ;
650663 }
651664 _PyXI_session_result result = {0 };
@@ -655,43 +668,44 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp,
655668 // If an error occured at this step, it means that interp
656669 // was not prepared and switched.
657670 _PyXI_FreeSession (session );
671+ _PyXI_FreeFailure (failure );
658672 assert (result .excinfo == NULL );
659673 return -1 ;
660674 }
661675
662676 // Run in the interpreter.
663- int res = -1 ;
664- _PyXI_errcode errcode = _PyXI_ERR_NO_ERROR ;
665677 if (script != NULL ) {
666678 assert (call == NULL );
667- PyObject * mainns = _PyXI_GetMainNamespace (session , & errcode );
679+ PyObject * mainns = _PyXI_GetMainNamespace (session , failure );
668680 if (mainns == NULL ) {
669681 goto finally ;
670682 }
671- res = _run_script (script , mainns , & errcode );
683+ res = _run_script (script , mainns , failure );
672684 }
673685 else {
674686 assert (call != NULL );
675687 PyObject * resobj ;
676- res = _make_call (call , & resobj , & errcode );
688+ res = _make_call (call , & resobj , failure );
677689 if (res == 0 ) {
678- res = _PyXI_Preserve (session , "resobj" , resobj , & errcode );
690+ res = _PyXI_Preserve (session , "resobj" , resobj , failure );
679691 Py_DECREF (resobj );
680692 if (res < 0 ) {
681693 goto finally ;
682694 }
683695 }
684696 }
685- int exitres ;
686697
687698finally :
688699 // Clean up and switch back.
689- exitres = _PyXI_Exit (session , errcode , & result );
700+ (void )res ;
701+ int exitres = _PyXI_Exit (session , failure , & result );
690702 assert (res == 0 || exitres != 0 );
691703 _PyXI_FreeSession (session );
704+ _PyXI_FreeFailure (failure );
692705
693706 res = exitres ;
694707 if (_PyErr_Occurred (tstate )) {
708+ // It's a directly propagated exception.
695709 assert (res < 0 );
696710 }
697711 else if (res < 0 ) {
@@ -1064,7 +1078,7 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs)
10641078
10651079 // Clean up and switch back.
10661080 assert (!PyErr_Occurred ());
1067- int res = _PyXI_Exit (session , _PyXI_ERR_NO_ERROR , NULL );
1081+ int res = _PyXI_Exit (session , NULL , NULL );
10681082 _PyXI_FreeSession (session );
10691083 assert (res == 0 );
10701084 if (res < 0 ) {
@@ -1124,7 +1138,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds)
11241138 // global variables. They will be resolved against __main__.
11251139 _PyXIData_t xidata = {0 };
11261140 if (_PyCode_GetScriptXIData (tstate , code , & xidata ) < 0 ) {
1127- unwrap_not_shareable (tstate );
1141+ unwrap_not_shareable (tstate , NULL );
11281142 return NULL ;
11291143 }
11301144
@@ -1188,7 +1202,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds)
11881202
11891203 _PyXIData_t xidata = {0 };
11901204 if (_PyCode_GetScriptXIData (tstate , script , & xidata ) < 0 ) {
1191- unwrap_not_shareable (tstate );
1205+ unwrap_not_shareable (tstate , NULL );
11921206 return NULL ;
11931207 }
11941208
@@ -1251,7 +1265,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds)
12511265
12521266 _PyXIData_t xidata = {0 };
12531267 if (_PyCode_GetScriptXIData (tstate , code , & xidata ) < 0 ) {
1254- unwrap_not_shareable (tstate );
1268+ unwrap_not_shareable (tstate , NULL );
12551269 return NULL ;
12561270 }
12571271
@@ -1542,16 +1556,16 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds)
15421556 }
15431557 PyObject * captured = NULL ;
15441558
1545- _PyXI_excinfo info = { 0 } ;
1546- if (_PyXI_InitExcInfo ( & info , exc ) < 0 ) {
1559+ _PyXI_excinfo * info = _PyXI_NewExcInfo ( exc ) ;
1560+ if (info == NULL ) {
15471561 goto finally ;
15481562 }
1549- captured = _PyXI_ExcInfoAsObject (& info );
1563+ captured = _PyXI_ExcInfoAsObject (info );
15501564 if (captured == NULL ) {
15511565 goto finally ;
15521566 }
15531567
1554- PyObject * formatted = _PyXI_FormatExcInfo (& info );
1568+ PyObject * formatted = _PyXI_FormatExcInfo (info );
15551569 if (formatted == NULL ) {
15561570 Py_CLEAR (captured );
15571571 goto finally ;
@@ -1564,7 +1578,7 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds)
15641578 }
15651579
15661580finally :
1567- _PyXI_ClearExcInfo ( & info );
1581+ _PyXI_FreeExcInfo ( info );
15681582 if (exc != exc_arg ) {
15691583 if (PyErr_Occurred ()) {
15701584 PyErr_SetRaisedException (exc );
0 commit comments