As it gets 'messaging_context' as argument, we're sure a messaging context
with a raw tevent context already exist.
It means we can allow a wrapper tevent context that wrapps the main tevent
context of the messaging context.
The use of tevent_req_defer_callback() makes sure that the callers
callback function calls messaging_filtered_read_recv() from the
correct "wrapped" environment.
Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
+ if (tevent_context_same_loop(reg->ev, ev)) {
reg->refcount += 1;
return true;
}
reg->refcount += 1;
return true;
}
+ if (tevent_context_same_loop(reg->ev, ev)) {
reg->refcount -= 1;
if (reg->refcount == 0) {
reg->refcount -= 1;
if (reg->refcount == 0) {
state->filter = filter;
state->private_data = private_data;
state->filter = filter;
state->private_data = private_data;
- if (tevent_context_is_wrapper(ev)) {
+ if (tevent_context_is_wrapper(ev) &&
+ !tevent_context_same_loop(ev, msg_ctx->event_ctx))
+ {
/* This is really a programmer error! */
DBG_ERR("Wrapper tevent context doesn't use main context.\n");
tevent_req_error(req, EINVAL);
/* This is really a programmer error! */
DBG_ERR("Wrapper tevent context doesn't use main context.\n");
tevent_req_error(req, EINVAL);
/*
* We have to defer the callback here, as we might be called from
/*
* We have to defer the callback here, as we might be called from
- * within a different tevent_context than state->ev
+ * within a different tevent_context than state->ev.
+ *
+ * This is important for two cases:
+ * 1. nested event contexts, used by blocking ctdb calls
+ * 2. possible impersonation using wrapper tevent contexts.
*/
tevent_req_defer_callback(req, state->ev);
*/
tevent_req_defer_callback(req, state->ev);
state = tevent_req_data(
req, struct messaging_filtered_read_state);
state = tevent_req_data(
req, struct messaging_filtered_read_state);
- if ((ev == state->ev) &&
+ if (tevent_context_same_loop(ev, state->ev) &&
state->filter(rec, state->private_data)) {
messaging_filtered_read_done(req, rec);
return true;
state->filter(rec, state->private_data)) {
messaging_filtered_read_done(req, rec);
return true;