bpo-30347: Stop crashes when concurrently iterate over itertools.grou… · python/cpython@c740e4f (original) (raw)
`@@ -73,10 +73,37 @@ groupby_traverse(groupbyobject *gbo, visitproc visit, void *arg)
`
73
73
`return 0;
`
74
74
`}
`
75
75
``
``
76
`+
Py_LOCAL_INLINE(int)
`
``
77
`+
groupby_step(groupbyobject *gbo)
`
``
78
`+
{
`
``
79
`+
PyObject *newvalue, *newkey, *oldvalue;
`
``
80
+
``
81
`+
newvalue = PyIter_Next(gbo->it);
`
``
82
`+
if (newvalue == NULL)
`
``
83
`+
return -1;
`
``
84
+
``
85
`+
if (gbo->keyfunc == Py_None) {
`
``
86
`+
newkey = newvalue;
`
``
87
`+
Py_INCREF(newvalue);
`
``
88
`+
} else {
`
``
89
`+
newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL);
`
``
90
`+
if (newkey == NULL) {
`
``
91
`+
Py_DECREF(newvalue);
`
``
92
`+
return -1;
`
``
93
`+
}
`
``
94
`+
}
`
``
95
+
``
96
`+
oldvalue = gbo->currvalue;
`
``
97
`+
gbo->currvalue = newvalue;
`
``
98
`+
Py_XSETREF(gbo->currkey, newkey);
`
``
99
`+
Py_XDECREF(oldvalue);
`
``
100
`+
return 0;
`
``
101
`+
}
`
``
102
+
76
103
`static PyObject *
`
77
104
`groupby_next(groupbyobject *gbo)
`
78
105
`{
`
79
``
`-
PyObject *newvalue, *newkey, *r, *grouper;
`
``
106
`+
PyObject *r, *grouper;
`
80
107
``
81
108
`gbo->currgrouper = NULL;
`
82
109
`/* skip to next iteration group */
`
`@@ -95,25 +122,9 @@ groupby_next(groupbyobject *gbo)
`
95
122
`break;
`
96
123
` }
`
97
124
``
98
``
`-
newvalue = PyIter_Next(gbo->it);
`
99
``
`-
if (newvalue == NULL)
`
``
125
`+
if (groupby_step(gbo) < 0)
`
100
126
`return NULL;
`
101
``
-
102
``
`-
if (gbo->keyfunc == Py_None) {
`
103
``
`-
newkey = newvalue;
`
104
``
`-
Py_INCREF(newvalue);
`
105
``
`-
} else {
`
106
``
`-
newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL);
`
107
``
`-
if (newkey == NULL) {
`
108
``
`-
Py_DECREF(newvalue);
`
109
``
`-
return NULL;
`
110
``
`-
}
`
111
``
`-
}
`
112
``
-
113
``
`-
Py_XSETREF(gbo->currkey, newkey);
`
114
``
`-
Py_XSETREF(gbo->currvalue, newvalue);
`
115
127
` }
`
116
``
-
117
128
`Py_INCREF(gbo->currkey);
`
118
129
`Py_XSETREF(gbo->tgtkey, gbo->currkey);
`
119
130
``
`@@ -285,30 +296,14 @@ static PyObject *
`
285
296
`_grouper_next(_grouperobject *igo)
`
286
297
`{
`
287
298
`groupbyobject *gbo = (groupbyobject *)igo->parent;
`
288
``
`-
PyObject *newvalue, *newkey, *r;
`
``
299
`+
PyObject *r;
`
289
300
`int rcmp;
`
290
301
``
291
302
`if (gbo->currgrouper != igo)
`
292
303
`return NULL;
`
293
304
`if (gbo->currvalue == NULL) {
`
294
``
`-
newvalue = PyIter_Next(gbo->it);
`
295
``
`-
if (newvalue == NULL)
`
``
305
`+
if (groupby_step(gbo) < 0)
`
296
306
`return NULL;
`
297
``
-
298
``
`-
if (gbo->keyfunc == Py_None) {
`
299
``
`-
newkey = newvalue;
`
300
``
`-
Py_INCREF(newvalue);
`
301
``
`-
} else {
`
302
``
`-
newkey = PyObject_CallFunctionObjArgs(gbo->keyfunc, newvalue, NULL);
`
303
``
`-
if (newkey == NULL) {
`
304
``
`-
Py_DECREF(newvalue);
`
305
``
`-
return NULL;
`
306
``
`-
}
`
307
``
`-
}
`
308
``
-
309
``
`-
assert(gbo->currkey == NULL);
`
310
``
`-
gbo->currkey = newkey;
`
311
``
`-
gbo->currvalue = newvalue;
`
312
307
` }
`
313
308
``
314
309
`assert(gbo->currkey != NULL);
`