summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 */