@@ -79,11 +79,16 @@ _PyErr_StackItem *
79
79
_PyErr_GetTopmostException (PyThreadState * tstate )
80
80
{
81
81
_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 ) &&
83
85
exc_info -> previous_item != NULL )
84
86
{
87
+ assert (exc_info -> exc_type == NULL || exc_info -> exc_type == Py_None );
85
88
exc_info = exc_info -> previous_item ;
86
89
}
90
+ assert (exc_info -> previous_item == NULL ||
91
+ (exc_info -> exc_type != NULL && exc_info -> exc_type != Py_None ));
87
92
return exc_info ;
88
93
}
89
94
@@ -471,10 +476,20 @@ _PyErr_GetExcInfo(PyThreadState *tstate,
471
476
PyObject * * p_type , PyObject * * p_value , PyObject * * p_traceback )
472
477
{
473
478
_PyErr_StackItem * exc_info = _PyErr_GetTopmostException (tstate );
474
- * p_type = exc_info -> exc_type ;
479
+
475
480
* p_value = exc_info -> exc_value ;
476
481
* p_traceback = exc_info -> exc_traceback ;
477
482
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
+
478
493
Py_XINCREF (* p_type );
479
494
Py_XINCREF (* p_value );
480
495
Py_XINCREF (* p_traceback );
@@ -507,42 +522,66 @@ PyErr_SetExcInfo(PyObject *p_type, PyObject *p_value, PyObject *p_traceback)
507
522
Py_XDECREF (oldtraceback );
508
523
}
509
524
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
+
510
549
/* Like PyErr_Restore(), but if an exception is already set,
511
550
set the context associated with it.
512
551
513
552
The caller is responsible for ensuring that this call won't create
514
553
any cycles in the exception context chain. */
515
554
void
516
- _PyErr_ChainExceptions (PyObject * exc , PyObject * val , PyObject * tb )
555
+ _PyErr_ChainExceptions (PyObject * typ , PyObject * val , PyObject * tb )
517
556
{
518
- if (exc == NULL )
557
+ if (typ == NULL )
519
558
return ;
520
559
521
560
PyThreadState * tstate = _PyThreadState_GET ();
522
561
523
- if (!PyExceptionClass_Check (exc )) {
562
+ if (!PyExceptionClass_Check (typ )) {
524
563
_PyErr_Format (tstate , PyExc_SystemError ,
525
564
"_PyErr_ChainExceptions: "
526
565
"exception %R is not a BaseException subclass" ,
527
- exc );
566
+ typ );
528
567
return ;
529
568
}
530
569
531
570
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 );
535
574
if (tb != NULL ) {
536
575
PyException_SetTraceback (val , tb );
537
576
Py_DECREF (tb );
538
577
}
539
- Py_DECREF (exc );
540
- _PyErr_NormalizeException (tstate , & exc2 , & val2 , & tb2 );
578
+ Py_DECREF (typ );
579
+ _PyErr_NormalizeException (tstate , & typ2 , & val2 , & tb2 );
541
580
PyException_SetContext (val2 , val );
542
- _PyErr_Restore (tstate , exc2 , val2 , tb2 );
581
+ _PyErr_Restore (tstate , typ2 , val2 , tb2 );
543
582
}
544
583
else {
545
- _PyErr_Restore (tstate , exc , val , tb );
584
+ _PyErr_Restore (tstate , typ , val , tb );
546
585
}
547
586
}
548
587
@@ -567,7 +606,11 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info)
567
606
} else {
568
607
exc_info_given = 1 ;
569
608
}
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 ) {
571
614
return ;
572
615
}
573
616
@@ -579,21 +622,32 @@ _PyErr_ChainStackItem(_PyErr_StackItem *exc_info)
579
622
tstate -> exc_info = exc_info ;
580
623
}
581
624
582
- PyObject * exc , * val , * tb ;
583
- _PyErr_Fetch (tstate , & exc , & val , & tb );
625
+ PyObject * typ , * val , * tb ;
626
+ _PyErr_Fetch (tstate , & typ , & val , & tb );
584
627
585
- PyObject * exc2 , * val2 , * tb2 ;
586
- exc2 = exc_info -> exc_type ;
628
+ PyObject * typ2 , * val2 , * tb2 ;
629
+ typ2 = exc_info -> exc_type ;
587
630
val2 = exc_info -> exc_value ;
588
631
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
590
644
if (tb2 != NULL ) {
591
645
PyException_SetTraceback (val2 , tb2 );
592
646
}
593
647
594
648
/* _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
597
651
Py_XDECREF (val );
598
652
Py_XDECREF (tb );
599
653
0 commit comments