Skip to content

Commit 8700667

Browse files
authored
Merge branch 'main' into pythongh-93554
2 parents eb82d24 + ffa24aa commit 8700667

13 files changed

Lines changed: 167 additions & 96 deletions

File tree

‎Doc/library/base64.rst‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ The modern interface provides:
193193

194194
*wrapcol* controls whether the output should have newline (``b'\n'``)
195195
characters added to it. If this is non-zero, each output line will be
196-
at most this many characters long.
196+
at most this many characters long, excluding the trailing newline.
197197

198198
*pad* controls whether the input is padded to a multiple of 4
199199
before encoding. Note that the ``btoa`` implementation always pads.

‎Include/cpython/pystate.h‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,14 +83,16 @@ struct _ts {
8383
unsigned int bound_gilstate:1;
8484
/* Currently in use (maybe holds the GIL). */
8585
unsigned int active:1;
86+
/* Currently holds the GIL. */
87+
unsigned int holds_gil:1;
8688

8789
/* various stages of finalization */
8890
unsigned int finalizing:1;
8991
unsigned int cleared:1;
9092
unsigned int finalized:1;
9193

9294
/* padding to align to 4 bytes */
93-
unsigned int :24;
95+
unsigned int :23;
9496
} _status;
9597
#ifdef Py_BUILD_CORE
9698
# define _PyThreadState_WHENCE_NOTSET -1

‎Include/internal/pycore_ceval.h‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -131,11 +131,10 @@ extern int _PyEval_ThreadsInitialized(void);
131131
extern void _PyEval_InitGIL(PyThreadState *tstate, int own_gil);
132132
extern void _PyEval_FiniGIL(PyInterpreterState *interp);
133133

134-
// Acquire the GIL and return 1. In free-threaded builds, this function may
135-
// return 0 to indicate that the GIL was disabled and therefore not acquired.
136-
extern int _PyEval_AcquireLock(PyThreadState *tstate);
134+
extern void _PyEval_AcquireLock(PyThreadState *tstate);
137135

138-
extern void _PyEval_ReleaseLock(PyInterpreterState *, PyThreadState *);
136+
extern void _PyEval_ReleaseLock(PyInterpreterState *, PyThreadState *,
137+
int final_release);
139138

140139
#ifdef Py_GIL_DISABLED
141140
// Returns 0 or 1 if the GIL for the given thread's interpreter is disabled or

‎Lib/base64.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,7 @@ def a85encode(b, *, foldspaces=False, wrapcol=0, pad=False, adobe=False):
332332
333333
wrapcol controls whether the output should have newline (b'\\n') characters
334334
added to it. If this is non-zero, each output line will be at most this
335-
many characters long.
335+
many characters long, excluding the trailing newline.
336336
337337
pad controls whether the input is padded to a multiple of 4 before
338338
encoding. Note that the btoa implementation always pads.

‎Lib/test/test_importlib/test_threaded_import.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from test.support import verbose
1818
from test.support.import_helper import forget, mock_register_at_fork
1919
from test.support.os_helper import (TESTFN, unlink, rmtree)
20-
from test.support import script_helper, threading_helper, requires_gil_enabled
20+
from test.support import script_helper, threading_helper
2121

2222
threading_helper.requires_working_threading(module=True)
2323

@@ -248,9 +248,6 @@ def test_concurrent_futures_circular_import(self):
248248
'partial', 'cfimport.py')
249249
script_helper.assert_python_ok(fn)
250250

251-
# gh-118727 and gh-118729: pool_in_threads.py may crash in free-threaded
252-
# builds, which can hang the Tsan test so temporarily skip it for now.
253-
@requires_gil_enabled("gh-118727: test may crash in free-threaded builds")
254251
def test_multiprocessing_pool_circular_import(self):
255252
# Regression test for bpo-41567
256253
fn = os.path.join(os.path.dirname(__file__),

‎Lib/test/test_socket.py‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ def _have_socket_qipcrtr():
160160

161161
def _have_socket_vsock():
162162
"""Check whether AF_VSOCK sockets are supported on this host."""
163-
ret = get_cid() is not None
164-
return ret
163+
cid = get_cid()
164+
return (cid is not None)
165165

166166

167167
def _have_socket_bluetooth():
@@ -520,8 +520,6 @@ def clientTearDown(self):
520520
@unittest.skipIf(WSL, 'VSOCK does not work on Microsoft WSL')
521521
@unittest.skipUnless(HAVE_SOCKET_VSOCK,
522522
'VSOCK sockets required for this test.')
523-
@unittest.skipUnless(get_cid() != 2,
524-
"This test can only be run on a virtual guest.")
525523
class ThreadedVSOCKSocketStreamTest(unittest.TestCase, ThreadableTest):
526524

527525
def __init__(self, methodName='runTest'):
@@ -543,6 +541,9 @@ def clientSetUp(self):
543541
self.cli = socket.socket(socket.AF_VSOCK, socket.SOCK_STREAM)
544542
self.addCleanup(self.cli.close)
545543
cid = get_cid()
544+
if cid in (socket.VMADDR_CID_HOST, socket.VMADDR_CID_ANY):
545+
# gh-119461: Use the local communication address (loopback)
546+
cid = socket.VMADDR_CID_LOCAL
546547
self.cli.connect((cid, VSOCKPORT))
547548

548549
def testStream(self):
@@ -2515,6 +2516,7 @@ def testVSOCKConstants(self):
25152516
socket.SO_VM_SOCKETS_BUFFER_MAX_SIZE
25162517
socket.VMADDR_CID_ANY
25172518
socket.VMADDR_PORT_ANY
2519+
socket.VMADDR_CID_LOCAL
25182520
socket.VMADDR_CID_HOST
25192521
socket.VM_SOCKETS_INVALID_VERSION
25202522
socket.IOCTL_VM_SOCKETS_GET_LOCAL_CID
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Objects in the datetime C-API are now all statically allocated, which means
2+
better memory safety, especially when the module is reloaded. This should be
3+
transparent to users.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Add ``socket.VMADDR_CID_LOCAL`` constant. Patch by Victor Stinner.

‎Modules/_datetimemodule.c‎

Lines changed: 83 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,6 +1178,8 @@ new_time_subclass_fold_ex(int hour, int minute, int second, int usecond,
11781178
return t;
11791179
}
11801180

1181+
static PyDateTime_Delta * look_up_delta(int, int, int, PyTypeObject *);
1182+
11811183
/* Create a timedelta instance. Normalize the members iff normalize is
11821184
* true. Passing false is a speed optimization, if you know for sure
11831185
* that seconds and microseconds are already in their proper ranges. In any
@@ -1198,6 +1200,12 @@ new_delta_ex(int days, int seconds, int microseconds, int normalize,
11981200
if (check_delta_day_range(days) < 0)
11991201
return NULL;
12001202

1203+
self = look_up_delta(days, seconds, microseconds, type);
1204+
if (self != NULL) {
1205+
return (PyObject *)self;
1206+
}
1207+
assert(!PyErr_Occurred());
1208+
12011209
self = (PyDateTime_Delta *) (type->tp_alloc(type, 0));
12021210
if (self != NULL) {
12031211
self->hashcode = -1;
@@ -1219,6 +1227,8 @@ typedef struct
12191227
PyObject *name;
12201228
} PyDateTime_TimeZone;
12211229

1230+
static PyDateTime_TimeZone * look_up_timezone(PyObject *offset, PyObject *name);
1231+
12221232
/* Create new timezone instance checking offset range. This
12231233
function does not check the name argument. Caller must assure
12241234
that offset is a timedelta instance and name is either NULL
@@ -1234,6 +1244,12 @@ create_timezone(PyObject *offset, PyObject *name)
12341244
assert(PyDelta_Check(offset));
12351245
assert(name == NULL || PyUnicode_Check(name));
12361246

1247+
self = look_up_timezone(offset, name);
1248+
if (self != NULL) {
1249+
return (PyObject *)self;
1250+
}
1251+
assert(!PyErr_Occurred());
1252+
12371253
self = (PyDateTime_TimeZone *)(type->tp_alloc(type, 0));
12381254
if (self == NULL) {
12391255
return NULL;
@@ -2892,6 +2908,25 @@ static PyTypeObject PyDateTime_DeltaType = {
28922908
0, /* tp_free */
28932909
};
28942910

2911+
// XXX Can we make this const?
2912+
static PyDateTime_Delta zero_delta = {
2913+
PyObject_HEAD_INIT(&PyDateTime_DeltaType)
2914+
/* Letting this be set lazily is a benign race. */
2915+
.hashcode = -1,
2916+
};
2917+
2918+
static PyDateTime_Delta *
2919+
look_up_delta(int days, int seconds, int microseconds, PyTypeObject *type)
2920+
{
2921+
if (days == 0 && seconds == 0 && microseconds == 0
2922+
&& type == zero_delta.ob_base.ob_type)
2923+
{
2924+
return &zero_delta;
2925+
}
2926+
return NULL;
2927+
}
2928+
2929+
28952930
/*
28962931
* PyDateTime_Date implementation.
28972932
*/
@@ -4184,6 +4219,23 @@ static PyTypeObject PyDateTime_TimeZoneType = {
41844219
timezone_new, /* tp_new */
41854220
};
41864221

4222+
// XXX Can we make this const?
4223+
static PyDateTime_TimeZone utc_timezone = {
4224+
PyObject_HEAD_INIT(&PyDateTime_TimeZoneType)
4225+
.offset = (PyObject *)&zero_delta,
4226+
.name = NULL,
4227+
};
4228+
4229+
static PyDateTime_TimeZone *
4230+
look_up_timezone(PyObject *offset, PyObject *name)
4231+
{
4232+
if (offset == utc_timezone.offset && name == NULL) {
4233+
return &utc_timezone;
4234+
}
4235+
return NULL;
4236+
}
4237+
4238+
41874239
/*
41884240
* PyDateTime_Time implementation.
41894241
*/
@@ -6719,45 +6771,42 @@ static PyMethodDef module_methods[] = {
67196771
{NULL, NULL}
67206772
};
67216773

