@@ -553,14 +553,31 @@ kill_wrap_bad_guy(PyTaskletObject *prev, PyTaskletObject *bad_guy)
553
553
PyObject *
554
554
slp_restore_exception (PyFrameObject * f , int exc , PyObject * retval )
555
555
{
556
+ PyObject * tmp_type , * tmp_value , * tmp_tb ;
556
557
PyThreadState * ts = PyThreadState_GET ();
557
558
PyCFrameObject * cf = (PyCFrameObject * ) f ;
558
559
560
+ if (cf -> ob1 == NULL ) {
561
+ /* set_exc_info in ceval.c contains the same assertions */
562
+ assert (cf -> ob2 == NULL );
563
+ assert (cf -> ob3 == NULL );
564
+ }
565
+
559
566
f = cf -> f_back ;
567
+ /* Set new exception for this thread.
568
+ * This code is follows suit the code of set_exc_info() in ceval.c */
569
+ tmp_type = ts -> exc_type ;
570
+ tmp_value = ts -> exc_value ;
571
+ tmp_tb = ts -> exc_traceback ;
560
572
ts -> exc_type = cf -> ob1 ;
561
573
ts -> exc_value = cf -> ob2 ;
562
574
ts -> exc_traceback = cf -> ob3 ;
563
575
cf -> ob1 = cf -> ob2 = cf -> ob3 = NULL ;
576
+
577
+ Py_XDECREF (tmp_type );
578
+ Py_XDECREF (tmp_value );
579
+ Py_XDECREF (tmp_tb );
580
+
564
581
Py_DECREF (cf );
565
582
ts -> frame = f ;
566
583
return STACKLESS_PACK (ts , retval );
@@ -1071,17 +1088,32 @@ slp_schedule_task_prepared(PyThreadState *ts, PyObject **result, PyTaskletObject
1071
1088
}
1072
1089
if (ts -> exc_type != NULL ) {
1073
1090
/* build a shadow frame if we are returning here*/
1091
+ /* The following code follows suit the code of sys.exc_clear() and
1092
+ * ceval.c set_exc_info()
1093
+ */
1074
1094
if (ts -> frame != NULL ) {
1075
1095
PyCFrameObject * f = slp_cframe_new (slp_restore_exception , 1 );
1076
1096
if (f == NULL )
1077
1097
return -1 ;
1078
1098
f -> ob1 = ts -> exc_type ;
1079
1099
f -> ob2 = ts -> exc_value ;
1080
1100
f -> ob3 = ts -> exc_traceback ;
1101
+ ts -> exc_type = NULL ;
1102
+ ts -> exc_value = NULL ;
1103
+ ts -> exc_traceback = NULL ;
1081
1104
prev -> f .frame = (PyFrameObject * ) f ;
1105
+ } else {
1106
+ PyObject * tmp_type , * tmp_value , * tmp_tb ;
1107
+ tmp_type = ts -> exc_type ;
1108
+ tmp_value = ts -> exc_value ;
1109
+ tmp_tb = ts -> exc_traceback ;
1110
+ ts -> exc_type = NULL ;
1111
+ ts -> exc_value = NULL ;
1112
+ ts -> exc_traceback = NULL ;
1113
+ Py_XDECREF (tmp_type );
1114
+ Py_XDECREF (tmp_value );
1115
+ Py_XDECREF (tmp_tb );
1082
1116
}
1083
- ts -> exc_type = ts -> exc_value =
1084
- ts -> exc_traceback = NULL ;
1085
1117
}
1086
1118
if (ts -> use_tracing || ts -> tracing ) {
1087
1119
/* build a shadow frame if we are returning here */
@@ -1425,12 +1457,19 @@ slp_tasklet_end(PyObject *retval)
1425
1457
* clean up any current exception - this tasklet is dead.
1426
1458
* This only happens if we are killing tasklets in the middle
1427
1459
* of their execution.
1460
+ * The code follows suit the code of sys.exc_clear().
1428
1461
*/
1429
1462
if (ts -> exc_type != NULL && ts -> exc_type != Py_None ) {
1430
- Py_DECREF (ts -> exc_type );
1431
- Py_XDECREF (ts -> exc_value );
1432
- Py_XDECREF (ts -> exc_traceback );
1433
- ts -> exc_type = ts -> exc_value = ts -> exc_traceback = NULL ;
1463
+ PyObject * tmp_type , * tmp_value , * tmp_tb ;
1464
+ tmp_type = ts -> exc_type ;
1465
+ tmp_value = ts -> exc_value ;
1466
+ tmp_tb = ts -> exc_traceback ;
1467
+ ts -> exc_type = NULL ;
1468
+ ts -> exc_value = NULL ;
1469
+ ts -> exc_traceback = NULL ;
1470
+ Py_DECREF (tmp_type );
1471
+ Py_XDECREF (tmp_value );
1472
+ Py_XDECREF (tmp_tb );
1434
1473
}
1435
1474
1436
1475
/* capture all exceptions */
0 commit comments