diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-09-04 17:22:20 +1000 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-09-04 17:29:21 +1000 |
commit | 8995491f59e7b6cee79b4249424e886f54f6b94d (patch) | |
tree | 9d8d767702c6ae2ab4b4ad8ae361b82e14a5bf28 /source4/lib/ldb | |
parent | 5121499816db70bf7bd380f604c22311be8fd3de (diff) | |
download | samba-8995491f59e7b6cee79b4249424e886f54f6b94d.tar.gz samba-8995491f59e7b6cee79b4249424e886f54f6b94d.tar.bz2 samba-8995491f59e7b6cee79b4249424e886f54f6b94d.zip |
ldb: make ldb module programming less error prone
When a top level method in a module returns an error, it is supposed
to call ldb_module_done(). We ran across a case where this wasn't
done, and then found that in fact that are hundreds of similar cases
in our modules. It took Andrew and I a full day to work out that this
was the cause of a subtle segv in another part of the code.
To try to prevent this happening again, this patch changes
ldb_next_request() to catch the error by checking if a module
returning an error has called ldb_module_done(). If it hasn't then the
call is made on behalf of the module.
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r-- | source4/lib/ldb/common/ldb_modules.c | 14 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb_private.h | 3 |
2 files changed, 17 insertions, 0 deletions
diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index b792daa913..79a97cabed 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -577,6 +577,17 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request) /* Set a default error string, to place the blame somewhere */ ldb_asprintf_errstring(module->ldb, "error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret); } + + if (!(request->handle->flags & LDB_HANDLE_FLAG_DONE_CALLED)) { + /* It is _extremely_ common that a module returns a + * failure without calling ldb_module_done(), but that + * guarantees we will end up hanging in + * ldb_wait(). This fixes it without having to rewrite + * all our modules, and leaves us one less sharp + * corner for module developers to cut themselves on + */ + ldb_module_done(request, NULL, NULL, ret); + } return ret; } @@ -629,6 +640,7 @@ struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb) h->status = LDB_SUCCESS; h->state = LDB_ASYNC_INIT; h->ldb = ldb; + h->flags = 0; return h; } @@ -715,6 +727,8 @@ int ldb_module_done(struct ldb_request *req, ares->response = talloc_steal(ares, response); ares->error = error; + req->handle->flags |= LDB_HANDLE_FLAG_DONE_CALLED; + req->callback(req, ares); return error; } diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h index 3cda9a3e33..a70d9c704d 100644 --- a/source4/lib/ldb/include/ldb_private.h +++ b/source4/lib/ldb/include/ldb_private.h @@ -47,10 +47,13 @@ struct ldb_module_ops; struct ldb_backend_ops; +#define LDB_HANDLE_FLAG_DONE_CALLED 1 + struct ldb_handle { int status; enum ldb_state state; struct ldb_context *ldb; + unsigned flags; }; /* basic module structure */ |