for (i=0; i<num_event_contexts; i++) {
struct messaging_registered_ev *reg = &ctx->event_contexts[i];
- if (reg->ev == ev) {
- reg->refcount += 1;
- return true;
- }
if (reg->refcount == 0) {
if (reg->ev != NULL) {
abort();
}
free_reg = reg;
+ /*
+ * We continue here and may find another
+ * free_req, but the important thing is
+ * that we continue to search for an
+ * existing registration in the loop.
+ */
+ continue;
+ }
+
+ if (reg->ev == ev) {
+ reg->refcount += 1;
+ return true;
}
}
if (free_reg == NULL) {
+ struct tevent_immediate *im = NULL;
+
+ im = tevent_create_immediate(ctx);
+ if (im == NULL) {
+ return false;
+ }
+
tmp = talloc_realloc(ctx, ctx->event_contexts,
struct messaging_registered_ev,
num_event_contexts+1);
ctx->event_contexts = tmp;
free_reg = &ctx->event_contexts[num_event_contexts];
+ free_reg->im = talloc_move(ctx->event_contexts, &im);
}
- *free_reg = (struct messaging_registered_ev) { .ev = ev, .refcount = 1 };
+ /*
+ * free_reg->im might be cached
+ */
+ free_reg->ev = ev;
+ free_reg->refcount = 1;
return true;
}
for (i=0; i<num_event_contexts; i++) {
struct messaging_registered_ev *reg = &ctx->event_contexts[i];
+ if (reg->refcount == 0) {
+ continue;
+ }
+
if (reg->ev == ev) {
- if (reg->refcount == 0) {
- return false;
- }
reg->refcount -= 1;
if (reg->refcount == 0) {
+ /*
+ * The primary event context
+ * is never unregistered using
+ * messaging_deregister_event_context()
+ * it's only registered using
+ * messaging_register_event_context().
+ */
+ SMB_ASSERT(ev != ctx->event_ctx);
+ SMB_ASSERT(reg->ev != ctx->event_ctx);
+
/*
* Not strictly necessary, just
* paranoia
/*
* Do not talloc_free(reg->im),
* recycle immediates events.
+ *
+ * We just invalidate it using
+ * the primary event context,
+ * which is never unregistered.
*/
+ tevent_schedule_immediate(reg->im,
+ ctx->event_ctx,
+ NULL, NULL);
}
return true;
}
continue;
}
- if (reg->im == NULL) {
- reg->im = tevent_create_immediate(
- ctx->event_contexts);
- }
- if (reg->im == NULL) {
- DBG_WARNING("Could not create immediate\n");
- continue;
- }
-
/*
* We depend on schedule_immediate to work
* multiple times. Might be a bit inefficient,
* alternatively would be to track whether the
* immediate has already been scheduled. For
* now, avoid that complexity here.
+ *
+ * reg->ev and ctx->event_ctx can't
+ * be wrapper tevent_context pointers
+ * so we don't need to use
+ * tevent_context_same_loop().
*/
if (reg->ev == ctx->event_ctx) {
(unsigned)rec.msg_type, rec.buf.length, num_fds,
server_id_str_buf(rec.src, &idbuf));
+ if (server_id_same_process(&rec.src, &msg_ctx->id)) {
+ DBG_DEBUG("Ignoring self-send\n");
+ goto close_fail;
+ }
+
messaging_dispatch_rec(msg_ctx, ev, &rec);
return;
const char *priv_path;
bool ok;
- lck_path = lock_path("msg.lock");
+ /*
+ * sec_init() *must* be called before any other
+ * functions that use sec_XXX(). e.g. sec_initial_uid().
+ */
+
+ sec_init();
+
+ if (tevent_context_is_wrapper(ev)) {
+ /* This is really a programmer error! */
+ DBG_ERR("Should not be used with a wrapper tevent context\n");
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ lck_path = lock_path(talloc_tos(), "msg.lock");
if (lck_path == NULL) {
return NT_STATUS_NO_MEMORY;
}
goto done;
}
- sec_init();
-
ctx->msg_dgm_ref = messaging_dgm_ref(ctx,
ctx->event_ctx,
&ctx->id.unique_id,
return ctx;
}
-NTSTATUS messaging_init_client(TALLOC_CTX *mem_ctx,
- struct tevent_context *ev,
- struct messaging_context **pmsg_ctx)
-{
- return messaging_init_internal(mem_ctx,
- ev,
- pmsg_ctx);
-}
-
struct server_id messaging_server_id(const struct messaging_context *msg_ctx)
{
return msg_ctx->id;
.pid = getpid(), .vnn = msg_ctx->id.vnn
};
- lck_path = lock_path("msg.lock");
+ lck_path = lock_path(talloc_tos(), "msg.lock");
if (lck_path == NULL) {
return NT_STATUS_NO_MEMORY;
}
struct send_all_state *state = private_data;
NTSTATUS status;
+ if (pid == getpid()) {
+ DBG_DEBUG("Skip ourselves in messaging_send_all\n");
+ return 0;
+ }
+
status = messaging_send_buf(state->msg_ctx, pid_to_procid(pid),
state->msg_type, state->buf, state->len);
if (!NT_STATUS_IS_OK(status)) {
state->filter = filter;
state->private_data = private_data;
+ if (tevent_context_is_wrapper(ev)) {
+ /* This is really a programmer error! */
+ DBG_ERR("Wrapper tevent context doesn't use main context.\n");
+ tevent_req_error(req, EINVAL);
+ return tevent_req_post(req, ev);
+ }
+
/*
* We have to defer the callback here, as we might be called from
* within a different tevent_context than state->ev
bool consumed;
size_t i;
+ /*
+ * ev and msg_ctx->event_ctx can't be wrapper tevent_context pointers
+ * so we don't need to use tevent_context_same_loop().
+ */
+
if (ev == msg_ctx->event_ctx) {
consumed = messaging_dispatch_classic(msg_ctx, rec);
if (consumed) {