| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 6eb6c5d commit c7f4a80
5 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -303,10 +303,10 @@ typedef struct _excinfo { | |||
| 303 | 303 | const char *errdisplay; | |
| 304 | 304 | } _PyXI_excinfo; | |
| 305 | 305 | ||
| 306 | - PyAPI_FUNC(int) _PyXI_InitExcInfo(_PyXI_excinfo *info, PyObject *exc); | ||
| 306 | + PyAPI_FUNC(_PyXI_excinfo *) _PyXI_NewExcInfo(PyObject *exc); | ||
| 307 | + PyAPI_FUNC(void) _PyXI_FreeExcInfo(_PyXI_excinfo *info); | ||
| 307 | 308 | PyAPI_FUNC(PyObject *) _PyXI_FormatExcInfo(_PyXI_excinfo *info); | |
| 308 | 309 | PyAPI_FUNC(PyObject *) _PyXI_ExcInfoAsObject(_PyXI_excinfo *info); | |
| 309 | - PyAPI_FUNC(void) _PyXI_ClearExcInfo(_PyXI_excinfo *info); | ||
| 310 | 310 | ||
| 311 | 311 | ||
| 312 | 312 | typedef enum error_code { | |
@@ -322,19 +322,20 @@ typedef enum error_code { | |||
| 322 | 322 | _PyXI_ERR_NOT_SHAREABLE = -9, | |
| 323 | 323 | } _PyXI_errcode; | |
| 324 | 324 | ||
| 325 | + typedef struct xi_failure _PyXI_failure; | ||
| 325 | 326 | ||
| 326 | - typedef struct _sharedexception { | ||
| 327 | - // The originating interpreter. | ||
| 328 | - PyInterpreterState *interp; | ||
| 329 | - // The kind of error to propagate. | ||
| 330 | - _PyXI_errcode code; | ||
| 331 | - // The exception information to propagate, if applicable. | ||
| 332 | - // This is populated only for some error codes, | ||
| 333 | - // but always for _PyXI_ERR_UNCAUGHT_EXCEPTION. | ||
| 334 | - _PyXI_excinfo uncaught; | ||
| 335 | - } _PyXI_error; | ||
| 327 | + PyAPI_FUNC(_PyXI_failure *) _PyXI_NewFailure(void); | ||
| 328 | + PyAPI_FUNC(void) _PyXI_FreeFailure(_PyXI_failure *); | ||
| 329 | + PyAPI_FUNC(_PyXI_errcode) _PyXI_GetFailureCode(_PyXI_failure *); | ||
| 330 | + PyAPI_FUNC(int) _PyXI_InitFailure(_PyXI_failure *, _PyXI_errcode, PyObject *); | ||
| 331 | + PyAPI_FUNC(void) _PyXI_InitFailureUTF8( | ||
| 332 | + _PyXI_failure *, | ||
| 333 | + _PyXI_errcode, | ||
| 334 | + const char *); | ||
| 336 | 335 | ||
| 337 | - PyAPI_FUNC(PyObject *) _PyXI_ApplyError(_PyXI_error *err); | ||
| 336 | + PyAPI_FUNC(int) _PyXI_UnwrapNotShareableError( | ||
| 337 | + PyThreadState *, | ||
| 338 | + _PyXI_failure *); | ||
| 338 | 339 | ||
| 339 | 340 | ||
| 340 | 341 | // A cross-interpreter session involves entering an interpreter | |
@@ -366,19 +367,21 @@ PyAPI_FUNC(int) _PyXI_Enter( | |||
| 366 | 367 | _PyXI_session_result *); | |
| 367 | 368 | PyAPI_FUNC(int) _PyXI_Exit( | |
| 368 | 369 | _PyXI_session *, | |
| 369 | - _PyXI_errcode, | ||
| 370 | + _PyXI_failure *, | ||
| 370 | 371 | _PyXI_session_result *); | |
| 371 | 372 | ||
| 372 | 373 | PyAPI_FUNC(PyObject *) _PyXI_GetMainNamespace( | |
| 373 | 374 | _PyXI_session *, | |
| 374 | - _PyXI_errcode *); | ||
| 375 | + _PyXI_failure *); | ||
| 375 | 376 | ||
| 376 | 377 | PyAPI_FUNC(int) _PyXI_Preserve( | |
| 377 | 378 | _PyXI_session *, | |
| 378 | 379 | const char *, | |
| 379 | 380 | PyObject *, | |
| 380 | - _PyXI_errcode *); | ||
| 381 | - PyAPI_FUNC(PyObject *) _PyXI_GetPreserved(_PyXI_session_result *, const char *); | ||
| 381 | + _PyXI_failure *); | ||
| 382 | + PyAPI_FUNC(PyObject *) _PyXI_GetPreserved( | ||
| 383 | + _PyXI_session_result *, | ||
| 384 | + const char *); | ||
| 382 | 385 | ||
| 383 | 386 | ||
| 384 | 387 | /*************/ | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -80,21 +80,11 @@ is_notshareable_raised(PyThreadState *tstate) | |||
| 80 | 80 | } | |
| 81 | 81 | ||
| 82 | 82 | static void | |
| 83 | - unwrap_not_shareable(PyThreadState *tstate) | ||
| 83 | + unwrap_not_shareable(PyThreadState *tstate, _PyXI_failure *failure) | ||
| 84 | 84 | { | |
| 85 | - if (!is_notshareable_raised(tstate)) { | ||
| 86 | - return; | ||
| 87 | - } | ||
| 88 | - PyObject *exc = _PyErr_GetRaisedException(tstate); | ||
| 89 | - PyObject *cause = PyException_GetCause(exc); | ||
| 90 | - if (cause != NULL) { | ||
| 91 | - Py_DECREF(exc); | ||
| 92 | - exc = cause; | ||
| 85 | + if (_PyXI_UnwrapNotShareableError(tstate, failure) < 0) { | ||
| 86 | + _PyErr_Clear(tstate); | ||
| 93 | 87 | } | |
| 94 | - else { | ||
| 95 | - assert(PyException_GetContext(exc) == NULL); | ||
| 96 | - } | ||
| 97 | - _PyErr_SetRaisedException(tstate, exc); | ||
| 98 | 88 | } | |
| 99 | 89 | ||
| 100 | 90 | ||
@@ -532,13 +522,30 @@ _interp_call_pack(PyThreadState *tstate, struct interp_call *call, | |||
| 532 | 522 | return 0; | |
| 533 | 523 | } | |
| 534 | 524 | ||
| 525 | + static void | ||
| 526 | + wrap_notshareable(PyThreadState *tstate, const char *label) | ||
| 527 | + { | ||
| 528 | + if (!is_notshareable_raised(tstate)) { | ||
| 529 | + return; | ||
| 530 | + } | ||
| 531 | + assert(label != NULL && strlen(label) > 0); | ||
| 532 | + PyObject *cause = _PyErr_GetRaisedException(tstate); | ||
| 533 | + _PyXIData_FormatNotShareableError(tstate, "%s not shareable", label); | ||
| 534 | + PyObject *exc = _PyErr_GetRaisedException(tstate); | ||
| 535 | + PyException_SetCause(exc, cause); | ||
| 536 | + _PyErr_SetRaisedException(tstate, exc); | ||
| 537 | + } | ||
| 538 | + | ||
| 535 | 539 | static int | |
| 536 | 540 | _interp_call_unpack(struct interp_call *call, | |
| 537 | 541 | PyObject **p_func, PyObject **p_args, PyObject **p_kwargs) | |
| 538 | 542 | { | |
| 543 | + PyThreadState *tstate = PyThreadState_Get(); | ||
| 544 | + | ||
| 539 | 545 | // Unpack the func. | |
| 540 | 546 | PyObject *func = _PyXIData_NewObject(call->func); | |
| 541 | 547 | if (func == NULL) { | |
| 548 | + wrap_notshareable(tstate, "func"); | ||
| 542 | 549 | return -1; | |
| 543 | 550 | } | |
| 544 | 551 | // Unpack the args. | |
@@ -553,6 +560,7 @@ _interp_call_unpack(struct interp_call *call, | |||
| 553 | 560 | else { | |
| 554 | 561 | args = _PyXIData_NewObject(call->args); | |
| 555 | 562 | if (args == NULL) { | |
| 563 | + wrap_notshareable(tstate, "args"); | ||
| 556 | 564 | Py_DECREF(func); | |
| 557 | 565 | return -1; | |
| 558 | 566 | } | |
@@ -563,6 +571,7 @@ _interp_call_unpack(struct interp_call *call, | |||
| 563 | 571 | if (call->kwargs != NULL) { | |
| 564 | 572 | kwargs = _PyXIData_NewObject(call->kwargs); | |
| 565 | 573 | if (kwargs == NULL) { | |
| 574 | + wrap_notshareable(tstate, "kwargs"); | ||
| 566 | 575 | Py_DECREF(func); | |
| 567 | 576 | Py_DECREF(args); | |
| 568 | 577 | return -1; | |
@@ -577,7 +586,7 @@ _interp_call_unpack(struct interp_call *call, | |||
| 577 | 586 | ||
| 578 | 587 | static int | |
| 579 | 588 | _make_call(struct interp_call *call, | |
| 580 | - PyObject **p_result, _PyXI_errcode *p_errcode) | ||
| 589 | + PyObject **p_result, _PyXI_failure *failure) | ||
| 581 | 590 | { | |
| 582 | 591 | assert(call != NULL && call->func != NULL); | |
| 583 | 592 | PyThreadState *tstate = _PyThreadState_GET(); | |
@@ -588,12 +597,10 @@ _make_call(struct interp_call *call, | |||
| 588 | 597 | assert(func == NULL); | |
| 589 | 598 | assert(args == NULL); | |
| 590 | 599 | assert(kwargs == NULL); | |
| 591 | - *p_errcode = is_notshareable_raised(tstate) | ||
| 592 | - ? _PyXI_ERR_NOT_SHAREABLE | ||
| 593 | - : _PyXI_ERR_OTHER; | ||
| 600 | + _PyXI_InitFailure(failure, _PyXI_ERR_OTHER, NULL); | ||
| 601 | + unwrap_not_shareable(tstate, failure); | ||
| 594 | 602 | return -1; | |
| 595 | 603 | } | |
| 596 | - *p_errcode = _PyXI_ERR_NO_ERROR; | ||
| 597 | 604 | ||
| 598 | 605 | // Make the call. | |
| 599 | 606 | PyObject *resobj = PyObject_Call(func, args, kwargs); | |
@@ -608,17 +615,17 @@ _make_call(struct interp_call *call, | |||
| 608 | 615 | } | |
| 609 | 616 | ||
| 610 | 617 | static int | |
| 611 | - _run_script(_PyXIData_t *script, PyObject *ns, _PyXI_errcode *p_errcode) | ||
| 618 | + _run_script(_PyXIData_t *script, PyObject *ns, _PyXI_failure *failure) | ||
| 612 | 619 | { | |
| 613 | 620 | PyObject *code = _PyXIData_NewObject(script); | |
| 614 | 621 | if (code == NULL) { | |
| 615 | - *p_errcode = _PyXI_ERR_NOT_SHAREABLE; | ||
| 622 | + _PyXI_InitFailure(failure, _PyXI_ERR_NOT_SHAREABLE, NULL); | ||
| 616 | 623 | return -1; | |
| 617 | 624 | } | |
| 618 | 625 | PyObject *result = PyEval_EvalCode(code, ns, ns); | |
| 619 | 626 | Py_DECREF(code); | |
| 620 | 627 | if (result == NULL) { | |
| 621 | - *p_errcode = _PyXI_ERR_UNCAUGHT_EXCEPTION; | ||
| 628 | + _PyXI_InitFailure(failure, _PyXI_ERR_UNCAUGHT_EXCEPTION, NULL); | ||
| 622 | 629 | return -1; | |
| 623 | 630 | } | |
| 624 | 631 | assert(result == Py_None); | |
@@ -644,8 +651,14 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp, | |||
| 644 | 651 | PyObject *shareables, struct run_result *runres) | |
| 645 | 652 | { | |
| 646 | 653 | assert(!_PyErr_Occurred(tstate)); | |
| 654 | + int res = -1; | ||
| 655 | + _PyXI_failure *failure = _PyXI_NewFailure(); | ||
| 656 | + if (failure == NULL) { | ||
| 657 | + return -1; | ||
| 658 | + } | ||
| 647 | 659 | _PyXI_session *session = _PyXI_NewSession(); | |
| 648 | 660 | if (session == NULL) { | |
| 661 | + _PyXI_FreeFailure(failure); | ||
| 649 | 662 | return -1; | |
| 650 | 663 | } | |
| 651 | 664 | _PyXI_session_result result = {0}; | |
@@ -655,43 +668,44 @@ _run_in_interpreter(PyThreadState *tstate, PyInterpreterState *interp, | |||
| 655 | 668 | // If an error occured at this step, it means that interp | |
| 656 | 669 | // was not prepared and switched. | |
| 657 | 670 | _PyXI_FreeSession(session); | |
| 671 | + _PyXI_FreeFailure(failure); | ||
| 658 | 672 | assert(result.excinfo == NULL); | |
| 659 | 673 | return -1; | |
| 660 | 674 | } | |
| 661 | 675 | ||
| 662 | 676 | // Run in the interpreter. | |
| 663 | - int res = -1; | ||
| 664 | - _PyXI_errcode errcode = _PyXI_ERR_NO_ERROR; | ||
| 665 | 677 | if (script != NULL) { | |
| 666 | 678 | assert(call == NULL); | |
| 667 | - PyObject *mainns = _PyXI_GetMainNamespace(session, &errcode); | ||
| 679 | + PyObject *mainns = _PyXI_GetMainNamespace(session, failure); | ||
| 668 | 680 | if (mainns == NULL) { | |
| 669 | 681 | goto finally; | |
| 670 | 682 | } | |
| 671 | - res = _run_script(script, mainns, &errcode); | ||
| 683 | + res = _run_script(script, mainns, failure); | ||
| 672 | 684 | } | |
| 673 | 685 | else { | |
| 674 | 686 | assert(call != NULL); | |
| 675 | 687 | PyObject *resobj; | |
| 676 | - res = _make_call(call, &resobj, &errcode); | ||
| 688 | + res = _make_call(call, &resobj, failure); | ||
| 677 | 689 | if (res == 0) { | |
| 678 | - res = _PyXI_Preserve(session, "resobj", resobj, &errcode); | ||
| 690 | + res = _PyXI_Preserve(session, "resobj", resobj, failure); | ||
| 679 | 691 | Py_DECREF(resobj); | |
| 680 | 692 | if (res < 0) { | |
| 681 | 693 | goto finally; | |
| 682 | 694 | } | |
| 683 | 695 | } | |
| 684 | 696 | } | |
| 685 | - int exitres; | ||
| 686 | 697 | ||
| 687 | 698 | finally: | |
| 688 | 699 | // Clean up and switch back. | |
| 689 | - exitres = _PyXI_Exit(session, errcode, &result); | ||
| 700 | + (void)res; | ||
| 701 | + int exitres = _PyXI_Exit(session, failure, &result); | ||
| 690 | 702 | assert(res == 0 || exitres != 0); | |
| 691 | 703 | _PyXI_FreeSession(session); | |
| 704 | + _PyXI_FreeFailure(failure); | ||
| 692 | 705 | ||
| 693 | 706 | res = exitres; | |
| 694 | 707 | if (_PyErr_Occurred(tstate)) { | |
| 708 | + // It's a directly propagated exception. | ||
| 695 | 709 | assert(res < 0); | |
| 696 | 710 | } | |
| 697 | 711 | else if (res < 0) { | |
@@ -1064,7 +1078,7 @@ interp_set___main___attrs(PyObject *self, PyObject *args, PyObject *kwargs) | |||
| 1064 | 1078 | ||
| 1065 | 1079 | // Clean up and switch back. | |
| 1066 | 1080 | assert(!PyErr_Occurred()); | |
| 1067 | - int res = _PyXI_Exit(session, _PyXI_ERR_NO_ERROR, NULL); | ||
| 1081 | + int res = _PyXI_Exit(session, NULL, NULL); | ||
| 1068 | 1082 | _PyXI_FreeSession(session); | |
| 1069 | 1083 | assert(res == 0); | |
| 1070 | 1084 | if (res < 0) { | |
@@ -1124,7 +1138,7 @@ interp_exec(PyObject *self, PyObject *args, PyObject *kwds) | |||
| 1124 | 1138 | // global variables. They will be resolved against __main__. | |
| 1125 | 1139 | _PyXIData_t xidata = {0}; | |
| 1126 | 1140 | if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) { | |
| 1127 | - unwrap_not_shareable(tstate); | ||
| 1141 | + unwrap_not_shareable(tstate, NULL); | ||
| 1128 | 1142 | return NULL; | |
| 1129 | 1143 | } | |
| 1130 | 1144 | ||
@@ -1188,7 +1202,7 @@ interp_run_string(PyObject *self, PyObject *args, PyObject *kwds) | |||
| 1188 | 1202 | ||
| 1189 | 1203 | _PyXIData_t xidata = {0}; | |
| 1190 | 1204 | if (_PyCode_GetScriptXIData(tstate, script, &xidata) < 0) { | |
| 1191 | - unwrap_not_shareable(tstate); | ||
| 1205 | + unwrap_not_shareable(tstate, NULL); | ||
| 1192 | 1206 | return NULL; | |
| 1193 | 1207 | } | |
| 1194 | 1208 | ||
@@ -1251,7 +1265,7 @@ interp_run_func(PyObject *self, PyObject *args, PyObject *kwds) | |||
| 1251 | 1265 | ||
| 1252 | 1266 | _PyXIData_t xidata = {0}; | |
| 1253 | 1267 | if (_PyCode_GetScriptXIData(tstate, code, &xidata) < 0) { | |
| 1254 | - unwrap_not_shareable(tstate); | ||
| 1268 | + unwrap_not_shareable(tstate, NULL); | ||
| 1255 | 1269 | return NULL; | |
| 1256 | 1270 | } | |
| 1257 | 1271 | ||
@@ -1542,16 +1556,16 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) | |||
| 1542 | 1556 | } | |
| 1543 | 1557 | PyObject *captured = NULL; | |
| 1544 | 1558 | ||
| 1545 | - _PyXI_excinfo info = {0}; | ||
| 1546 | - if (_PyXI_InitExcInfo(&info, exc) < 0) { | ||
| 1559 | + _PyXI_excinfo *info = _PyXI_NewExcInfo(exc); | ||
| 1560 | + if (info == NULL) { | ||
| 1547 | 1561 | goto finally; | |
| 1548 | 1562 | } | |
| 1549 | - captured = _PyXI_ExcInfoAsObject(&info); | ||
| 1563 | + captured = _PyXI_ExcInfoAsObject(info); | ||
| 1550 | 1564 | if (captured == NULL) { | |
| 1551 | 1565 | goto finally; | |
| 1552 | 1566 | } | |
| 1553 | 1567 | ||
| 1554 | - PyObject *formatted = _PyXI_FormatExcInfo(&info); | ||
| 1568 | + PyObject *formatted = _PyXI_FormatExcInfo(info); | ||
| 1555 | 1569 | if (formatted == NULL) { | |
| 1556 | 1570 | Py_CLEAR(captured); | |
| 1557 | 1571 | goto finally; | |
@@ -1564,7 +1578,7 @@ capture_exception(PyObject *self, PyObject *args, PyObject *kwds) | |||
| 1564 | 1578 | } | |
| 1565 | 1579 | ||
| 1566 | 1580 | finally: | |
| 1567 | - _PyXI_ClearExcInfo(&info); | ||
| 1581 | + _PyXI_FreeExcInfo(info); | ||
| 1568 | 1582 | if (exc != exc_arg) { | |
| 1569 | 1583 | if (PyErr_Occurred()) { | |
| 1570 | 1584 | PyErr_SetRaisedException(exc); | |
| Back | FazBrowse Home | New Git URL |
0 commit comments