Skip to content

Commit

Permalink
pythongh-112062: Make _struct module thread-safe in --disable-gil b…
Browse files Browse the repository at this point in the history
…uilds

* use `PyDict_GetItemRef` instead of `PyDict_GetItemWithError` in `cache_struct_converter` to avoid usage of borrowed ref with explicit incref
* clear cache dict but preserve the reference in `_clearcache_impl`
* create cache dict in `_structmodule_exec`
  • Loading branch information
chgnrdv committed Nov 14, 2023
1 parent 9302f05 commit bc2dac3
Showing 1 changed file with 9 additions and 12 deletions.
21 changes: 9 additions & 12 deletions Modules/_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -2250,20 +2250,12 @@ cache_struct_converter(PyObject *module, PyObject *fmt, PyStructObject **ptr)
return 1;
}

if (state->cache == NULL) {
state->cache = PyDict_New();
if (state->cache == NULL)
return 0;
if (PyDict_GetItemRef(state->cache, fmt, ptr) < 0) {
return 0;
}

s_object = PyDict_GetItemWithError(state->cache, fmt);
if (s_object != NULL) {
*ptr = (PyStructObject *)Py_NewRef(s_object);
if (*ptr != NULL) {
return Py_CLEANUP_SUPPORTED;
}
else if (PyErr_Occurred()) {
return 0;
}

s_object = PyObject_CallOneArg(state->PyStructType, fmt);
if (s_object != NULL) {
Expand All @@ -2288,7 +2280,7 @@ static PyObject *
_clearcache_impl(PyObject *module)
/*[clinic end generated code: output=ce4fb8a7bf7cb523 input=463eaae04bab3211]*/
{
Py_CLEAR(get_struct_state(module)->cache);
PyDict_Clear(get_struct_state(module)->cache);
Py_RETURN_NONE;
}

Expand Down Expand Up @@ -2512,6 +2504,11 @@ _structmodule_exec(PyObject *m)
{
_structmodulestate *state = get_struct_state(m);

state->cache = PyDict_New();
if (state->cache == NULL) {
return -1;
}

state->PyStructType = PyType_FromModuleAndSpec(
m, &PyStructType_spec, NULL);
if (state->PyStructType == NULL) {
Expand Down

0 comments on commit bc2dac3

Please sign in to comment.