summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2009-09-04 17:22:20 +1000
committerAndrew Tridgell <tridge@samba.org>2009-09-04 17:29:21 +1000
commit8995491f59e7b6cee79b4249424e886f54f6b94d (patch)
tree9d8d767702c6ae2ab4b4ad8ae361b82e14a5bf28 /source4
parent5121499816db70bf7bd380f604c22311be8fd3de (diff)
downloadsamba-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')
-rw-r--r--source4/lib/ldb/common/ldb_modules.c14
-rw-r--r--source4/lib/ldb/include/ldb_private.h3
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 */