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

``