diff options
author | Andrew Bartlett <abartlet@samba.org> | 2012-07-16 19:43:15 +1000 |
---|---|---|
committer | Andrew Bartlett <abartlet@samba.org> | 2012-07-16 13:51:51 +0200 |
commit | c92a5670e3d60decbc13bd8680de37184bc12815 (patch) | |
tree | 5d0987b2c12caba6235cd55c35f87cde0c784ad8 | |
parent | a8e88332a394f4a4c3e43b496738008fba39d39f (diff) | |
download | samba-c92a5670e3d60decbc13bd8680de37184bc12815.tar.gz samba-c92a5670e3d60decbc13bd8680de37184bc12815.tar.bz2 samba-c92a5670e3d60decbc13bd8680de37184bc12815.zip |
pytdb: Check if the database is closed before we touch it
If .close() has already been called, we have to play dead - the
self->ctx is just not valid any more, as we have been shut down to
allow some other part of Samba to open the tdb.
Andrew Bartlett
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
Autobuild-Date(master): Mon Jul 16 13:51:52 CEST 2012 on sn-devel-104
-rw-r--r-- | lib/tdb/pytdb.c | 90 | ||||
-rw-r--r-- | lib/tdb/python/tests/simple.py | 5 |
2 files changed, 85 insertions, 10 deletions
diff --git a/lib/tdb/pytdb.c b/lib/tdb/pytdb.c index ca1c847fb5..ae0e6f808d 100644 --- a/lib/tdb/pytdb.c +++ b/lib/tdb/pytdb.c @@ -75,6 +75,20 @@ static PyObject *PyString_FromTDB_DATA(TDB_DATA data) return NULL; \ } +#define PyErr_TDB_RAISE_IF_CLOSED(self) \ + if (self->closed) { \ + PyErr_SetObject(PyExc_RuntimeError, \ + Py_BuildValue("(i,s)", TDB_ERR_IO, "Database is already closed")); \ + return NULL; \ + } + +#define PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self) \ + if (self->closed) { \ + PyErr_SetObject(PyExc_RuntimeError, \ + Py_BuildValue("(i,s)", TDB_ERR_IO, "Database is already closed")); \ + return -1; \ + } + static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwargs) { char *name = NULL; @@ -109,56 +123,74 @@ static PyObject *py_tdb_open(PyTypeObject *type, PyObject *args, PyObject *kwarg static PyObject *obj_transaction_cancel(PyTdbObject *self) { - int ret = tdb_transaction_cancel(self->ctx); + int ret; + + PyErr_TDB_RAISE_IF_CLOSED(self); + + ret = tdb_transaction_cancel(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_transaction_commit(PyTdbObject *self) { - int ret = tdb_transaction_commit(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_commit(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_transaction_prepare_commit(PyTdbObject *self) { - int ret = tdb_transaction_prepare_commit(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_prepare_commit(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_transaction_start(PyTdbObject *self) { - int ret = tdb_transaction_start(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_transaction_start(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_reopen(PyTdbObject *self) { - int ret = tdb_reopen(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_reopen(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_lockall(PyTdbObject *self) { - int ret = tdb_lockall(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_lockall(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_unlockall(PyTdbObject *self) { - int ret = tdb_unlockall(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_unlockall(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_lockall_read(PyTdbObject *self) { - int ret = tdb_lockall_read(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_lockall_read(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } @@ -185,6 +217,9 @@ static PyObject *obj_get(PyTdbObject *self, PyObject *args) { TDB_DATA key; PyObject *py_key; + + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "O", &py_key)) return NULL; @@ -200,6 +235,9 @@ static PyObject *obj_append(PyTdbObject *self, PyObject *args) TDB_DATA key, data; PyObject *py_key, *py_data; int ret; + + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "OO", &py_key, &py_data)) return NULL; @@ -217,6 +255,8 @@ static PyObject *obj_append(PyTdbObject *self, PyObject *args) static PyObject *obj_firstkey(PyTdbObject *self) { + PyErr_TDB_RAISE_IF_CLOSED(self); + return PyString_FromTDB_DATA(tdb_firstkey(self->ctx)); } @@ -224,6 +264,8 @@ static PyObject *obj_nextkey(PyTdbObject *self, PyObject *args) { TDB_DATA key; PyObject *py_key; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "O", &py_key)) return NULL; @@ -239,6 +281,8 @@ static PyObject *obj_delete(PyTdbObject *self, PyObject *args) TDB_DATA key; PyObject *py_key; int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "O", &py_key)) return NULL; @@ -255,6 +299,8 @@ static PyObject *obj_has_key(PyTdbObject *self, PyObject *args) TDB_DATA key; int ret; PyObject *py_key; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "O", &py_key)) return NULL; @@ -276,6 +322,8 @@ static PyObject *obj_store(PyTdbObject *self, PyObject *args) int flag = TDB_REPLACE; PyObject *py_key, *py_value; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "OO|i", &py_key, &py_value, &flag)) return NULL; @@ -295,6 +343,8 @@ static PyObject *obj_add_flags(PyTdbObject *self, PyObject *args) { unsigned flags; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "I", &flags)) return NULL; @@ -306,6 +356,8 @@ static PyObject *obj_remove_flags(PyTdbObject *self, PyObject *args) { unsigned flags; + PyErr_TDB_RAISE_IF_CLOSED(self); + if (!PyArg_ParseTuple(args, "I", &flags)) return NULL; @@ -350,6 +402,8 @@ static PyObject *tdb_object_iter(PyTdbObject *self) { PyTdbIteratorObject *ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = PyObject_New(PyTdbIteratorObject, &PyTdbIterator); if (!ret) return NULL; @@ -361,26 +415,32 @@ static PyObject *tdb_object_iter(PyTdbObject *self) static PyObject *obj_clear(PyTdbObject *self) { - int ret = tdb_wipe_all(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_wipe_all(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_repack(PyTdbObject *self) { - int ret = tdb_repack(self->ctx); + int ret; + PyErr_TDB_RAISE_IF_CLOSED(self); + ret = tdb_repack(self->ctx); PyErr_TDB_ERROR_IS_ERR_RAISE(ret, self->ctx); Py_RETURN_NONE; } static PyObject *obj_enable_seqnum(PyTdbObject *self) { + PyErr_TDB_RAISE_IF_CLOSED(self); tdb_enable_seqnum(self->ctx); Py_RETURN_NONE; } static PyObject *obj_increment_seqnum_nonblock(PyTdbObject *self) { + PyErr_TDB_RAISE_IF_CLOSED(self); tdb_increment_seqnum_nonblock(self->ctx); Py_RETURN_NONE; } @@ -434,11 +494,13 @@ static PyMethodDef tdb_object_methods[] = { static PyObject *obj_get_hash_size(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyInt_FromLong(tdb_hash_size(self->ctx)); } static int obj_set_max_dead(PyTdbObject *self, PyObject *max_dead, void *closure) { + PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self); if (!PyInt_Check(max_dead)) return -1; tdb_set_max_dead(self->ctx, PyInt_AsLong(max_dead)); @@ -447,26 +509,31 @@ static int obj_set_max_dead(PyTdbObject *self, PyObject *max_dead, void *closure static PyObject *obj_get_map_size(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyInt_FromLong(tdb_map_size(self->ctx)); } static PyObject *obj_get_freelist_size(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyInt_FromLong(tdb_freelist_size(self->ctx)); } static PyObject *obj_get_flags(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyInt_FromLong(tdb_get_flags(self->ctx)); } static PyObject *obj_get_filename(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyString_FromString(tdb_name(self->ctx)); } static PyObject *obj_get_seqnum(PyTdbObject *self, void *closure) { + PyErr_TDB_RAISE_IF_CLOSED(self); return PyInt_FromLong(tdb_get_seqnum(self->ctx)); } @@ -484,6 +551,7 @@ static PyGetSetDef tdb_object_getsetters[] = { static PyObject *tdb_object_repr(PyTdbObject *self) { + PyErr_TDB_RAISE_IF_CLOSED(self); if (tdb_get_flags(self->ctx) & TDB_INTERNAL) { return PyString_FromString("Tdb(<internal>)"); } else { @@ -501,6 +569,7 @@ static void tdb_object_dealloc(PyTdbObject *self) static PyObject *obj_getitem(PyTdbObject *self, PyObject *key) { TDB_DATA tkey, val; + PyErr_TDB_RAISE_IF_CLOSED(self); if (!PyString_Check(key)) { PyErr_SetString(PyExc_TypeError, "Expected string as key"); return NULL; @@ -522,6 +591,7 @@ static int obj_setitem(PyTdbObject *self, PyObject *key, PyObject *value) { TDB_DATA tkey, tval; int ret; + PyErr_TDB_RAISE_RETURN_MINUS_1_IF_CLOSED(self); if (!PyString_Check(key)) { PyErr_SetString(PyExc_TypeError, "Expected string as key"); return -1; diff --git a/lib/tdb/python/tests/simple.py b/lib/tdb/python/tests/simple.py index c37ef83a61..7e295a8c95 100644 --- a/lib/tdb/python/tests/simple.py +++ b/lib/tdb/python/tests/simple.py @@ -33,6 +33,11 @@ class CloseTdbTests(TestCase): self.tdb.close() self.tdb.close() + # Check that further operations do not crash python + self.assertRaises(RuntimeError, lambda: self.tdb.transaction_start()) + + self.assertRaises(RuntimeError, lambda: self.tdb["bar"]) + class InternalTdbTests(TestCase): |