6774+
6775+
/* The C-API is process-global. This violates interpreter isolation
6776+
* due to the objects stored here. Thus each of those objects must
6777+
* be managed carefully. */
6778+
// XXX Can we make this const?
6779+
static PyDateTime_CAPI capi = {
6780+
/* The classes must be readied before used here.
6781+
* That will happen the first time the module is loaded.
6782+
* They aren't safe to be shared between interpreters,
6783+
* but that's okay as long as the module is single-phase init. */
6784+
.DateType = &PyDateTime_DateType,
6785+
.DateTimeType = &PyDateTime_DateTimeType,
6786+
.TimeType = &PyDateTime_TimeType,
6787+
.DeltaType = &PyDateTime_DeltaType,
6788+
.TZInfoType = &PyDateTime_TZInfoType,
6789+
6790+
.TimeZone_UTC = (PyObject *)&utc_timezone,
6791+
6792+
.Date_FromDate = new_date_ex,
6793+
.DateTime_FromDateAndTime = new_datetime_ex,
6794+
.Time_FromTime = new_time_ex,
6795+
.Delta_FromDelta = new_delta_ex,
6796+
.TimeZone_FromTimeZone = new_timezone,
6797+
.DateTime_FromTimestamp = datetime_fromtimestamp,
6798+
.Date_FromTimestamp = datetime_date_fromtimestamp_capi,
6799+
.DateTime_FromDateAndTimeAndFold = new_datetime_ex2,
6800+
.Time_FromTimeAndFold = new_time_ex2,
6801+
};
6802+
67226803
/* Get a new C API by calling this function.
67236804
* Clients get at C API via PyDateTime_IMPORT, defined in datetime.h.
67246805
*/
67256806
static inline PyDateTime_CAPI *
67266807
get_datetime_capi(void)
67276808
{
6728-
datetime_state *st = get_datetime_state();
6729-
6730-
PyDateTime_CAPI *capi = PyMem_Malloc(sizeof(PyDateTime_CAPI));
6731-
if (capi == NULL) {
6732-
PyErr_NoMemory();
6733-
return NULL;
6734-
}
6735-
capi->DateType = st->date_type;
6736-
capi->DateTimeType = st->datetime_type;
6737-
capi->TimeType = st->time_type;
6738-
capi->DeltaType = st->delta_type;
6739-
capi->TZInfoType = st->tzinfo_type;
6740-
capi->Date_FromDate = new_date_ex;
6741-
capi->DateTime_FromDateAndTime = new_datetime_ex;
6742-
capi->Time_FromTime = new_time_ex;
6743-
capi->Delta_FromDelta = new_delta_ex;
6744-
capi->TimeZone_FromTimeZone = new_timezone;
6745-
capi->DateTime_FromTimestamp = datetime_fromtimestamp;
6746-
capi->Date_FromTimestamp = datetime_date_fromtimestamp_capi;
6747-
capi->DateTime_FromDateAndTimeAndFold = new_datetime_ex2;
6748-
capi->Time_FromTimeAndFold = new_time_ex2;
6749-
// Make sure this function is called after utc has
6750-
// been initialized.
6751-
assert(st->utc != NULL);
6752-
capi->TimeZone_UTC = st->utc; // borrowed ref
6753-
return capi;
6754-
}
6755-
6756-
static void
6757-
datetime_destructor(PyObject *op)
6758-
{
6759-
void *ptr = PyCapsule_GetPointer(op, PyDateTime_CAPSULE_NAME);
6760-
PyMem_Free(ptr);
6809+
return &capi;
67616810
}
67626811

67636812
static int
@@ -6955,8 +7004,7 @@ _datetime_exec(PyObject *module)
69557004
if (capi == NULL) {
69567005
goto error;
69577006
}
6958-
PyObject *capsule = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME,
6959-
datetime_destructor);
7007+
PyObject *capsule = PyCapsule_New(capi, PyDateTime_CAPSULE_NAME, NULL);
69607008
if (capsule == NULL) {
69617009
PyMem_Free(capi);
69627010
goto error;

‎Modules/socketmodule.c‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7596,6 +7596,7 @@ socket_exec(PyObject *m)
75967596
ADD_INT_CONST(m, "SO_VM_SOCKETS_BUFFER_MAX_SIZE", 2);
75977597
ADD_INT_CONST(m, "VMADDR_CID_ANY", 0xffffffff);
75987598
ADD_INT_CONST(m, "VMADDR_PORT_ANY", 0xffffffff);
7599+
ADD_INT_CONST(m, "VMADDR_CID_LOCAL", 1);
75997600
ADD_INT_CONST(m, "VMADDR_CID_HOST", 2);
76007601
ADD_INT_CONST(m, "VM_SOCKETS_INVALID_VERSION", 0xffffffff);
76017602
ADD_INT_CONST(m, "IOCTL_VM_SOCKETS_GET_LOCAL_CID", _IO(7, 0xb9));

0 commit comments

Comments
 (0)