[PATCH] Two messaging fixes
Volker Lendecke
Volker.Lendecke at SerNet.DE
Thu Oct 23 08:34:46 MDT 2014
Hi!
Hopefully the comments are descriptive enough. Proper
rundown of structures is hard...
Review&push would be appreciated.
Thanks,
Volker
--
SerNet GmbH, Bahnhofsallee 1b, 37081 Göttingen
phone: +49-551-370000-0, fax: +49-551-370000-9
AG Göttingen, HRB 2816, GF: Dr. Johannes Loxen
http://www.sernet.de, mailto:kontakt at sernet.de
-------------- next part --------------
From a70ecb341775eaa1e8cd6d647d76f4f297549d43 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 22 Oct 2014 15:02:49 +0000
Subject: [PATCH 1/2] poll_funcs_tevent: Fix a valgrind error
The valgrind error happened in poll_funcs_tevent_handle_destructor in
if (handle->ctx->refcount == 0)
handle->ctx was already gone at the time this destructor
was called. It happened because during messaging_init the
messaging_dgm subsystem was free'ed. The unix_msg context and the
poll_funcs_tevent_context are children of messaging_dgm_context. How
was poll_funcs_tevent_handle_destructor still called? While working
on the new notify subsystem I've added some messaging_read_send
tevent_reqs, which register themselves with the dgm_context via
messaging_dgm_register_tevent_context. They were not gone yet. When
later these were also run down due to another talloc_free somewhere else,
this destructor referenced dead memory.
This code now protects the poll_funcs_tevent_handle against the
poll_funcs_tevent_context going away first with the loop
for (h = ctx->handles; h != NULL; h = h->next) {
h->ctx = NULL;
}
in poll_funcs_tevent_context_destructor together with
if (handle->ctx == NULL) {
return 0;
}
in poll_funcs_tevent_handle_destructor.
A side-effect of this code is that messaging_read_send request won't be
satisfied anymore after a reinit_after_fork kicked in. But I think this is the
right thing anyway: Every process should register its own message handlers
explicitly.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/poll_funcs/poll_funcs_tevent.c | 28 ++++++++++++++++++++--------
1 file changed, 20 insertions(+), 8 deletions(-)
diff --git a/source3/lib/poll_funcs/poll_funcs_tevent.c b/source3/lib/poll_funcs/poll_funcs_tevent.c
index ee800ba..565cdaf 100644
--- a/source3/lib/poll_funcs/poll_funcs_tevent.c
+++ b/source3/lib/poll_funcs/poll_funcs_tevent.c
@@ -19,6 +19,7 @@
#include "poll_funcs_tevent.h"
#include "tevent.h"
#include "system/select.h"
+#include "dlinklist.h"
/*
* A poll_watch is asked for by the engine using this library via
@@ -53,7 +54,7 @@ struct poll_funcs_state {
};
struct poll_funcs_tevent_context {
- unsigned refcount;
+ struct poll_funcs_tevent_handle *handles;
struct poll_funcs_state *state;
unsigned slot; /* index into state->contexts[] */
struct tevent_context *ev;
@@ -67,6 +68,7 @@ struct poll_funcs_tevent_context {
* multiple times. So we have to share one poll_funcs_tevent_context.
*/
struct poll_funcs_tevent_handle {
+ struct poll_funcs_tevent_handle *prev, *next;
struct poll_funcs_tevent_context *ctx;
};
@@ -352,7 +354,7 @@ static struct poll_funcs_tevent_context *poll_funcs_tevent_context_new(
return NULL;
}
- ctx->refcount = 0;
+ ctx->handles = NULL;
ctx->state = state;
ctx->ev = ev;
ctx->slot = slot;
@@ -385,7 +387,14 @@ fail:
static int poll_funcs_tevent_context_destructor(
struct poll_funcs_tevent_context *ctx)
{
+ struct poll_funcs_tevent_handle *h;
+
ctx->state->contexts[ctx->slot] = NULL;
+
+ for (h = ctx->handles; h != NULL; h = h->next) {
+ h->ctx = NULL;
+ }
+
return 0;
}
@@ -427,7 +436,7 @@ void *poll_funcs_tevent_register(TALLOC_CTX *mem_ctx, struct poll_funcs *f,
}
handle->ctx = state->contexts[slot];
- handle->ctx->refcount += 1;
+ DLIST_ADD(handle->ctx->handles, handle);
talloc_set_destructor(handle, poll_funcs_tevent_handle_destructor);
return handle;
fail:
@@ -438,14 +447,17 @@ fail:
static int poll_funcs_tevent_handle_destructor(
struct poll_funcs_tevent_handle *handle)
{
- if (handle->ctx->refcount == 0) {
+ if (handle->ctx == NULL) {
+ return 0;
+ }
+ if (handle->ctx->handles == NULL) {
abort();
}
- handle->ctx->refcount -= 1;
- if (handle->ctx->refcount != 0) {
- return 0;
+ DLIST_REMOVE(handle->ctx->handles, handle);
+
+ if (handle->ctx->handles == NULL) {
+ TALLOC_FREE(handle->ctx);
}
- TALLOC_FREE(handle->ctx);
return 0;
}
--
1.7.9.5
From 1a3deedca31f0531c0f811b50f49bfa1325f81c7 Mon Sep 17 00:00:00 2001
From: Volker Lendecke <vl at samba.org>
Date: Wed, 22 Oct 2014 15:11:43 +0000
Subject: [PATCH 2/2] messaging3: Fix running down a messaging_context
When you do a talloc_free(msg_ctx), existing waiters can't and don't have to
clean up behind themselves properly anymore. The msg_ctx the cleanup function
refers to is just gone.
Signed-off-by: Volker Lendecke <vl at samba.org>
---
source3/lib/messages.c | 16 ++++++++++++++++
1 file changed, 16 insertions(+)
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index aaaee52..d4c580f 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -267,7 +267,23 @@ static void messaging_recv_cb(const uint8_t *msg, size_t msg_len,
static int messaging_context_destructor(struct messaging_context *ctx)
{
+ unsigned i;
+
messaging_dgm_destroy();
+
+ for (i=0; i<ctx->num_new_waiters; i++) {
+ if (ctx->new_waiters[i] != NULL) {
+ tevent_req_set_cleanup_fn(ctx->new_waiters[i], NULL);
+ ctx->new_waiters[i] = NULL;
+ }
+ }
+ for (i=0; i<ctx->num_waiters; i++) {
+ if (ctx->waiters[i] != NULL) {
+ tevent_req_set_cleanup_fn(ctx->waiters[i], NULL);
+ ctx->waiters[i] = NULL;
+ }
+ }
+
return 0;
}
--
1.7.9.5
More information about the samba-technical
mailing list