Skip to content

Commit 0dba59e

Browse files
gh-128182: add critical sections to ctypes arrays getters and setters (#132152)
1 parent 0a10b45 commit 0dba59e

File tree

2 files changed

+165
-28
lines changed

2 files changed

+165
-28
lines changed

Modules/_ctypes/_ctypes.c

Lines changed: 64 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1425,14 +1425,24 @@ static PyType_Spec pycpointer_type_spec = {
14251425
PyCArrayType_init ensures that the new Array subclass created has a _length_
14261426
attribute, and a _type_ attribute.
14271427
*/
1428+
/*[clinic input]
1429+
class _ctypes.PyCArrayType_Type "CDataObject *" "clinic_state()->PyCArrayType_Type"
1430+
[clinic start generated code]*/
1431+
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6340cbaead1bf3f3]*/
1432+
1433+
/*[clinic input]
1434+
@critical_section
1435+
@setter
1436+
_ctypes.PyCArrayType_Type.raw
1437+
[clinic start generated code]*/
14281438

14291439
static int
1430-
CharArray_set_raw(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
1440+
_ctypes_PyCArrayType_Type_raw_set_impl(CDataObject *self, PyObject *value)
1441+
/*[clinic end generated code: output=cf9b2a9fd92e9ecb input=a3717561efc45efd]*/
14311442
{
14321443
char *ptr;
14331444
Py_ssize_t size;
14341445
Py_buffer view;
1435-
CDataObject *self = _CDataObject_CAST(op);
14361446

14371447
if (value == NULL) {
14381448
PyErr_SetString(PyExc_AttributeError, "cannot delete attribute");
@@ -1457,39 +1467,51 @@ CharArray_set_raw(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
14571467
return -1;
14581468
}
14591469

1470+
/*[clinic input]
1471+
@critical_section
1472+
@getter
1473+
_ctypes.PyCArrayType_Type.raw
1474+
[clinic start generated code]*/
1475+
14601476
static PyObject *
1461-
CharArray_get_raw(PyObject *op, void *Py_UNUSED(ignored))
1477+
_ctypes_PyCArrayType_Type_raw_get_impl(CDataObject *self)
1478+
/*[clinic end generated code: output=3a90be6f43764e31 input=4c49bbb715235ba7]*/
14621479
{
1463-
PyObject *res;
1464-
CDataObject *self = _CDataObject_CAST(op);
1465-
LOCK_PTR(self);
1466-
res = PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
1467-
UNLOCK_PTR(self);
1468-
return res;
1480+
return PyBytes_FromStringAndSize(self->b_ptr, self->b_size);
14691481
}
14701482

1483+
/*[clinic input]
1484+
@critical_section
1485+
@getter
1486+
_ctypes.PyCArrayType_Type.value
1487+
[clinic start generated code]*/
1488+
14711489
static PyObject *
1472-
CharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
1490+
_ctypes_PyCArrayType_Type_value_get_impl(CDataObject *self)
1491+
/*[clinic end generated code: output=fb0636f4d8875483 input=2432a2aeb1ed78d1]*/
14731492
{
14741493
Py_ssize_t i;
14751494
PyObject *res;
1476-
CDataObject *self = _CDataObject_CAST(op);
1477-
LOCK_PTR(self);
14781495
char *ptr = self->b_ptr;
14791496
for (i = 0; i < self->b_size; ++i)
14801497
if (*ptr++ == '\0')
14811498
break;
14821499
res = PyBytes_FromStringAndSize(self->b_ptr, i);
1483-
UNLOCK_PTR(self);
14841500
return res;
14851501
}
14861502

1503+
/*[clinic input]
1504+
@critical_section
1505+
@setter
1506+
_ctypes.PyCArrayType_Type.value
1507+
[clinic start generated code]*/
1508+
14871509
static int
1488-
CharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
1510+
_ctypes_PyCArrayType_Type_value_set_impl(CDataObject *self, PyObject *value)
1511+
/*[clinic end generated code: output=39ad655636a28dd5 input=e2e6385fc6ab1a29]*/
14891512
{
14901513
const char *ptr;
14911514
Py_ssize_t size;
1492-
CDataObject *self = _CDataObject_CAST(op);
14931515

14941516
if (value == NULL) {
14951517
PyErr_SetString(PyExc_TypeError,
@@ -1513,40 +1535,46 @@ CharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
15131535
}
15141536

15151537
ptr = PyBytes_AS_STRING(value);
1516-
LOCK_PTR(self);
15171538
memcpy(self->b_ptr, ptr, size);
15181539
if (size < self->b_size)
15191540
self->b_ptr[size] = '\0';
1520-
UNLOCK_PTR(self);
15211541
Py_DECREF(value);
15221542

15231543
return 0;
15241544
}
15251545

15261546
static PyGetSetDef CharArray_getsets[] = {
1527-
{ "raw", CharArray_get_raw, CharArray_set_raw, "value", NULL },
1528-
{ "value", CharArray_get_value, CharArray_set_value, "string value" },
1547+
_CTYPES_PYCARRAYTYPE_TYPE_RAW_GETSETDEF
1548+
_CTYPES_PYCARRAYTYPE_TYPE_VALUE_GETSETDEF
15291549
{ NULL, NULL }
15301550
};
15311551

15321552
static PyObject *
1533-
WCharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
1553+
WCharArray_get_value_lock_held(PyObject *op)
15341554
{
15351555
Py_ssize_t i;
15361556
PyObject *res;
15371557
CDataObject *self = _CDataObject_CAST(op);
15381558
wchar_t *ptr = (wchar_t *)self->b_ptr;
1539-
LOCK_PTR(self);
15401559
for (i = 0; i < self->b_size/(Py_ssize_t)sizeof(wchar_t); ++i)
15411560
if (*ptr++ == (wchar_t)0)
15421561
break;
15431562
res = PyUnicode_FromWideChar((wchar_t *)self->b_ptr, i);
1544-
UNLOCK_PTR(self);
1563+
return res;
1564+
}
1565+
1566+
static PyObject *
1567+
WCharArray_get_value(PyObject *op, void *Py_UNUSED(ignored))
1568+
{
1569+
PyObject *res;
1570+
Py_BEGIN_CRITICAL_SECTION(op);
1571+
res = WCharArray_get_value_lock_held(op);
1572+
Py_END_CRITICAL_SECTION();
15451573
return res;
15461574
}
15471575

15481576
static int
1549-
WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
1577+
WCharArray_set_value_lock_held(PyObject *op, PyObject *value)
15501578
{
15511579
CDataObject *self = _CDataObject_CAST(op);
15521580

@@ -1575,12 +1603,20 @@ WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
15751603
return -1;
15761604
}
15771605
Py_ssize_t rc;
1578-
LOCK_PTR(self);
15791606
rc = PyUnicode_AsWideChar(value, (wchar_t *)self->b_ptr, size);
1580-
UNLOCK_PTR(self);
15811607
return rc < 0 ? -1 : 0;
15821608
}
15831609

1610+
static int
1611+
WCharArray_set_value(PyObject *op, PyObject *value, void *Py_UNUSED(ignored))
1612+
{
1613+
int rc;
1614+
Py_BEGIN_CRITICAL_SECTION(op);
1615+
rc = WCharArray_set_value_lock_held(op, value);
1616+
Py_END_CRITICAL_SECTION();
1617+
return rc;
1618+
}
1619+
15841620
static PyGetSetDef WCharArray_getsets[] = {
15851621
{ "value", WCharArray_get_value, WCharArray_set_value, "string value" },
15861622
{ NULL, NULL }
@@ -2779,8 +2815,9 @@ static PyType_Spec pycfuncptr_type_spec = {
27792815
static CDataObject *
27802816
PyCData_GetContainer(CDataObject *self)
27812817
{
2782-
while (self->b_base)
2818+
while (self->b_base) {
27832819
self = self->b_base;
2820+
}
27842821
if (self->b_objects == NULL) {
27852822
if (self->b_length) {
27862823
self->b_objects = PyDict_New();
@@ -6305,4 +6342,4 @@ PyMODINIT_FUNC
63056342
PyInit__ctypes(void)
63066343
{
63076344
return PyModuleDef_Init(&_ctypesmodule);
6308-
}
6345+
}

Modules/_ctypes/clinic/_ctypes.c.h

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

0 commit comments

Comments
 (0)