Skip to content

Commit 0da2bbd

Browse files
authored
[mypyc] Make some dict primitives thread-safe on free-threading builds (#21616)
Use thread-safe `PyDict_GetItemRef` instead of `PyDict_GetItemWithError`. Also fix an unrelated memory leak in a setdefault primitive. I used coding agent assist.
1 parent 8b6642d commit 0da2bbd

1 file changed

Lines changed: 20 additions & 20 deletions

File tree

mypyc/lib-rt/dict_ops.c

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,10 @@
1515
// some indirections.
1616
PyObject *CPyDict_GetItem(PyObject *dict, PyObject *key) {
1717
if (PyDict_CheckExact(dict)) {
18-
PyObject *res = PyDict_GetItemWithError(dict, key);
19-
if (!res) {
20-
if (!PyErr_Occurred()) {
21-
PyErr_SetObject(PyExc_KeyError, key);
22-
}
23-
} else {
24-
Py_INCREF(res);
18+
PyObject *res;
19+
int found = PyDict_GetItemRef(dict, key, &res);
20+
if (found == 0) {
21+
PyErr_SetObject(PyExc_KeyError, key);
2522
}
2623
return res;
2724
} else {
@@ -56,14 +53,15 @@ PyObject *CPyDict_Build(Py_ssize_t size, ...) {
5653
PyObject *CPyDict_Get(PyObject *dict, PyObject *key, PyObject *fallback) {
5754
// We are dodgily assuming that get on a subclass doesn't have
5855
// different behavior.
59-
PyObject *res = PyDict_GetItemWithError(dict, key);
60-
if (!res) {
61-
if (PyErr_Occurred()) {
62-
return NULL;
63-
}
64-
res = fallback;
56+
PyObject *res;
57+
int found = PyDict_GetItemRef(dict, key, &res);
58+
if (found < 0) {
59+
return NULL;
60+
}
61+
if (found == 0) {
62+
Py_INCREF(fallback);
63+
return fallback;
6564
}
66-
Py_INCREF(res);
6765
return res;
6866
}
6967

@@ -100,17 +98,19 @@ PyObject *CPyDict_SetDefaultWithEmptyDatatype(PyObject *dict, PyObject *key,
10098
} else if (data_type == 3) {
10199
new_obj = PySet_New(NULL);
102100
} else {
103-
return NULL;
101+
new_obj = NULL;
104102
}
105103

106-
if (CPyDict_SetItem(dict, key, new_obj) == -1) {
107-
return NULL;
104+
if (new_obj == NULL) {
105+
res = NULL;
106+
} else if (CPyDict_SetItem(dict, key, new_obj) == -1) {
107+
Py_DECREF(new_obj);
108+
res = NULL;
108109
} else {
109-
return new_obj;
110+
res = new_obj;
110111
}
111-
} else {
112-
return res;
113112
}
113+
return res;
114114
}
115115

116116
int CPyDict_SetItem(PyObject *dict, PyObject *key, PyObject *value) {

0 commit comments

Comments
 (0)