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

This commit is contained in:
Duane Griffin 2025-05-15 05:49:35 +12:00 committed by GitHub
parent 17d0fec702
commit ffaeb3dddf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 229 additions and 41 deletions

View file

@ -0,0 +1,2 @@
Fix libc thread safety issues with :mod:`dbm` by performing stateful
operations in critical sections.

View file

@ -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);

View file

@ -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);

View file

@ -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 @@ skip_optional:
exit:
return return_value;
}
/*[clinic end generated code: output=3b456118f231b160 input=a9049054013a1b77]*/
/*[clinic end generated code: output=279511ea7cda38dd input=a9049054013a1b77]*/

View file

@ -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 @@ skip_optional:
exit:
return return_value;
}
/*[clinic end generated code: output=d974cb39e4ee5d67 input=a9049054013a1b77]*/
/*[clinic end generated code: output=8bca34ce9d4493dd input=a9049054013a1b77]*/