Skip to content

Commit dd0553f

Browse files
authored
Merge branch 'main' into pprossi-patch-elementtree2
2 parents 9b3d903 + 19c5134 commit dd0553f

20 files changed

+254
-126
lines changed

.github/workflows/reusable-macos.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ jobs:
4242
run: |
4343
brew install pkg-config openssl@3.0 xz gdbm tcl-tk@8 make
4444
# Because alternate versions are not symlinked into place by default:
45-
brew link tcl-tk@8
45+
brew link --overwrite tcl-tk@8
4646
- name: Configure CPython
4747
run: |
4848
GDBM_CFLAGS="-I$(brew --prefix gdbm)/include" \

Doc/library/ssl.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2508,8 +2508,8 @@ thus several things you need to be aware of:
25082508
.. seealso::
25092509

25102510
The :mod:`asyncio` module supports :ref:`non-blocking SSL sockets
2511-
<ssl-nonblocking>` and provides a
2512-
higher level API. It polls for events using the :mod:`selectors` module and
2511+
<ssl-nonblocking>` and provides a higher level :ref:`Streams API <asyncio-streams>`.
2512+
It polls for events using the :mod:`selectors` module and
25132513
handles :exc:`SSLWantWriteError`, :exc:`SSLWantReadError` and
25142514
:exc:`BlockingIOError` exceptions. It runs the SSL handshake asynchronously
25152515
as well.

Include/internal/pycore_critical_section.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ _PyCriticalSection_IsActive(uintptr_t tag)
109109
static inline void
110110
_PyCriticalSection_BeginMutex(PyCriticalSection *c, PyMutex *m)
111111
{
112-
if (PyMutex_LockFast(&m->_bits)) {
112+
if (PyMutex_LockFast(m)) {
113113
PyThreadState *tstate = _PyThreadState_GET();
114114
c->_cs_mutex = m;
115115
c->_cs_prev = tstate->critical_section;
@@ -170,8 +170,8 @@ _PyCriticalSection2_BeginMutex(PyCriticalSection2 *c, PyMutex *m1, PyMutex *m2)
170170
m2 = tmp;
171171
}
172172

173-
if (PyMutex_LockFast(&m1->_bits)) {
174-
if (PyMutex_LockFast(&m2->_bits)) {
173+
if (PyMutex_LockFast(m1)) {
174+
if (PyMutex_LockFast(m2)) {
175175
PyThreadState *tstate = _PyThreadState_GET();
176176
c->_cs_base._cs_mutex = m1;
177177
c->_cs_mutex2 = m2;

Include/internal/pycore_lock.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,10 @@ extern "C" {
1818
#define _Py_ONCE_INITIALIZED 4
1919

2020
static inline int
21-
PyMutex_LockFast(uint8_t *lock_bits)
21+
PyMutex_LockFast(PyMutex *m)
2222
{
2323
uint8_t expected = _Py_UNLOCKED;
24+
uint8_t *lock_bits = &m->_bits;
2425
return _Py_atomic_compare_exchange_uint8(lock_bits, &expected, _Py_LOCKED);
2526
}
2627

Include/internal/pycore_opcode_metadata.h

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Include/internal/pycore_typeobject.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ typedef int (*_py_validate_type)(PyTypeObject *);
278278
// and if the validation is passed, it will set the ``tp_version`` as valid
279279
// tp_version_tag from the ``ty``.
280280
extern int _PyType_Validate(PyTypeObject *ty, _py_validate_type validate, unsigned int *tp_version);
281+
extern int _PyType_CacheGetItemForSpecialization(PyHeapTypeObject *ht, PyObject *descriptor, uint32_t tp_version);
281282

282283
#ifdef __cplusplus
283284
}

Include/internal/pycore_uop_metadata.h

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/test/test_capi/test_unicode.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import unittest
22
import sys
33
from test import support
4-
from test.support import import_helper
4+
from test.support import threading_helper
55

66
try:
77
import _testcapi
@@ -1005,6 +1005,24 @@ def test_asutf8(self):
10051005
self.assertRaises(TypeError, unicode_asutf8, [], 0)
10061006
# CRASHES unicode_asutf8(NULL, 0)
10071007

1008+
@unittest.skipIf(_testcapi is None, 'need _testcapi module')
1009+
@threading_helper.requires_working_threading()
1010+
def test_asutf8_race(self):
1011+
"""Test that there's no race condition in PyUnicode_AsUTF8()"""
1012+
unicode_asutf8 = _testcapi.unicode_asutf8
1013+
from threading import Thread
1014+
1015+
data = "😊"
1016+
1017+
def worker():
1018+
for _ in range(1000):
1019+
self.assertEqual(unicode_asutf8(data, 5), b'\xf0\x9f\x98\x8a\0')
1020+
1021+
threads = [Thread(target=worker) for _ in range(10)]
1022+
with threading_helper.start_threads(threads):
1023+
pass
1024+
1025+
10081026
@support.cpython_only
10091027
@unittest.skipIf(_testlimitedcapi is None, 'need _testlimitedcapi module')
10101028
def test_asutf8andsize(self):

Lib/test/test_opcache.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1069,7 +1069,7 @@ def write(items):
10691069
opname = "STORE_SUBSCR_LIST_INT"
10701070
self.assert_races_do_not_crash(opname, get_items, read, write)
10711071

1072-
@requires_specialization
1072+
@requires_specialization_ft
10731073
def test_unpack_sequence_list(self):
10741074
def get_items():
10751075
items = []
@@ -1245,6 +1245,14 @@ def f(o, n):
12451245
f(test_obj, 1)
12461246
self.assertEqual(test_obj.b, 0)
12471247

1248+
# gh-127274: BINARY_SUBSCR_GETITEM will only cache __getitem__ methods that
1249+
# are deferred. We only defer functions defined at the top-level.
1250+
class CGetItem:
1251+
def __init__(self, val):
1252+
self.val = val
1253+
def __getitem__(self, item):
1254+
return self.val
1255+
12481256

12491257
class TestSpecializer(TestBase):
12501258

@@ -1520,6 +1528,15 @@ def binary_subscr_str_int():
15201528
self.assert_specialized(binary_subscr_str_int, "BINARY_SUBSCR_STR_INT")
15211529
self.assert_no_opcode(binary_subscr_str_int, "BINARY_SUBSCR")
15221530

1531+
def binary_subscr_getitems():
1532+
items = [CGetItem(i) for i in range(100)]
1533+
for i in range(100):
1534+
self.assertEqual(items[i][i], i)
1535+
1536+
binary_subscr_getitems()
1537+
self.assert_specialized(binary_subscr_getitems, "BINARY_SUBSCR_GETITEM")
1538+
self.assert_no_opcode(binary_subscr_getitems, "BINARY_SUBSCR")
1539+
15231540

15241541
if __name__ == "__main__":
15251542
unittest.main()

Modules/_asynciomodule.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3723,6 +3723,11 @@ module_clear(PyObject *mod)
37233723
Py_CLEAR(state->iscoroutine_typecache);
37243724

37253725
Py_CLEAR(state->context_kwname);
3726+
// Clear the ref to running loop so that finalizers can run early.
3727+
// If there are other running loops in different threads,
3728+
// those get cleared in PyThreadState_Clear.
3729+
_PyThreadStateImpl *ts = (_PyThreadStateImpl *)_PyThreadState_GET();
3730+
Py_CLEAR(ts->asyncio_running_loop);
37263731

37273732
return 0;
37283733
}

0 commit comments

Comments
 (0)