https://github.com/python/cpython/commit/ffaeb3dddf17b891301e6f172c87267f59784d00
commit: ffaeb3dddf17b891301e6f172c87267f59784d00
branch: main
author: Duane Griffin <dua...@dghda.com>
committer: corona10 <donghee.n...@gmail.com>
date: 2025-05-14T13:49:35-04:00
summary:

gh-127081: add critical sections to `dbm` objects (gh-132749)

files:
A Misc/NEWS.d/next/Library/2025-04-21-01-05-14.gh-issue-127081.Egrpq7.rst
M Modules/_dbmmodule.c
M Modules/_gdbmmodule.c
M Modules/clinic/_dbmmodule.c.h
M Modules/clinic/_gdbmmodule.c.h

diff --git 
a/Misc/NEWS.d/next/Library/2025-04-21-01-05-14.gh-issue-127081.Egrpq7.rst 
b/Misc/NEWS.d/next/Library/2025-04-21-01-05-14.gh-issue-127081.Egrpq7.rst
new file mode 100644
index 00000000000000..30643673bf9a3f
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2025-04-21-01-05-14.gh-issue-127081.Egrpq7.rst
@@ -0,0 +1,2 @@
+Fix libc thread safety issues with :mod:`dbm` by performing stateful
+operations in critical sections.
diff --git a/Modules/_dbmmodule.c b/Modules/_dbmmodule.c
index cc65cbd98d71dc..0cd0f043de453d 100644
--- a/Modules/_dbmmodule.c
+++ b/Modules/_dbmmodule.c
@@ -69,6 +69,7 @@ typedef struct {
 #include "clinic/_dbmmodule.c.h"
 
 #define check_dbmobject_open(v, err)                                \
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED((v))                  \
     if ((v)->di_dbm == NULL) {                                      \
         PyErr_SetString(err, "DBM object has already been closed"); \
         return NULL;                                                \
@@ -116,7 +117,7 @@ dbm_dealloc(PyObject *self)
 }
 
 static Py_ssize_t
-dbm_length(PyObject *self)
+dbm_length_lock_held(PyObject *self)
 {
     dbmobject *dp = dbmobject_CAST(self);
     _dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -138,8 +139,18 @@ dbm_length(PyObject *self)
     return dp->di_size;
 }
 
+static Py_ssize_t
+dbm_length(PyObject *self)
+{
+    Py_ssize_t result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = dbm_length_lock_held(self);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 static int
-dbm_bool(PyObject *self)
+dbm_bool_lock_held(PyObject *self)
 {
     dbmobject *dp = dbmobject_CAST(self);
     _dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -170,8 +181,18 @@ dbm_bool(PyObject *self)
     return 1;
 }
 
+static int
+dbm_bool(PyObject *self)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = dbm_bool_lock_held(self);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 static PyObject *
-dbm_subscript(PyObject *self, PyObject *key)
+dbm_subscript_lock_held(PyObject *self, PyObject *key)
 {
     datum drec, krec;
     Py_ssize_t tmp_size;
@@ -197,8 +218,18 @@ dbm_subscript(PyObject *self, PyObject *key)
     return PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
 }
 
+static PyObject *
+dbm_subscript(PyObject *self, PyObject *key)
+{
+    PyObject *result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = dbm_subscript_lock_held(self, key);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 static int
-dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
+dbm_ass_sub_lock_held(PyObject *self, PyObject *v, PyObject *w)
 {
     datum krec, drec;
     Py_ssize_t tmp_size;
@@ -252,7 +283,18 @@ dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
     return 0;
 }
 
+static int
+dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = dbm_ass_sub_lock_held(self, v, w);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 /*[clinic input]
+@critical_section
 _dbm.dbm.close
 
 Close the database.
@@ -260,7 +302,7 @@ Close the database.
 
 static PyObject *
 _dbm_dbm_close_impl(dbmobject *self)
-/*[clinic end generated code: output=c8dc5b6709600b86 input=046db72377d51be8]*/
+/*[clinic end generated code: output=c8dc5b6709600b86 input=4a94f79facbc28ca]*/
 {
     if (self->di_dbm) {
         dbm_close(self->di_dbm);
@@ -270,6 +312,7 @@ _dbm_dbm_close_impl(dbmobject *self)
 }
 
 /*[clinic input]
+@critical_section
 _dbm.dbm.keys
 
     cls: defining_class
@@ -279,7 +322,7 @@ Return a list of all keys in the database.
 
 static PyObject *
 _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=f2a593b3038e5996 input=d3706a28fc051097]*/
+/*[clinic end generated code: output=f2a593b3038e5996 input=6ddefeadf2a80156]*/
 {
     PyObject *v, *item;
     datum key;
@@ -310,7 +353,7 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls)
 }
 
 static int
-dbm_contains(PyObject *self, PyObject *arg)
+dbm_contains_lock_held(PyObject *self, PyObject *arg)
 {
     dbmobject *dp = dbmobject_CAST(self);
     datum key, val;
@@ -343,7 +386,18 @@ dbm_contains(PyObject *self, PyObject *arg)
     return val.dptr != NULL;
 }
 
+static int
+dbm_contains(PyObject *self, PyObject *arg)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = dbm_contains_lock_held(self, arg);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 /*[clinic input]
+@critical_section
 _dbm.dbm.get
     cls: defining_class
     key: str(accept={str, robuffer}, zeroes=True)
@@ -356,7 +410,7 @@ Return the value for key if present, otherwise default.
 static PyObject *
 _dbm_dbm_get_impl(dbmobject *self, PyTypeObject *cls, const char *key,
                   Py_ssize_t key_length, PyObject *default_value)
-/*[clinic end generated code: output=b4e55f8b6d482bc4 input=66b993b8349fa8c1]*/
+/*[clinic end generated code: output=b4e55f8b6d482bc4 input=1d88a22bb5e55202]*/
 {
     datum dbm_key, val;
     _dbm_state *state = PyType_GetModuleState(cls);
@@ -373,6 +427,7 @@ _dbm_dbm_get_impl(dbmobject *self, PyTypeObject *cls, const 
char *key,
 }
 
 /*[clinic input]
+@critical_section
 _dbm.dbm.setdefault
     cls: defining_class
     key: str(accept={str, robuffer}, zeroes=True)
@@ -387,7 +442,7 @@ If key is not in the database, it is inserted with default 
as the value.
 static PyObject *
 _dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject *cls, const char *key,
                          Py_ssize_t key_length, PyObject *default_value)
-/*[clinic end generated code: output=9c2f6ea6d0fb576c input=126a3ff15c5f8232]*/
+/*[clinic end generated code: output=9c2f6ea6d0fb576c input=c01510ef7571e13b]*/
 {
     datum dbm_key, val;
     Py_ssize_t tmp_size;
@@ -427,6 +482,7 @@ _dbm_dbm_setdefault_impl(dbmobject *self, PyTypeObject 
*cls, const char *key,
 }
 
 /*[clinic input]
+@critical_section
 _dbm.dbm.clear
     cls: defining_class
     /
@@ -436,7 +492,7 @@ Remove all items from the database.
 
 static PyObject *
 _dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=8d126b9e1d01a434 input=43aa6ca1acb7f5f5]*/
+/*[clinic end generated code: output=8d126b9e1d01a434 input=a1aa5d99adfb9656]*/
 {
     _dbm_state *state = PyType_GetModuleState(cls);
     assert(state != NULL);
diff --git a/Modules/_gdbmmodule.c b/Modules/_gdbmmodule.c
index ab2ebdba9249bf..9c402e20e513b9 100644
--- a/Modules/_gdbmmodule.c
+++ b/Modules/_gdbmmodule.c
@@ -81,6 +81,7 @@ typedef struct {
 #include "clinic/_gdbmmodule.c.h"
 
 #define check_gdbmobject_open(v, err)                                 \
+    _Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED((v))                   \
     if ((v)->di_dbm == NULL) {                                       \
         PyErr_SetString(err, "GDBM object has already been closed"); \
         return NULL;                                                 \
@@ -142,7 +143,7 @@ gdbm_dealloc(PyObject *op)
 }
 
 static Py_ssize_t
-gdbm_length(PyObject *op)
+gdbm_length_lock_held(PyObject *op)
 {
     gdbmobject *dp = _gdbmobject_CAST(op);
     _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -188,8 +189,18 @@ gdbm_length(PyObject *op)
     return dp->di_size;
 }
 
+static Py_ssize_t
+gdbm_length(PyObject *op)
+{
+    Py_ssize_t result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = gdbm_length_lock_held(op);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 static int
-gdbm_bool(PyObject *op)
+gdbm_bool_lock_held(PyObject *op)
 {
     gdbmobject *dp = _gdbmobject_CAST(op);
     _gdbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
@@ -218,6 +229,16 @@ gdbm_bool(PyObject *op)
     return 1;
 }
 
+static int
+gdbm_bool(PyObject *op)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = gdbm_bool_lock_held(op);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 // Wrapper function for PyArg_Parse(o, "s#", &d.dptr, &d.size).
 // This function is needed to support PY_SSIZE_T_CLEAN.
 // Return 1 on success, same to PyArg_Parse().
@@ -240,7 +261,7 @@ parse_datum(PyObject *o, datum *d, const char *failmsg)
 }
 
 static PyObject *
-gdbm_subscript(PyObject *op, PyObject *key)
+gdbm_subscript_lock_held(PyObject *op, PyObject *key)
 {
     PyObject *v;
     datum drec, krec;
@@ -265,6 +286,16 @@ gdbm_subscript(PyObject *op, PyObject *key)
     return v;
 }
 
+static PyObject *
+gdbm_subscript(PyObject *op, PyObject *key)
+{
+    PyObject *result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = gdbm_subscript_lock_held(op, key);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 /*[clinic input]
 _gdbm.gdbm.get
 
@@ -290,7 +321,7 @@ _gdbm_gdbm_get_impl(gdbmobject *self, PyObject *key, 
PyObject *default_value)
 }
 
 static int
-gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
+gdbm_ass_sub_lock_held(PyObject *op, PyObject *v, PyObject *w)
 {
     datum krec, drec;
     const char *failmsg = "gdbm mappings have bytes or string indices only";
@@ -335,7 +366,18 @@ gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
     return 0;
 }
 
+static int
+gdbm_ass_sub(PyObject *op, PyObject *v, PyObject *w)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(op);
+    result = gdbm_ass_sub_lock_held(op, v, w);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.setdefault
 
     key: object
@@ -348,7 +390,7 @@ Get value for key, or set it to default and return default 
if not present.
 static PyObject *
 _gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
                            PyObject *default_value)
-/*[clinic end generated code: output=f3246e880509f142 input=0db46b69e9680171]*/
+/*[clinic end generated code: output=f3246e880509f142 input=854374cd81ab51b6]*/
 {
     PyObject *res;
 
@@ -363,6 +405,7 @@ _gdbm_gdbm_setdefault_impl(gdbmobject *self, PyObject *key,
 }
 
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.close
 
 Close the database.
@@ -370,7 +413,7 @@ Close the database.
 
 static PyObject *
 _gdbm_gdbm_close_impl(gdbmobject *self)
-/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=0a203447379b45fd]*/
+/*[clinic end generated code: output=f5abb4d6bb9e52d5 input=56b604f4e77f533d]*/
 {
     if (self->di_dbm) {
         gdbm_close(self->di_dbm);
@@ -381,6 +424,7 @@ _gdbm_gdbm_close_impl(gdbmobject *self)
 
 /* XXX Should return a set or a set view */
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.keys
 
     cls: defining_class
@@ -390,7 +434,7 @@ Get a list of all keys in the database.
 
 static PyObject *
 _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=c24b824e81404755 input=1428b7c79703d7d5]*/
+/*[clinic end generated code: output=c24b824e81404755 input=785988b1ea8f77e0]*/
 {
     PyObject *v, *item;
     datum key, nextkey;
@@ -432,7 +476,7 @@ _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls)
 }
 
 static int
-gdbm_contains(PyObject *self, PyObject *arg)
+gdbm_contains_lock_held(PyObject *self, PyObject *arg)
 {
     gdbmobject *dp = (gdbmobject *)self;
     datum key;
@@ -463,7 +507,18 @@ gdbm_contains(PyObject *self, PyObject *arg)
     return gdbm_exists(dp->di_dbm, key);
 }
 
+static int
+gdbm_contains(PyObject *self, PyObject *arg)
+{
+    int result;
+    Py_BEGIN_CRITICAL_SECTION(self);
+    result = gdbm_contains_lock_held(self, arg);
+    Py_END_CRITICAL_SECTION();
+    return result;
+}
+
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.firstkey
 
     cls: defining_class
@@ -477,7 +532,7 @@ hash values, and won't be sorted by the key values.
 
 static PyObject *
 _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=139275e9c8b60827 input=ed8782a029a5d299]*/
+/*[clinic end generated code: output=139275e9c8b60827 input=aad5a7c886c542f5]*/
 {
     PyObject *v;
     datum key;
@@ -497,6 +552,7 @@ _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject 
*cls)
 }
 
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.nextkey
 
     cls: defining_class
@@ -517,7 +573,7 @@ to create a list in memory that contains them all:
 static PyObject *
 _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject *cls, const char *key,
                         Py_ssize_t key_length)
-/*[clinic end generated code: output=c81a69300ef41766 input=365e297bc0b3db48]*/
+/*[clinic end generated code: output=c81a69300ef41766 input=181f1130d5bfeb1e]*/
 {
     PyObject *v;
     datum dbm_key, nextkey;
@@ -539,6 +595,7 @@ _gdbm_gdbm_nextkey_impl(gdbmobject *self, PyTypeObject 
*cls, const char *key,
 }
 
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.reorganize
 
     cls: defining_class
@@ -554,7 +611,7 @@ kept and reused as new (key,value) pairs are added.
 
 static PyObject *
 _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=d77c69e8e3dd644a input=e1359faeef844e46]*/
+/*[clinic end generated code: output=d77c69e8e3dd644a input=3e3ca0d2ea787861]*/
 {
     _gdbm_state *state = PyType_GetModuleState(cls);
     assert(state != NULL);
@@ -573,6 +630,7 @@ _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject 
*cls)
 }
 
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.sync
 
     cls: defining_class
@@ -585,7 +643,7 @@ any unwritten data to be written to the disk.
 
 static PyObject *
 _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=bb680a2035c3f592 input=3d749235f79b6f2a]*/
+/*[clinic end generated code: output=bb680a2035c3f592 input=6054385b071d238a]*/
 {
     _gdbm_state *state = PyType_GetModuleState(cls);
     assert(state != NULL);
@@ -595,6 +653,7 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls)
 }
 
 /*[clinic input]
+@critical_section
 _gdbm.gdbm.clear
     cls: defining_class
     /
@@ -604,7 +663,7 @@ Remove all items from the database.
 
 static PyObject *
 _gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject *cls)
-/*[clinic end generated code: output=673577c573318661 input=34136d52fcdd4210]*/
+/*[clinic end generated code: output=673577c573318661 input=b17467adfe62f23d]*/
 {
     _gdbm_state *state = PyType_GetModuleState(cls);
     assert(state != NULL);
diff --git a/Modules/clinic/_dbmmodule.c.h b/Modules/clinic/_dbmmodule.c.h
index 5e503194408776..091ce9edc43d4b 100644
--- a/Modules/clinic/_dbmmodule.c.h
+++ b/Modules/clinic/_dbmmodule.c.h
@@ -5,6 +5,7 @@ preserve
 #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
 #  include "pycore_runtime.h"     // _Py_SINGLETON()
 #endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_modsupport.h"    // _PyArg_UnpackKeywords()
 
 PyDoc_STRVAR(_dbm_dbm_close__doc__,
@@ -22,7 +23,13 @@ _dbm_dbm_close_impl(dbmobject *self);
 static PyObject *
 _dbm_dbm_close(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    return _dbm_dbm_close_impl((dbmobject *)self);
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _dbm_dbm_close_impl((dbmobject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
 }
 
 PyDoc_STRVAR(_dbm_dbm_keys__doc__,
@@ -40,11 +47,18 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls);
 static PyObject *
 _dbm_dbm_keys(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _dbm_dbm_keys_impl((dbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _dbm_dbm_keys_impl((dbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(_dbm_dbm_get__doc__,
@@ -85,7 +99,9 @@ _dbm_dbm_get(PyObject *self, PyTypeObject *cls, PyObject 
*const *args, Py_ssize_
         &key, &key_length, &default_value)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = _dbm_dbm_get_impl((dbmobject *)self, cls, key, key_length, 
default_value);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -131,7 +147,9 @@ _dbm_dbm_setdefault(PyObject *self, PyTypeObject *cls, 
PyObject *const *args, Py
         &key, &key_length, &default_value)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = _dbm_dbm_setdefault_impl((dbmobject *)self, cls, key, 
key_length, default_value);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -152,11 +170,18 @@ _dbm_dbm_clear_impl(dbmobject *self, PyTypeObject *cls);
 static PyObject *
 _dbm_dbm_clear(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "clear() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _dbm_dbm_clear_impl((dbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _dbm_dbm_clear_impl((dbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(dbmopen__doc__,
@@ -221,4 +246,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t 
nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=3b456118f231b160 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=279511ea7cda38dd input=a9049054013a1b77]*/
diff --git a/Modules/clinic/_gdbmmodule.c.h b/Modules/clinic/_gdbmmodule.c.h
index 00950f18e53541..6fd6aa3da50335 100644
--- a/Modules/clinic/_gdbmmodule.c.h
+++ b/Modules/clinic/_gdbmmodule.c.h
@@ -5,6 +5,7 @@ preserve
 #if defined(Py_BUILD_CORE) && !defined(Py_BUILD_CORE_MODULE)
 #  include "pycore_runtime.h"     // _Py_SINGLETON()
 #endif
+#include "pycore_critical_section.h"// Py_BEGIN_CRITICAL_SECTION()
 #include "pycore_modsupport.h"    // _PyArg_CheckPositional()
 
 PyDoc_STRVAR(_gdbm_gdbm_get__doc__,
@@ -70,7 +71,9 @@ _gdbm_gdbm_setdefault(PyObject *self, PyObject *const *args, 
Py_ssize_t nargs)
     }
     default_value = args[1];
 skip_optional:
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = _gdbm_gdbm_setdefault_impl((gdbmobject *)self, key, 
default_value);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -91,7 +94,13 @@ _gdbm_gdbm_close_impl(gdbmobject *self);
 static PyObject *
 _gdbm_gdbm_close(PyObject *self, PyObject *Py_UNUSED(ignored))
 {
-    return _gdbm_gdbm_close_impl((gdbmobject *)self);
+    PyObject *return_value = NULL;
+
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_close_impl((gdbmobject *)self);
+    Py_END_CRITICAL_SECTION();
+
+    return return_value;
 }
 
 PyDoc_STRVAR(_gdbm_gdbm_keys__doc__,
@@ -109,11 +118,18 @@ _gdbm_gdbm_keys_impl(gdbmobject *self, PyTypeObject *cls);
 static PyObject *
 _gdbm_gdbm_keys(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "keys() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _gdbm_gdbm_keys_impl((gdbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_keys_impl((gdbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(_gdbm_gdbm_firstkey__doc__,
@@ -135,11 +151,18 @@ _gdbm_gdbm_firstkey_impl(gdbmobject *self, PyTypeObject 
*cls);
 static PyObject *
 _gdbm_gdbm_firstkey(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "firstkey() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _gdbm_gdbm_firstkey_impl((gdbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_firstkey_impl((gdbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(_gdbm_gdbm_nextkey__doc__,
@@ -187,7 +210,9 @@ _gdbm_gdbm_nextkey(PyObject *self, PyTypeObject *cls, 
PyObject *const *args, Py_
         &key, &key_length)) {
         goto exit;
     }
+    Py_BEGIN_CRITICAL_SECTION(self);
     return_value = _gdbm_gdbm_nextkey_impl((gdbmobject *)self, cls, key, 
key_length);
+    Py_END_CRITICAL_SECTION();
 
 exit:
     return return_value;
@@ -214,11 +239,18 @@ _gdbm_gdbm_reorganize_impl(gdbmobject *self, PyTypeObject 
*cls);
 static PyObject *
 _gdbm_gdbm_reorganize(PyObject *self, PyTypeObject *cls, PyObject *const 
*args, Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "reorganize() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _gdbm_gdbm_reorganize_impl((gdbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_reorganize_impl((gdbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(_gdbm_gdbm_sync__doc__,
@@ -239,11 +271,18 @@ _gdbm_gdbm_sync_impl(gdbmobject *self, PyTypeObject *cls);
 static PyObject *
 _gdbm_gdbm_sync(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "sync() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _gdbm_gdbm_sync_impl((gdbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_sync_impl((gdbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(_gdbm_gdbm_clear__doc__,
@@ -261,11 +300,18 @@ _gdbm_gdbm_clear_impl(gdbmobject *self, PyTypeObject 
*cls);
 static PyObject *
 _gdbm_gdbm_clear(PyObject *self, PyTypeObject *cls, PyObject *const *args, 
Py_ssize_t nargs, PyObject *kwnames)
 {
+    PyObject *return_value = NULL;
+
     if (nargs || (kwnames && PyTuple_GET_SIZE(kwnames))) {
         PyErr_SetString(PyExc_TypeError, "clear() takes no arguments");
-        return NULL;
+        goto exit;
     }
-    return _gdbm_gdbm_clear_impl((gdbmobject *)self, cls);
+    Py_BEGIN_CRITICAL_SECTION(self);
+    return_value = _gdbm_gdbm_clear_impl((gdbmobject *)self, cls);
+    Py_END_CRITICAL_SECTION();
+
+exit:
+    return return_value;
 }
 
 PyDoc_STRVAR(dbmopen__doc__,
@@ -343,4 +389,4 @@ dbmopen(PyObject *module, PyObject *const *args, Py_ssize_t 
nargs)
 exit:
     return return_value;
 }
-/*[clinic end generated code: output=d974cb39e4ee5d67 input=a9049054013a1b77]*/
+/*[clinic end generated code: output=8bca34ce9d4493dd input=a9049054013a1b77]*/

_______________________________________________
Python-checkins mailing list -- python-checkins@python.org
To unsubscribe send an email to python-checkins-le...@python.org
https://mail.python.org/mailman3/lists/python-checkins.python.org/
Member address: arch...@mail-archive.com

Reply via email to