Skip to content

Commit 0774870

Browse files
committed
Switch to calling a *_lock_held variant while holding the critical section
instead of using gotos everywhere.
1 parent 83a05d5 commit 0774870

File tree

2 files changed

+135
-105
lines changed

2 files changed

+135
-105
lines changed

Modules/_dbmmodule.c

Lines changed: 69 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,8 @@ typedef struct {
6868

6969
#include "clinic/_dbmmodule.c.h"
7070

71-
/* NOTE: Must be used within a critical section! */
7271
#define check_dbmobject_open(v, err) \
72+
_Py_CRITICAL_SECTION_ASSERT_OBJECT_LOCKED((v)) \
7373
if ((v)->di_dbm == NULL) { \
7474
PyErr_SetString(err, "DBM object has already been closed"); \
7575
return NULL; \
@@ -117,17 +117,14 @@ dbm_dealloc(PyObject *self)
117117
}
118118

119119
static Py_ssize_t
120-
dbm_length(PyObject *self)
120+
dbm_length_lock_held(PyObject *self)
121121
{
122-
Py_ssize_t result = -1;
123122
dbmobject *dp = dbmobject_CAST(self);
124123
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
125124
assert(state != NULL);
126-
127-
Py_BEGIN_CRITICAL_SECTION(self);
128125
if (dp->di_dbm == NULL) {
129126
PyErr_SetString(state->dbm_error, "DBM object has already been closed");
130-
goto done;
127+
return -1;
131128
}
132129
if ( dp->di_size < 0 ) {
133130
datum key;
@@ -139,95 +136,103 @@ dbm_length(PyObject *self)
139136
size++;
140137
dp->di_size = size;
141138
}
142-
result = dp->di_size;
143-
done:;
139+
return dp->di_size;
140+
}
141+
142+
static Py_ssize_t
143+
dbm_length(PyObject *self)
144+
{
145+
Py_ssize_t result;
146+
Py_BEGIN_CRITICAL_SECTION(self);
147+
result = dbm_length_lock_held(self);
144148
Py_END_CRITICAL_SECTION();
145149
return result;
146150
}
147151

148152
static int
149-
dbm_bool(PyObject *self)
153+
dbm_bool_lock_held(PyObject *self)
150154
{
151-
int result;
152155
dbmobject *dp = dbmobject_CAST(self);
153156
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
154157
assert(state != NULL);
155158

156-
Py_BEGIN_CRITICAL_SECTION(self);
157159
if (dp->di_dbm == NULL) {
158160
PyErr_SetString(state->dbm_error, "DBM object has already been closed");
159-
result = -1;
160-
goto done;
161+
return -1;
161162
}
162163

163164
if (dp->di_size > 0) {
164165
/* Known non-zero size. */
165-
result = 1;
166-
goto done;
166+
return 1;
167167
}
168168
if (dp->di_size == 0) {
169169
/* Known zero size. */
170-
result = 0;
171-
goto done;
170+
return 0;
172171
}
173172

174173
/* Unknown size. Ensure DBM object has an entry. */
175174
datum key = dbm_firstkey(dp->di_dbm);
176175
if (key.dptr == NULL) {
177176
/* Empty. Cache this fact. */
178-
result = dp->di_size = 0;
179-
goto done;
177+
dp->di_size = 0;
178+
return 0;
180179
}
181-
182180
/* Non-empty. Don't cache the length since we don't know. */
183-
result = 1;
184-
done:;
181+
return 1;
182+
}
183+
184+
static int
185+
dbm_bool(PyObject *self)
186+
{
187+
int result;
188+
Py_BEGIN_CRITICAL_SECTION(self);
189+
result = dbm_bool_lock_held(self);
185190
Py_END_CRITICAL_SECTION();
186191
return result;
187192
}
188193

189194
static PyObject *
190-
dbm_subscript(PyObject *self, PyObject *key)
195+
dbm_subscript_lock_held(PyObject *self, PyObject *key)
191196
{
192197
datum drec, krec;
193198
Py_ssize_t tmp_size;
194-
PyObject *result = NULL;
195199
dbmobject *dp = dbmobject_CAST(self);
196200
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
197201
assert(state != NULL);
198202
if (!PyArg_Parse(key, "s#", &krec.dptr, &tmp_size)) {
199203
return NULL;
200204
}
201-
krec.dsize = tmp_size;
202205

203-
Py_BEGIN_CRITICAL_SECTION(self);
204-
/* Can't use the macro here as it returns. */
205-
if (dp->di_dbm == NULL) {
206-
PyErr_SetString(state->dbm_error, "DBM object has already been closed");
207-
goto done;
208-
}
206+
krec.dsize = tmp_size;
207+
check_dbmobject_open(dp, state->dbm_error);
209208
drec = dbm_fetch(dp->di_dbm, krec);
210209
if ( drec.dptr == 0 ) {
211210
PyErr_SetObject(PyExc_KeyError, key);
212-
goto done;
211+
return NULL;
213212
}
214213
if ( dbm_error(dp->di_dbm) ) {
215214
dbm_clearerr(dp->di_dbm);
216215
PyErr_SetString(state->dbm_error, "");
217-
goto done;
216+
return NULL;
218217
}
219-
result = PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
220-
done:;
218+
return PyBytes_FromStringAndSize(drec.dptr, drec.dsize);
219+
}
220+
221+
static PyObject *
222+
dbm_subscript(PyObject *self, PyObject *key)
223+
{
224+
PyObject *result;
225+
Py_BEGIN_CRITICAL_SECTION(self);
226+
result = dbm_subscript_lock_held(self, key);
221227
Py_END_CRITICAL_SECTION();
222228
return result;
223229
}
224230

225231
static int
226-
dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
232+
dbm_ass_sub_lock_held(PyObject *self, PyObject *v, PyObject *w)
227233
{
228234
datum krec, drec;
229235
Py_ssize_t tmp_size;
230-
int result = -1;
231236
dbmobject *dp = dbmobject_CAST(self);
232237

233238
if ( !PyArg_Parse(v, "s#", &krec.dptr, &tmp_size) ) {
@@ -238,13 +243,10 @@ dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
238243
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
239244
assert(state != NULL);
240245
krec.dsize = tmp_size;
241-
242-
Py_BEGIN_CRITICAL_SECTION(self);
243246
if (dp->di_dbm == NULL) {
244-
PyErr_SetString(state->dbm_error, "DBM object has already been closed");
245-
goto done;
247+
PyErr_SetString(state->dbm_error, "DBM object has already been closed");
248+
return -1;
246249
}
247-
248250
dp->di_size = -1;
249251
if (w == NULL) {
250252
if ( dbm_delete(dp->di_dbm, krec) < 0 ) {
@@ -257,30 +259,36 @@ dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
257259
else {
258260
PyErr_SetString(state->dbm_error, "cannot delete item from database");
259261
}
260-
goto done;
262+
return -1;
261263
}
262264
} else {
263265
if ( !PyArg_Parse(w, "s#", &drec.dptr, &tmp_size) ) {
264266
PyErr_SetString(PyExc_TypeError,
265267
"dbm mappings have bytes or string elements only");
266-
goto done;
268+
return -1;
267269
}
268270
drec.dsize = tmp_size;
269271
if ( dbm_store(dp->di_dbm, krec, drec, DBM_REPLACE) < 0 ) {
270272
dbm_clearerr(dp->di_dbm);
271273
PyErr_SetString(state->dbm_error,
272274
"cannot add item to database");
273-
goto done;
275+
return -1;
274276
}
275277
}
276278
if ( dbm_error(dp->di_dbm) ) {
277279
dbm_clearerr(dp->di_dbm);
278280
PyErr_SetString(state->dbm_error, "");
279-
goto done;
281+
return -1;
280282
}
283+
return 0;
284+
}
281285

282-
result = 0;
283-
done:;
286+
static int
287+
dbm_ass_sub(PyObject *self, PyObject *v, PyObject *w)
288+
{
289+
int result;
290+
Py_BEGIN_CRITICAL_SECTION(self);
291+
result = dbm_ass_sub_lock_held(self, v, w);
284292
Py_END_CRITICAL_SECTION();
285293
return result;
286294
}
@@ -345,41 +353,45 @@ _dbm_dbm_keys_impl(dbmobject *self, PyTypeObject *cls)
345353
}
346354

347355
static int
348-
dbm_contains(PyObject *self, PyObject *arg)
356+
dbm_contains_lock_held(PyObject *self, PyObject *arg)
349357
{
350358
dbmobject *dp = dbmobject_CAST(self);
351359
datum key, val;
352360
Py_ssize_t size;
353-
int result = -1;
354361

355362
_dbm_state *state = PyType_GetModuleState(Py_TYPE(dp));
356363
assert(state != NULL);
357-
358-
Py_BEGIN_CRITICAL_SECTION(self);
359364
if ((dp)->di_dbm == NULL) {
360365
PyErr_SetString(state->dbm_error,
361366
"DBM object has already been closed");
362-
goto done;
367+
return -1;
363368
}
364369
if (PyUnicode_Check(arg)) {
365370
key.dptr = (char *)PyUnicode_AsUTF8AndSize(arg, &size);
366371
key.dsize = size;
367372
if (key.dptr == NULL)
368-
goto done;
373+
return -1;
369374
}
370375
else if (!PyBytes_Check(arg)) {
371376
PyErr_Format(PyExc_TypeError,
372377
"dbm key must be bytes or string, not %.100s",
373378
Py_TYPE(arg)->tp_name);
374-
goto done;
379+
return -1;
375380
}
376381
else {
377382
key.dptr = PyBytes_AS_STRING(arg);
378383
key.dsize = PyBytes_GET_SIZE(arg);
379384
}
380385
val = dbm_fetch(dp->di_dbm, key);
381-
result = val.dptr != NULL;
382-
done:;
386+
return val.dptr != NULL;
387+
}
388+
389+
static int
390+
dbm_contains(PyObject *self, PyObject *arg)
391+
{
392+
int result;
393+
Py_BEGIN_CRITICAL_SECTION(self);
394+
result = dbm_contains_lock_held(self, arg);
383395
Py_END_CRITICAL_SECTION();
384396
return result;
385397
}

0 commit comments

Comments
 (0)