Skip to content

Commit 62d2deb

Browse files
Try to add thread safety to pointer_type
1 parent fc3bc33 commit 62d2deb

2 files changed

Lines changed: 29 additions & 11 deletions

File tree

Modules/_ctypes/_ctypes.c

Lines changed: 25 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,9 @@ ctype_get_pointer_type(PyObject *self, void *Py_UNUSED(ignored))
588588
return NULL;
589589
}
590590

591-
if (info->pointer_type) {
592-
return Py_NewRef(info->pointer_type);
591+
PyObject* pointer_type = FT_ATOMIC_LOAD_PTR_ACQUIRE(info->pointer_type);
592+
if (pointer_type) {
593+
return Py_NewRef(pointer_type);
593594
}
594595
Py_RETURN_NONE;
595596
}
@@ -1227,26 +1228,39 @@ PyCPointerType_SetProto(ctypes_state *st, PyObject *self, StgInfo *stginfo, PyOb
12271228
PyErr_Format(PyExc_TypeError, "%R must have storage info", proto);
12281229
return -1;
12291230
}
1230-
if (info->pointer_type && info->pointer_type != self) {
1231+
1232+
PyObject* pointer_type = FT_ATOMIC_LOAD_PTR_ACQUIRE(info->pointer_type);
1233+
PyObject* stginfo_proto = FT_ATOMIC_LOAD_PTR_ACQUIRE(stginfo->proto);
1234+
1235+
if (pointer_type && pointer_type != self) {
12311236
PyErr_Format(PyExc_TypeError,
12321237
"pointer type already set: old=%R, new=%R",
1233-
info->pointer_type, self);
1238+
pointer_type, self);
12341239
return -1;
12351240
}
1236-
if (stginfo->proto && stginfo->proto != proto) {
1241+
if (stginfo_proto && stginfo_proto != proto) {
12371242
PyErr_Format(PyExc_TypeError,
12381243
"cls type already set: old=%R, new=%R",
1239-
stginfo->proto, proto);
1244+
stginfo_proto, proto);
12401245
return -1;
12411246
}
12421247

1243-
if (!stginfo->proto) {
1244-
stginfo->proto = Py_NewRef(proto);
1245-
}
1248+
if (!stginfo_proto || !pointer_type) {
1249+
STGINFO2_LOCK(stginfo, info);
1250+
1251+
stginfo_proto = FT_ATOMIC_LOAD_PTR_ACQUIRE(stginfo->proto);
1252+
if (!stginfo_proto) {
1253+
FT_ATOMIC_STORE_PTR_RELEASE(stginfo->proto, Py_NewRef(proto));
1254+
}
1255+
1256+
pointer_type = FT_ATOMIC_LOAD_PTR_ACQUIRE(info->pointer_type);
1257+
if (!pointer_type) {
1258+
FT_ATOMIC_STORE_PTR_RELEASE(info->pointer_type, Py_NewRef(self));
1259+
}
12461260

1247-
if (!info->pointer_type) {
1248-
info->pointer_type = Py_NewRef(self);
1261+
STGINFO2_UNLOCK();
12491262
}
1263+
12501264
return 0;
12511265
}
12521266

Modules/_ctypes/ctypes.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,10 @@ typedef struct {
422422
#define STGINFO_LOCK(stginfo) Py_BEGIN_CRITICAL_SECTION_MUT(&(stginfo)->mutex)
423423
#define STGINFO_UNLOCK() Py_END_CRITICAL_SECTION()
424424

425+
#define STGINFO2_LOCK(stginfo_a, stginfo_b) \
426+
Py_BEGIN_CRITICAL_SECTION2_MUT(&(stginfo_a)->mutex, &(stginfo_b)->mutex)
427+
#define STGINFO2_UNLOCK() Py_END_CRITICAL_SECTION2()
428+
425429
static inline uint8_t
426430
stginfo_get_dict_final(StgInfo *info)
427431
{

0 commit comments

Comments
 (0)