bpo-45711: use exc_value instead of exc_type to determine if exc_info… · python/cpython@c456dfa (original) (raw)
`@@ -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
``