@@ -79,11 +79,16 @@ _PyErr_StackItem *
7979_PyErr_GetTopmostException (PyThreadState * tstate )
8080{
8181 _PyErr_StackItem * exc_info = tstate -> exc_info ;
82- while ((exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None ) &&
82+ assert (exc_info );
83+
84+ while ((exc_info -> exc_value == NULL || exc_info -> exc_value == Py_None ) &&
8385 exc_info -> previous_item != NULL )
8486 {
87+ assert (exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None );
8588 exc_info = exc_info -> previous_item ;
8689 }
90+ assert (exc_info -> previous_item == NULL ||
91+ (exc_info -> exc_type != NULL && exc_info -> exc_type != Py_None ));
8792 return exc_info ;
8893}
8994
@@ -471,10 +476,20 @@ _PyErr_GetExcInfo(PyThreadState *tstate,
471476 PyObject * * p_type , PyObject * * p_value , PyObject * * p_traceback )
472477{
473478 _PyErr_StackItem * exc_info = _PyErr_GetTopmostException (tstate );
474- * p_type = exc_info -> exc_type ;
479+
475480 * p_value = exc_info -> exc_value ;
476481 * p_traceback = exc_info -> exc_traceback ;
477482
483+ if (* p_value == NULL || * p_value == Py_None ) {
484+ assert (exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None );
485+ * p_type = Py_None ;
486+ }
487+ else {
488+ assert (PyExceptionInstance_Check (* p_value ));
489+ assert (exc_info -> exc_type == PyExceptionInstance_Class (* p_value ));
490+ * p_type = PyExceptionInstance_Class (* p_value );
491+ }
492+
478493 Py_XINCREF (* p_type );
479494 Py_XINCREF (* p_value );
480495 Py_XINCREF (* p_traceback );
@@ -507,42 +522,66 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)
507522 Py_XDECREF (oldtraceback );
508523}
509524
525+
526+ PyObject *
527+ _PyErr_StackItemToExcInfoTuple (_PyErr_StackItem * err_info )
528+ {
529+ PyObject * exc_value = err_info -> exc_value ;
530+ if (exc_value == NULL ) {
531+ exc_value = Py_None ;
532+ }
533+
534+ assert (exc_value == Py_None || PyExceptionInstance_Check (exc_value ));
535+
536+ PyObject * exc_type = PyExceptionInstance_Check (exc_value ) ?
537+ PyExceptionInstance_Class (exc_value ) :
538+ Py_None ;
539+
540+ return Py_BuildValue (
541+ "(OOO)" ,
542+ exc_type ,
543+ exc_value ,
544+ err_info -> exc_traceback != NULL ?
545+ err_info -> exc_traceback : Py_None );
546+ }
547+
548+
510549/* Like PyErr_Restore(), but if an exception is already set,
511550 set the context associated with it.
512551
513552 The caller is responsible for ensuring that this call won't create
514553 any cycles in the exception context chain. */
515554void
516- _PyErr_ChainExceptions (PyObject * exc , PyObject * val , PyObject * tb )
555+ _PyErr_ChainExceptions (PyObject * typ , PyObject * val , PyObject * tb )
517556{
518- if (exc == NULL )
557+ if (typ == NULL )
519558 return ;
520559
521560 PyThreadState * tstate = _PyThreadState_GET ();
522561
523- if (!PyExceptionClass_Check (exc )) {
562+ if (!PyExceptionClass_Check (typ )) {
524563 _PyErr_Format (tstate , PyExc_SystemError ,
525564 "_PyErr_ChainExceptions: "
526565 "exception %R is not a BaseException subclass" ,
527- exc );
566+ typ );
528567 return ;
529568 }
530569
531570 if (_PyErr_Occurred (tstate )) {
532- PyObject * exc2 , * val2 , * tb2 ;
533- _PyErr_Fetch (tstate , & exc2 , & val2 , & tb2 );
534- _PyErr_NormalizeException (tstate , & exc , & val , & tb );
571+ PyObject * typ2 , * val2 , * tb2 ;
572+ _PyErr_Fetch (tstate , & typ2 , & val2 , & tb2 );
573+ _PyErr_NormalizeException (tstate , & typ , & val , & tb );
535574 if (tb != NULL ) {
536575 PyException_SetTraceback (val , tb );
537576 Py_DECREF (tb );
538577 }
539- Py_DECREF (exc );
540- _PyErr_NormalizeException (tstate , & exc2 , & val2 , & tb2 );
578+ Py_DECREF (typ );
579+ _PyErr_NormalizeException (tstate , & typ2 , & val2 , & tb2 );
541580 PyException_SetContext (val2 , val );
542- _PyErr_Restore (tstate , exc2 , val2 , tb2 );
581+ _PyErr_Restore (tstate , typ2 , val2 , tb2 );
543582 }
544583 else {
545- _PyErr_Restore (tstate , exc , val , tb );
584+ _PyErr_Restore (tstate , typ , val , tb );
546585 }
547586}
548587
@@ -567,7 +606,11 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info)
567606 } else {
568607 exc_info_given = 1 ;
569608 }
570- if (exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None ) {
609+
610+ assert ( (exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None ) ==
611+ (exc_info -> exc_value == NULL || exc_info -> exc_value == Py_None ) );
612+
613+ if (exc_info -> exc_value == NULL || exc_info -> exc_value == Py_None ) {
571614 return ;
572615 }
573616
@@ -579,21 +622,32 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info)
579622 tstate -> exc_info = exc_info ;
580623 }
581624
582- PyObject * exc , * val , * tb ;
583- _PyErr_Fetch (tstate , & exc , & val , & tb );
625+ PyObject * typ , * val , * tb ;
626+ _PyErr_Fetch (tstate , & typ , & val , & tb );
584627
585- PyObject * exc2 , * val2 , * tb2 ;
586- exc2 = exc_info -> exc_type ;
628+ PyObject * typ2 , * val2 , * tb2 ;
629+ typ2 = exc_info -> exc_type ;
587630 val2 = exc_info -> exc_value ;
588631 tb2 = exc_info -> exc_traceback ;
589- _PyErr_NormalizeException (tstate , & exc2 , & val2 , & tb2 );
632+ #ifdef Py_DEBUG
633+ PyObject * typ2_before = typ2 ;
634+ PyObject * val2_before = val2 ;
635+ PyObject * tb2_before = tb2 ;
636+ #endif
637+ _PyErr_NormalizeException (tstate , & typ2 , & val2 , & tb2 );
638+ #ifdef Py_DEBUG
639+ /* exc_info should already be normalized */
640+ assert (typ2 == typ2_before );
641+ assert (val2 == val2_before );
642+ assert (tb2 == tb2_before );
643+ #endif
590644 if (tb2 != NULL ) {
591645 PyException_SetTraceback (val2 , tb2 );
592646 }
593647
594648 /* _PyErr_SetObject sets the context from PyThreadState. */
595- _PyErr_SetObject (tstate , exc , val );
596- Py_DECREF (exc ); // since _PyErr_Occurred was true
649+ _PyErr_SetObject (tstate , typ , val );
650+ Py_DECREF (typ ); // since _PyErr_Occurred was true
597651 Py_XDECREF (val );
598652 Py_XDECREF (tb );
599653
0 commit comments