Skip to content

Commit d7cbe16

Browse files
committed
Make pairwise_next safe for free-threading
1 parent cb8e599 commit d7cbe16

File tree

1 file changed

+17
-10
lines changed

1 file changed

+17
-10
lines changed

Modules/itertoolsmodule.c

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -327,37 +327,43 @@ pairwise_traverse(pairwiseobject *po, visitproc visit, void *arg)
327327
static PyObject *
328328
pairwise_next(pairwiseobject *po)
329329
{
330-
PyObject *it = po->it;
331-
PyObject *old = po->old;
332-
PyObject *new, *result;
333-
330+
PyObject *it = Py_XNewRef(po->it);
334331
if (it == NULL) {
335332
return NULL;
336333
}
334+
335+
PyObject *old = Py_XNewRef(po->old);
336+
PyObject *new, *result;
337+
337338
if (old == NULL) {
338339
old = (*Py_TYPE(it)->tp_iternext)(it);
339-
Py_XSETREF(po->old, old);
340340
if (old == NULL) {
341341
Py_CLEAR(po->it);
342+
Py_DECREF(it);
342343
return NULL;
343344
}
344-
it = po->it;
345-
if (it == NULL) {
345+
Py_XSETREF(po->old, Py_NewRef(old));
346+
if (po->it == NULL) {
347+
// for re-entrant calls to pairwise next. the actual behavior is not important and this does not avoid any bugs (or does it?)
348+
// the reason for having it is to make the behaviour equal to the python implementation behavior
346349
Py_CLEAR(po->old);
350+
Py_DECREF(old);
351+
Py_DECREF(it);
347352
return NULL;
348353
}
349354
}
350-
Py_INCREF(old);
355+
351356
new = (*Py_TYPE(it)->tp_iternext)(it);
352357
if (new == NULL) {
353358
Py_CLEAR(po->it);
354359
Py_CLEAR(po->old);
360+
Py_DECREF(it);
355361
Py_DECREF(old);
356362
return NULL;
357363
}
358364

359365
result = po->result;
360-
if (Py_REFCNT(result) == 1) {
366+
if (_PyObject_IsUniquelyReferenced(result)) {
361367
Py_INCREF(result);
362368
PyObject *last_old = PyTuple_GET_ITEM(result, 0);
363369
PyObject *last_new = PyTuple_GET_ITEM(result, 1);
@@ -380,7 +386,8 @@ pairwise_next(pairwiseobject *po)
380386
}
381387

382388
Py_XSETREF(po->old, new);
383-
Py_DECREF(old);
389+
Py_DECREF(old); // instead of the decref here we could borrow the reference above
390+
Py_DECREF(it);
384391
return result;
385392
}
386393

0 commit comments

Comments
 (0)