]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-142518: add thread safety docs on bytes C-API (GH-146415) (#146515)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Fri, 27 Mar 2026 13:07:37 +0000 (14:07 +0100)
committerGitHub <noreply@github.com>
Fri, 27 Mar 2026 13:07:37 +0000 (13:07 +0000)
gh-142518: add thread safety docs on bytes C-API (GH-146415)
(cherry picked from commit 6a94980301b880b7ac1178efd31d14f031f690f5)

Co-authored-by: Kumar Aditya <kumaraditya@python.org>
Doc/c-api/bytes.rst
Doc/data/threadsafety.dat

index 7d8a511e100cf4150e54ac1e517890ec509c2a73..3a34b5329eb7ef4c74aa6b9050924d7a94f0f92b 100644 (file)
@@ -123,6 +123,10 @@ called with a non-bytes parameter.
    Return the bytes representation of object *o* that implements the buffer
    protocol.
 
+   .. note::
+      If the object implements the buffer protocol, then the buffer
+      must not be mutated while the bytes object is being created.
+
 
 .. c:function:: Py_ssize_t PyBytes_Size(PyObject *o)
 
@@ -181,6 +185,9 @@ called with a non-bytes parameter.
    created, the old reference to *bytes* will still be discarded and the value
    of *\*bytes* will be set to ``NULL``; the appropriate exception will be set.
 
+   .. note::
+      If *newpart* implements the buffer protocol, then the buffer
+      must not be mutated while the new bytes object is being created.
 
 .. c:function:: void PyBytes_ConcatAndDel(PyObject **bytes, PyObject *newpart)
 
@@ -188,6 +195,10 @@ called with a non-bytes parameter.
    appended to *bytes*.  This version releases the :term:`strong reference`
    to *newpart* (i.e. decrements its reference count).
 
+   .. note::
+      If *newpart* implements the buffer protocol, then the buffer
+      must not be mutated while the new bytes object is being created.
+
 
 .. c:function:: PyObject* PyBytes_Join(PyObject *sep, PyObject *iterable)
 
@@ -206,6 +217,9 @@ called with a non-bytes parameter.
 
    .. versionadded:: 3.14
 
+   .. note::
+      If *iterable* objects implement the buffer protocol, then the buffers
+      must not be mutated while the new bytes object is being created.
 
 .. c:function:: int _PyBytes_Resize(PyObject **bytes, Py_ssize_t newsize)
 
index 103e8ef3e97ed10534a0f44b7f1bbb9a877cf409..1210ab17aaa35b8482481b47acac762179f577be 100644 (file)
@@ -66,10 +66,44 @@ PyList_Reverse:shared:
 # is a list
 PyList_SetSlice:shared:
 
-# Sort - per-object lock held; comparison callbacks may execute
-# arbitrary Python code
+# Sort - per-object lock held; the list is emptied before sorting
+# so other threads may observe an empty list, but they won't see the
+# intermediate states of the sort
 PyList_Sort:shared:
 
 # Extend - lock target list; also lock source when it is a
 # list, set, or dict
 PyList_Extend:shared:
+
+# Creation - pure allocation, no shared state
+PyBytes_FromString:atomic:
+PyBytes_FromStringAndSize:atomic:
+PyBytes_DecodeEscape:atomic:
+
+# Creation from formatting C primitives - pure allocation, no shared state
+PyBytes_FromFormat:atomic:
+PyBytes_FromFormatV:atomic:
+
+# Creation from object - uses buffer protocol so may call arbitrary code;
+# safe as long as the buffer is not mutated by another thread during the operation
+PyBytes_FromObject:shared:
+
+# Size - uses atomic load on free-threaded builds
+PyBytes_Size:atomic:
+PyBytes_GET_SIZE:atomic:
+
+# Raw data - no locking; mutating it is unsafe if the bytes object is shared between threads
+PyBytes_AsString:compatible:
+PyBytes_AS_STRING:compatible:
+PyBytes_AsStringAndSize:compatible:
+
+# Concatenation - uses buffer protocol; safe as long as buffer is not mutated by another thread during the operation
+PyBytes_Concat:shared:
+PyBytes_ConcatAndDel:shared:
+PyBytes_Join:shared:
+
+# Resizing - safe if the object is unique
+_PyBytes_Resize:distinct:
+
+# Repr - atomic as bytes are immutable
+PyBytes_Repr:atomic: