Skip to content

Commit 44db4e0

Browse files
committed
Merge branch 'main' into gh-122697-memory-leaks
2 parents 05db2d8 + 3e753c6 commit 44db4e0

File tree

73 files changed

+987
-396
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

73 files changed

+987
-396
lines changed

.github/workflows/reusable-macos.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,10 @@ jobs:
4848
--prefix=/opt/python-dev \
4949
--with-openssl="$(brew --prefix [email protected])"
5050
- name: Build CPython
51-
run: make -j8
51+
run: set -o pipefail; make -j8 2>&1 | tee compiler_output.txt
5252
- name: Display build info
5353
run: make pythoninfo
54+
- name: Check compiler warnings
55+
run: python3 Tools/build/check_warnings.py --compiler-output-file-path=compiler_output.txt --warning-ignore-file-path=Tools/build/.warningignore_macos --compiler-output-type=clang
5456
- name: Tests
5557
run: make test

.github/workflows/reusable-ubuntu.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ jobs:
8080
working-directory: ${{ env.CPYTHON_BUILDDIR }}
8181
run: make pythoninfo
8282
- name: Check compiler warnings
83-
run: python Tools/build/check_warnings.py --compiler-output-file-path=${{ env.CPYTHON_BUILDDIR }}/compiler_output.txt --warning-ignore-file-path ${GITHUB_WORKSPACE}/Tools/build/.warningignore_ubuntu
83+
run: python Tools/build/check_warnings.py --compiler-output-file-path=${{ env.CPYTHON_BUILDDIR }}/compiler_output.txt --warning-ignore-file-path ${GITHUB_WORKSPACE}/Tools/build/.warningignore_ubuntu --compiler-output-type=json
8484
- name: Remount sources writable for tests
8585
# some tests write to srcdir, lack of pyc files slows down testing
8686
run: sudo mount $CPYTHON_RO_SRCDIR -oremount,rw

Doc/library/pathlib.rst

Lines changed: 28 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1636,7 +1636,7 @@ Copying, renaming and deleting
16361636
.. method:: Path.unlink(missing_ok=False)
16371637

16381638
Remove this file or symbolic link. If the path points to a directory,
1639-
use :func:`Path.rmdir` instead.
1639+
use :func:`Path.rmdir` or :func:`Path.delete` instead.
16401640

16411641
If *missing_ok* is false (the default), :exc:`FileNotFoundError` is
16421642
raised if the path does not exist.
@@ -1650,33 +1650,40 @@ Copying, renaming and deleting
16501650

16511651
.. method:: Path.rmdir()
16521652

1653-
Remove this directory. The directory must be empty.
1653+
Remove this directory. The directory must be empty; use
1654+
:meth:`Path.delete` to remove a non-empty directory.
16541655

16551656

1656-
.. method:: Path.rmtree(ignore_errors=False, on_error=None)
1657+
.. method:: Path.delete(ignore_errors=False, on_error=None)
16571658

1658-
Recursively delete this entire directory tree. The path must not refer to a symlink.
1659+
Delete this file or directory. If this path refers to a non-empty
1660+
directory, its files and sub-directories are deleted recursively.
16591661

1660-
If *ignore_errors* is true, errors resulting from failed removals will be
1661-
ignored. If *ignore_errors* is false or omitted, and a function is given to
1662-
*on_error*, it will be called each time an exception is raised. If neither
1663-
*ignore_errors* nor *on_error* are supplied, exceptions are propagated to
1664-
the caller.
1662+
If *ignore_errors* is true, errors resulting from failed deletions will be
1663+
ignored. If *ignore_errors* is false or omitted, and a callable is given as
1664+
the optional *on_error* argument, it will be called with one argument of
1665+
type :exc:`OSError` each time an exception is raised. The callable can
1666+
handle the error to continue the deletion process or re-raise it to stop.
1667+
Note that the filename is available as the :attr:`~OSError.filename`
1668+
attribute of the exception object. If neither *ignore_errors* nor
1669+
*on_error* are supplied, exceptions are propagated to the caller.
16651670

16661671
.. note::
16671672

1668-
On platforms that support the necessary fd-based functions, a symlink
1669-
attack-resistant version of :meth:`~Path.rmtree` is used by default. On
1670-
other platforms, the :func:`~Path.rmtree` implementation is susceptible
1671-
to a symlink attack: given proper timing and circumstances, attackers
1672-
can manipulate symlinks on the filesystem to delete files they would not
1673-
be able to access otherwise.
1674-
1675-
If the optional argument *on_error* is specified, it should be a callable;
1676-
it will be called with one argument of type :exc:`OSError`. The
1677-
callable can handle the error to continue the deletion process or re-raise
1678-
it to stop. Note that the filename is available as the :attr:`~OSError.filename`
1679-
attribute of the exception object.
1673+
When deleting non-empty directories on platforms that lack the necessary
1674+
file descriptor-based functions, the :meth:`~Path.delete` implementation
1675+
is susceptible to a symlink attack: given proper timing and
1676+
circumstances, attackers can manipulate symlinks on the filesystem to
1677+
delete files they would not be able to access otherwise. Applications
1678+
can use the :data:`~Path.delete.avoids_symlink_attacks` method attribute
1679+
to determine whether the implementation is immune to this attack.
1680+
1681+
.. attribute:: delete.avoids_symlink_attacks
1682+
1683+
Indicates whether the current platform and implementation provides a
1684+
symlink attack resistant version of :meth:`~Path.delete`. Currently
1685+
this is only true for platforms supporting fd-based directory access
1686+
functions.
16801687

16811688
.. versionadded:: 3.14
16821689

Doc/library/site.rst

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,22 @@ It starts by constructing up to four directories from a head and a tail part.
3232
For the head part, it uses ``sys.prefix`` and ``sys.exec_prefix``; empty heads
3333
are skipped. For the tail part, it uses the empty string and then
3434
:file:`lib/site-packages` (on Windows) or
35-
:file:`lib/python{X.Y}/site-packages` (on Unix and macOS). For each
35+
:file:`lib/python{X.Y[t]}/site-packages` (on Unix and macOS). (The
36+
optional suffix "t" indicates the :term:`free threading` build, and is
37+
appended if ``"t"`` is present in the :attr:`sys.abiflags` constant.)
38+
For each
3639
of the distinct head-tail combinations, it sees if it refers to an existing
3740
directory, and if so, adds it to ``sys.path`` and also inspects the newly
3841
added path for configuration files.
3942

4043
.. versionchanged:: 3.5
4144
Support for the "site-python" directory has been removed.
4245

46+
.. versionchanged:: 3.13
47+
On Unix, :term:`Free threading <free threading>` Python installations are
48+
identified by the "t" suffix in the version-specific directory name, such as
49+
:file:`lib/python3.13t/`.
50+
4351
If a file named "pyvenv.cfg" exists one directory above sys.executable,
4452
sys.prefix and sys.exec_prefix are set to that directory and
4553
it is also checked for site-packages (sys.base_prefix and
@@ -188,11 +196,12 @@ Module contents
188196

189197
Path to the user site-packages for the running Python. Can be ``None`` if
190198
:func:`getusersitepackages` hasn't been called yet. Default value is
191-
:file:`~/.local/lib/python{X.Y}/site-packages` for UNIX and non-framework
199+
:file:`~/.local/lib/python{X.Y}[t]/site-packages` for UNIX and non-framework
192200
macOS builds, :file:`~/Library/Python/{X.Y}/lib/python/site-packages` for macOS
193201
framework builds, and :file:`{%APPDATA%}\\Python\\Python{XY}\\site-packages`
194-
on Windows. This directory is a site directory, which means that
195-
:file:`.pth` files in it will be processed.
202+
on Windows. The optional "t" indicates the free-threaded build. This
203+
directory is a site directory, which means that :file:`.pth` files in it
204+
will be processed.
196205

197206

198207
.. data:: USER_BASE

Doc/library/stdtypes.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,8 +1245,9 @@ accepts integers that meet the value restriction ``0 <= x <= 255``).
12451245
| ``s.pop()`` or ``s.pop(i)`` | retrieves the item at *i* and | \(2) |
12461246
| | also removes it from *s* | |
12471247
+------------------------------+--------------------------------+---------------------+
1248-
| ``s.remove(x)`` | remove the first item from *s* | \(3) |
1249-
| | where ``s[i]`` is equal to *x* | |
1248+
| ``s.remove(x)`` | removes the first item from | \(3) |
1249+
| | *s* where ``s[i]`` is equal to | |
1250+
| | *x* | |
12501251
+------------------------------+--------------------------------+---------------------+
12511252
| ``s.reverse()`` | reverses the items of *s* in | \(4) |
12521253
| | place | |

Doc/reference/datamodel.rst

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -106,12 +106,16 @@ that mutable object is changed.
106106
Types affect almost all aspects of object behavior. Even the importance of
107107
object identity is affected in some sense: for immutable types, operations that
108108
compute new values may actually return a reference to any existing object with
109-
the same type and value, while for mutable objects this is not allowed. E.g.,
110-
after ``a = 1; b = 1``, ``a`` and ``b`` may or may not refer to the same object
111-
with the value one, depending on the implementation, but after ``c = []; d =
112-
[]``, ``c`` and ``d`` are guaranteed to refer to two different, unique, newly
113-
created empty lists. (Note that ``c = d = []`` assigns the same object to both
114-
``c`` and ``d``.)
109+
the same type and value, while for mutable objects this is not allowed.
110+
For example, after ``a = 1; b = 1``, *a* and *b* may or may not refer to
111+
the same object with the value one, depending on the implementation.
112+
This is because :class:`int` is an immutable type, so the reference to ``1``
113+
can be reused. This behaviour depends on the implementation used, so should
114+
not be relied upon, but is something to be aware of when making use of object
115+
identity tests.
116+
However, after ``c = []; d = []``, *c* and *d* are guaranteed to refer to two
117+
different, unique, newly created empty lists. (Note that ``e = f = []`` assigns
118+
the *same* object to both *e* and *f*.)
115119

116120

117121
.. _types:

Doc/using/cmdline.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ Command line
2424

2525
When invoking Python, you may specify any of these options::
2626

27-
python [-bBdEhiIOqsSuvVWx?] [-c command | -m module-name | script | - ] [args]
27+
python [-bBdEhiIOPqRsSuvVWx?] [-c command | -m module-name | script | - ] [args]
2828

2929
The most common use case is, of course, a simple invocation of a script::
3030

Doc/whatsnew/3.14.rst

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,8 +141,7 @@ pathlib
141141
:func:`shutil.copyfile`.
142142
* :meth:`~pathlib.Path.copytree` copies one directory tree to another, like
143143
:func:`shutil.copytree`.
144-
* :meth:`~pathlib.Path.rmtree` recursively removes a directory tree, like
145-
:func:`shutil.rmtree`.
144+
* :meth:`~pathlib.Path.delete` removes a file or directory tree.
146145

147146
(Contributed by Barney Gale in :gh:`73991`.)
148147

Include/cpython/object.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,9 @@ typedef struct _heaptypeobject {
270270
PyObject *ht_module;
271271
char *_ht_tpname; // Storage for "tp_name"; see PyType_FromModuleAndSpec
272272
struct _specialization_cache _spec_cache; // For use by the specializer.
273+
#ifdef Py_GIL_DISABLED
274+
Py_ssize_t unique_id; // ID used for thread-local refcounting
275+
#endif
273276
/* here are optional user slots, followed by the members. */
274277
} PyHeapTypeObject;
275278

Include/internal/pycore_gc.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -381,10 +381,6 @@ extern void _PyGC_ClearAllFreeLists(PyInterpreterState *interp);
381381
extern void _Py_ScheduleGC(PyThreadState *tstate);
382382
extern void _Py_RunGC(PyThreadState *tstate);
383383

384-
#ifdef Py_GIL_DISABLED
385-
// gh-117783: Immortalize objects that use deferred reference counting
386-
extern void _PyGC_ImmortalizeDeferredObjects(PyInterpreterState *interp);
387-
#endif
388384

389385
#ifdef __cplusplus
390386
}

Include/internal/pycore_interp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ extern "C" {
3535
#include "pycore_qsbr.h" // struct _qsbr_state
3636
#include "pycore_tstate.h" // _PyThreadStateImpl
3737
#include "pycore_tuple.h" // struct _Py_tuple_state
38+
#include "pycore_typeid.h" // struct _Py_type_id_pool
3839
#include "pycore_typeobject.h" // struct types_state
3940
#include "pycore_unicodeobject.h" // struct _Py_unicode_state
4041
#include "pycore_warnings.h" // struct _warnings_runtime_state
@@ -220,6 +221,7 @@ struct _is {
220221
#if defined(Py_GIL_DISABLED)
221222
struct _mimalloc_interp_state mimalloc;
222223
struct _brc_state brc; // biased reference counting state
224+
struct _Py_type_id_pool type_ids;
223225
PyMutex weakref_locks[NUM_WEAKREF_LIST_LOCKS];
224226
#endif
225227

Include/internal/pycore_object.h

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,19 @@ extern "C" {
1414
#include "pycore_interp.h" // PyInterpreterState.gc
1515
#include "pycore_pyatomic_ft_wrappers.h" // FT_ATOMIC_STORE_PTR_RELAXED
1616
#include "pycore_pystate.h" // _PyInterpreterState_GET()
17+
#include "pycore_typeid.h" // _PyType_IncrefSlow
1718

1819

1920
#define _Py_IMMORTAL_REFCNT_LOOSE ((_Py_IMMORTAL_REFCNT >> 1) + 1)
2021

22+
// This value is added to `ob_ref_shared` for objects that use deferred
23+
// reference counting so that they are not immediately deallocated when the
24+
// non-deferred reference count drops to zero.
25+
//
26+
// The value is half the maximum shared refcount because the low two bits of
27+
// `ob_ref_shared` are used for flags.
28+
#define _Py_REF_DEFERRED (PY_SSIZE_T_MAX / 8)
29+
2130
// gh-121528, gh-118997: Similar to _Py_IsImmortal() but be more loose when
2231
// comparing the reference count to stay compatible with C extensions built
2332
// with the stable ABI 3.11 or older. Such extensions implement INCREF/DECREF
@@ -280,6 +289,67 @@ extern PyStatus _PyObject_InitState(PyInterpreterState *interp);
280289
extern void _PyObject_FiniState(PyInterpreterState *interp);
281290
extern bool _PyRefchain_IsTraced(PyInterpreterState *interp, PyObject *obj);
282291

292+
#ifndef Py_GIL_DISABLED
293+
# define _Py_INCREF_TYPE Py_INCREF
294+
# define _Py_DECREF_TYPE Py_DECREF
295+
#else
296+
static inline void
297+
_Py_INCREF_TYPE(PyTypeObject *type)
298+
{
299+
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
300+
assert(_Py_IsImmortal(type));
301+
return;
302+
}
303+
304+
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
305+
PyHeapTypeObject *ht = (PyHeapTypeObject *)type;
306+
307+
// Unsigned comparison so that `unique_id=-1`, which indicates that
308+
// per-thread refcounting has been disabled on this type, is handled by
309+
// the "else".
310+
if ((size_t)ht->unique_id < (size_t)tstate->types.size) {
311+
# ifdef Py_REF_DEBUG
312+
_Py_INCREF_IncRefTotal();
313+
# endif
314+
_Py_INCREF_STAT_INC();
315+
tstate->types.refcounts[ht->unique_id]++;
316+
}
317+
else {
318+
// The slow path resizes the thread-local refcount array if necessary.
319+
// It handles the unique_id=-1 case to keep the inlinable function smaller.
320+
_PyType_IncrefSlow(ht);
321+
}
322+
}
323+
324+
static inline void
325+
_Py_DECREF_TYPE(PyTypeObject *type)
326+
{
327+
if (!_PyType_HasFeature(type, Py_TPFLAGS_HEAPTYPE)) {
328+
assert(_Py_IsImmortal(type));
329+
return;
330+
}
331+
332+
_PyThreadStateImpl *tstate = (_PyThreadStateImpl *)_PyThreadState_GET();
333+
PyHeapTypeObject *ht = (PyHeapTypeObject *)type;
334+
335+
// Unsigned comparison so that `unique_id=-1`, which indicates that
336+
// per-thread refcounting has been disabled on this type, is handled by
337+
// the "else".
338+
if ((size_t)ht->unique_id < (size_t)tstate->types.size) {
339+
# ifdef Py_REF_DEBUG
340+
_Py_DECREF_DecRefTotal();
341+
# endif
342+
_Py_DECREF_STAT_INC();
343+
tstate->types.refcounts[ht->unique_id]--;
344+
}
345+
else {
346+
// Directly decref the type if the type id is not assigned or if
347+
// per-thread refcounting has been disabled on this type.
348+
Py_DECREF(type);
349+
}
350+
}
351+
#endif
352+
283353
/* Inline functions trading binary compatibility for speed:
284354
_PyObject_Init() is the fast version of PyObject_Init(), and
285355
_PyObject_InitVar() is the fast version of PyObject_InitVar().
@@ -291,7 +361,7 @@ _PyObject_Init(PyObject *op, PyTypeObject *typeobj)
291361
assert(op != NULL);
292362
Py_SET_TYPE(op, typeobj);
293363
assert(_PyType_HasFeature(typeobj, Py_TPFLAGS_HEAPTYPE) || _Py_IsImmortalLoose(typeobj));
294-
Py_INCREF(typeobj);
364+
_Py_INCREF_TYPE(typeobj);
295365
_Py_NewReference(op);
296366
}
297367

Include/internal/pycore_tstate.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,16 @@ typedef struct _PyThreadStateImpl {
3131
struct _mimalloc_thread_state mimalloc;
3232
struct _Py_freelists freelists;
3333
struct _brc_thread_state brc;
34+
struct {
35+
// The thread-local refcounts for heap type objects
36+
Py_ssize_t *refcounts;
37+
38+
// Size of the refcounts array.
39+
Py_ssize_t size;
40+
41+
// If set, don't use thread-local refcounts
42+
int is_finalized;
43+
} types;
3444
#endif
3545

3646
#if defined(Py_REF_DEBUG) && defined(Py_GIL_DISABLED)

0 commit comments

Comments
 (0)