Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e276717

Browse files
committed
Fix a tuple memory leak when raising DB, DBEnv and DBCursor "object
has been closed" exceptions. Adds a DBCursorClosedError exception in the closed cursor case for future use in fixing the legacy bsddb interface deadlock problems due to its use of cursors with DB_INIT_LOCK | DB_THREAD support enabled.
1 parent 54a831b commit e276717

1 file changed

Lines changed: 15 additions & 17 deletions

File tree

Modules/_bsddb.c

Lines changed: 15 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ static PyInterpreterState* _db_interpreterState = NULL;
148148
/* Exceptions */
149149

150150
static PyObject* DBError; /* Base class, all others derive from this */
151+
static PyObject* DBCursorClosedError; /* raised when trying to use a closed cursor object */
151152
static PyObject* DBKeyEmptyError; /* DB_KEYEMPTY */
152153
static PyObject* DBKeyExistError; /* DB_KEYEXIST */
153154
static PyObject* DBLockDeadlockError; /* DB_LOCK_DEADLOCK */
@@ -258,27 +259,23 @@ staticforward PyTypeObject DB_Type, DBCursor_Type, DBEnv_Type, DBTxn_Type, DBLoc
258259

259260
#define RETURN_NONE() Py_INCREF(Py_None); return Py_None;
260261

261-
#define CHECK_DB_NOT_CLOSED(dbobj) \
262-
if (dbobj->db == NULL) { \
263-
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
264-
"DB object has been closed")); \
265-
return NULL; \
262+
#define _CHECK_OBJECT_NOT_CLOSED(nonNull, pyErrObj, name) \
263+
if ((nonNull) == NULL) { \
264+
PyObject *errTuple = NULL; \
265+
errTuple = Py_BuildValue("(is)", 0, #name " object has been closed"); \
266+
PyErr_SetObject((pyErrObj), errTuple); \
267+
Py_DECREF(errTuple); \
268+
return NULL; \
266269
}
267270

268-
#define CHECK_ENV_NOT_CLOSED(env) \
269-
if (env->db_env == NULL) { \
270-
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
271-
"DBEnv object has been closed"));\
272-
return NULL; \
273-
}
271+
#define CHECK_DB_NOT_CLOSED(dbobj) \
272+
_CHECK_OBJECT_NOT_CLOSED(dbobj->db, DBError, DB)
274273

275-
#define CHECK_CURSOR_NOT_CLOSED(curs) \
276-
if (curs->dbc == NULL) { \
277-
PyErr_SetObject(DBError, Py_BuildValue("(is)", 0, \
278-
"DBCursor object has been closed"));\
279-
return NULL; \
280-
}
274+
#define CHECK_ENV_NOT_CLOSED(env) \
275+
_CHECK_OBJECT_NOT_CLOSED(env->db_env, DBError, DBEnv)
281276

277+
#define CHECK_CURSOR_NOT_CLOSED(curs) \
278+
_CHECK_OBJECT_NOT_CLOSED(curs->dbc, DBCursorClosedError, DBCursor)
282279

283280

284281
#define CHECK_DBFLAG(mydb, flag) (((mydb)->flags & (flag)) || \
@@ -4717,6 +4714,7 @@ DL_EXPORT(void) init_bsddb(void)
47174714
#if !INCOMPLETE_IS_WARNING
47184715
MAKE_EX(DBIncompleteError);
47194716
#endif
4717+
MAKE_EX(DBCursorClosedError);
47204718
MAKE_EX(DBKeyEmptyError);
47214719
MAKE_EX(DBKeyExistError);
47224720
MAKE_EX(DBLockDeadlockError);

0 commit comments

Comments
 (0)