bpo-45711: use exc_value instead of exc_type to determine if exc_info… · python/cpython@c456dfa

@@ -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;

477482483+

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

}

509524525+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.

512551513552

The caller is responsible for ensuring that this call won't create

514553

any cycles in the exception context chain. */

515554

void

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;

520559521560

PyThreadState *tstate = _PyThreadState_GET();

522561523-

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

}

530569531570

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

}

581624582-

PyObject *exc, *val, *tb;

583-

_PyErr_Fetch(tstate, &exc, &val, &tb);

625+

PyObject *typ, *val, *tb;

626+

_PyErr_Fetch(tstate, &typ, &val, &tb);

584627585-

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

}

593647594648

/* _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