https://github.com/python/cpython/commit/d6dda0d23c4a2c7db360235b2198c8f18e0f5596
commit: d6dda0d23c4a2c7db360235b2198c8f18e0f5596
branch: 3.15
author: Miss Islington (bot) <[email protected]>
committer: encukou <[email protected]>
date: 2026-05-20T02:46:42+02:00
summary:

[3.15] gh-150042: queue.SimpleQueue.put: fix minor refleak. (GH-150043) 
(GH-150127)

If queue.SimpleQueue.put can't handoff the item to a
waiting thread, and fails to allocate memory when adding
the item to a ringbuf, it would leak a reference.  Fixed.
(cherry picked from commit 79088e0d82931c21fa72eadc416a18b7b0fdf9c1)

Co-authored-by: larryhastings <[email protected]>

files:
A 
Misc/NEWS.d/next/Core_and_Builtins/2026-05-18-16-54-54.gh-issue-150042.LSr5W8.rst
M Modules/_queuemodule.c

diff --git 
a/Misc/NEWS.d/next/Core_and_Builtins/2026-05-18-16-54-54.gh-issue-150042.LSr5W8.rst
 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-18-16-54-54.gh-issue-150042.LSr5W8.rst
new file mode 100644
index 00000000000000..18a4fbd9dadd60
--- /dev/null
+++ 
b/Misc/NEWS.d/next/Core_and_Builtins/2026-05-18-16-54-54.gh-issue-150042.LSr5W8.rst
@@ -0,0 +1 @@
+Fix refleak in queue.SimpleQueue.put if memory allocation fails.
diff --git a/Modules/_queuemodule.c b/Modules/_queuemodule.c
index ed925f3525a9a7..d5ba36273c8262 100644
--- a/Modules/_queuemodule.c
+++ b/Modules/_queuemodule.c
@@ -154,8 +154,6 @@ RingBuf_Get(RingBuf *buf)
 }
 
 // Returns 0 on success or -1 if the buffer failed to grow.
-//
-// Steals a reference to item.
 static int
 RingBuf_Put(RingBuf *buf, PyObject *item)
 {
@@ -165,11 +163,10 @@ RingBuf_Put(RingBuf *buf, PyObject *item)
         // Buffer is full, grow it.
         if (resize_ringbuf(buf, buf->items_cap * 2) < 0) {
             PyErr_NoMemory();
-            Py_DECREF(item);
             return -1;
         }
     }
-    buf->items[buf->put_idx] = item;
+    buf->items[buf->put_idx] = Py_NewRef(item);
     buf->put_idx = (buf->put_idx + 1) % buf->items_cap;
     buf->num_items++;
     return 0;
@@ -276,16 +273,13 @@ maybe_handoff_item(void *arg, void *park_arg, int 
has_more_waiters)
 {
     HandoffData *data = (HandoffData*)arg;
     PyObject **item = (PyObject**)park_arg;
-    if (item == NULL) {
-        // No threads were waiting
-        data->handed_off = false;
-    }
-    else {
+    data->queue->has_threads_waiting = has_more_waiters;
+
+    data->handed_off = item != NULL;
+    if (data->handed_off) {
         // There was at least one waiting thread, hand off the item
-        *item = data->item;
-        data->handed_off = true;
+        *item = Py_NewRef(data->item);
     }
-    data->queue->has_threads_waiting = has_more_waiters;
 }
 
 /*[clinic input]
@@ -307,21 +301,22 @@ _queue_SimpleQueue_put_impl(simplequeueobject *self, 
PyObject *item,
                             int block, PyObject *timeout)
 /*[clinic end generated code: output=4333136e88f90d8b input=a16dbb33363c0fa8]*/
 {
-    HandoffData data = {
-        .handed_off = 0,
-        .item = Py_NewRef(item),
-        .queue = self,
-    };
     if (self->has_threads_waiting) {
+        HandoffData data = {
+            .handed_off = 0,
+            .item = item,
+            .queue = self,
+        };
         // Try to hand the item off directly if there are threads waiting
         _PyParkingLot_Unpark(&self->has_threads_waiting,
                              maybe_handoff_item, &data);
-    }
-    if (!data.handed_off) {
-        if (RingBuf_Put(&self->buf, item) < 0) {
-            return NULL;
+        if (data.handed_off) {
+            Py_RETURN_NONE;
         }
     }
+    if (RingBuf_Put(&self->buf, item) < 0) {
+        return NULL;
+    }
     Py_RETURN_NONE;
 }
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to