]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-142518: add thread safety docs on bytes C-API (#146415)
authorKumar Aditya <kumaraditya@python.org>
Fri, 27 Mar 2026 13:01:18 +0000 (18:31 +0530)
committerGitHub <noreply@github.com>
Fri, 27 Mar 2026 13:01:18 +0000 (18:31 +0530)
Doc/c-api/bytes.rst
Doc/data/threadsafety.dat

index b3cd26a8504715479736bff04876d83e6d72f4fc..d1fde1baf71a4575e2133f05316299cab24e7e9c 100644 (file)
@@ -127,6 +127,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)
 
@@ -185,6 +189,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)
 
@@ -192,6 +199,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)
 
@@ -210,6 +221,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: