summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRonnie Sahlberg <ronniesahlberg@gmail.com>2012-02-22 17:38:12 +1100
committerRonnie Sahlberg <ronniesahlberg@gmail.com>2012-02-23 06:49:47 +1100
commit93ec9c589c55edfed1a04ceb2217108ceb690089 (patch)
treecdd698566d7c6e783cfe0bb93e5373a429de08a4
parent94b7a84cb118b0139c29bc247ead43c25ec60415 (diff)
downloadsamba-93ec9c589c55edfed1a04ceb2217108ceb690089.tar.gz
samba-93ec9c589c55edfed1a04ceb2217108ceb690089.tar.xz
samba-93ec9c589c55edfed1a04ceb2217108ceb690089.zip
Eventscripts: remove the horrible horrible circular reference between state and callback since these two structures do not even share the same parent talloc context.
Instead, tie them together via referencing a permanent linked list hung off the ctdb structure. (This used to be ctdb commit a95c02da6c67dc4bd8716b75318a4188301df6f9)
-rw-r--r--ctdb/include/ctdb_private.h3
-rw-r--r--ctdb/server/eventscript.c26
2 files changed, 22 insertions, 7 deletions
diff --git a/ctdb/include/ctdb_private.h b/ctdb/include/ctdb_private.h
index 272b94aa86..4b7e67580f 100644
--- a/ctdb/include/ctdb_private.h
+++ b/ctdb/include/ctdb_private.h
@@ -486,6 +486,9 @@ struct ctdb_context {
/* if we are a child process, do we have a domain socket to send controls on */
bool can_send_controls;
+
+ /* list of event script callback functions that are active */
+ struct event_script_callback *script_callbacks;
};
struct ctdb_db_context {
diff --git a/ctdb/server/eventscript.c b/ctdb/server/eventscript.c
index 722ebec6a9..146da9d1ec 100644
--- a/ctdb/server/eventscript.c
+++ b/ctdb/server/eventscript.c
@@ -26,6 +26,7 @@
#include "../include/ctdb_private.h"
#include "lib/tevent/tevent.h"
#include "../common/rb_tree.h"
+#include "lib/util/dlinklist.h"
static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
@@ -41,7 +42,8 @@ static void sigterm(int sig)
/* This is attached to the event script state. */
struct event_script_callback {
- struct ctdb_event_script_state *state;
+ struct event_script_callback *next, *prev;
+ struct ctdb_context *ctdb;
/* Warning: this can free us! */
void (*fn)(struct ctdb_context *, int, void *);
@@ -611,8 +613,18 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
}
/* This is allowed to free us; talloc will prevent double free anyway,
- * but beware if you call this outside the destructor! */
- callback = state->callback;
+ * but beware if you call this outside the destructor!
+ * the callback hangs off a different context so we walk the list
+ * of "active" callbacks until we find the one state points to.
+ * if we cant find it it means the callback has been removed.
+ */
+ for (callback = state->ctdb->script_callbacks; callback != NULL; callback = callback->next) {
+ if (callback == state->callback) {
+ break;
+ }
+ }
+
+ state->callback = NULL;
if (callback) {
/* Make sure destructor doesn't free itself! */
@@ -669,8 +681,7 @@ static bool check_options(enum ctdb_eventscript_call call, const char *options)
static int remove_callback(struct event_script_callback *callback)
{
- /* Detach ourselves from the running script state */
- callback->state->callback = NULL;
+ DLIST_REMOVE(callback->ctdb->script_callbacks, callback);
return 0;
}
@@ -694,9 +705,10 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
/* The callback isn't done if the context is freed. */
state->callback = talloc(mem_ctx, struct event_script_callback);
CTDB_NO_MEMORY(ctdb, state->callback);
+ DLIST_ADD(ctdb->script_callbacks, state->callback);
talloc_set_destructor(state->callback, remove_callback);
- state->callback->state = state;
- state->callback->fn = callback;
+ state->callback->ctdb = ctdb;
+ state->callback->fn = callback;
state->callback->private_data = private_data;
state->ctdb = ctdb;