change the eventscript handling to allow EventScriptTimeout for each individual scrip...
authorRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 28 Oct 2009 05:11:54 +0000 (16:11 +1100)
committerRonnie Sahlberg <ronniesahlberg@gmail.com>
Wed, 28 Oct 2009 05:11:54 +0000 (16:11 +1100)
restructure the talloc hierarchy to allow this

include/ctdb_private.h
server/ctdb_monitor.c
server/ctdb_recover.c
server/ctdb_takeover.c
server/eventscript.c

index e73913a2bf36549bc6f278258491f7c90dac24c4..7ee3db59d00576e84eef6969bda42619b34680b9 100644 (file)
@@ -450,8 +450,8 @@ struct ctdb_context {
        TALLOC_CTX *eventscripts_ctx; /* a context to hold data for the RUN_EVENTSCRIPTS control */
        uint32_t *recd_ping_count;
        TALLOC_CTX *release_ips_ctx; /* a context used to automatically drop all IPs if we fail to recover the node */
-       TALLOC_CTX *script_monitoring_ctx; /* a context where we store results while running the monitor event */
-       TALLOC_CTX *last_monitoring_ctx; 
+       TALLOC_CTX *script_monitor_ctx; /* a context where we store results while running the monitor event */
+       TALLOC_CTX *last_monitor_ctx; 
        TALLOC_CTX *banning_ctx;
 };
 
index f2d6d184add60aa8b0a0beddb15478c82e181fd0..efba8f9e14294dc2cc19e8cc3d4ba1eec239495f 100644 (file)
@@ -194,7 +194,7 @@ static void ctdb_startup_callback(struct ctdb_context *ctdb, int status, void *p
        } else if (status == 0) {
                DEBUG(DEBUG_NOTICE,("startup event OK - enabling monitoring\n"));
                ctdb->done_startup = true;
-               ctdb->monitor->next_interval = 1;
+               ctdb->monitor->next_interval = 5;
                ctdb_run_notification_script(ctdb, "startup");
        }
 
@@ -211,7 +211,7 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te,
                              struct timeval t, void *private_data)
 {
        struct ctdb_context *ctdb = talloc_get_type(private_data, struct ctdb_context);
-       int ret;
+       int ret = 0;
 
        if (ctdb->recovery_mode != CTDB_RECOVERY_NORMAL ||
            (ctdb->monitor->monitoring_mode == CTDB_MONITORING_DISABLED && ctdb->done_startup)) {
@@ -223,7 +223,7 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te,
        
        if (!ctdb->done_startup) {
                ret = ctdb_event_script_callback(ctdb, 
-                                                timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                                timeval_set(ctdb->tunable.script_timeout, 0),
                                                 ctdb->monitor->monitor_context, ctdb_startup_callback, 
                                                 ctdb, "startup");
        } else {
@@ -241,26 +241,26 @@ static void ctdb_check_health(struct event_context *ev, struct timed_event *te,
                                break;
                        }
                }
-               if (skip_monitoring) {
+               if (skip_monitoring != 0) {
                        event_add_timed(ctdb->ev, ctdb->monitor->monitor_context,
                                        timeval_current_ofs(ctdb->monitor->next_interval, 0), 
                                        ctdb_check_health, ctdb);
                        return;
                } else {
                        ret = ctdb_event_script_callback(ctdb, 
-                                                timeval_current_ofs(ctdb->tunable.script_timeout, 0),
-                                                ctdb->monitor->monitor_context, ctdb_health_callback, 
-                                                ctdb, "monitor");
+                                       timeval_set(ctdb->tunable.script_timeout, 0),
+                                       ctdb->monitor->monitor_context, ctdb_health_callback,
+                                       ctdb, "monitor");
                }
        }
 
        if (ret != 0) {
                DEBUG(DEBUG_ERR,("Unable to launch monitor event script\n"));
-               ctdb->monitor->next_interval = 1;
+               ctdb->monitor->next_interval = 5;
                event_add_timed(ctdb->ev, ctdb->monitor->monitor_context, 
-                               timeval_current_ofs(1, 0), 
-                               ctdb_check_health, ctdb);
-       }       
+                       timeval_current_ofs(5, 0), 
+                       ctdb_check_health, ctdb);
+       }
 }
 
 /* 
@@ -279,7 +279,7 @@ void ctdb_disable_monitoring(struct ctdb_context *ctdb)
 void ctdb_enable_monitoring(struct ctdb_context *ctdb)
 {
        ctdb->monitor->monitoring_mode  = CTDB_MONITORING_ACTIVE;
-       ctdb->monitor->next_interval = 2;
+       ctdb->monitor->next_interval = 5;
        DEBUG(DEBUG_INFO,("Monitoring has been enabled\n"));
 }
 
@@ -292,7 +292,7 @@ void ctdb_stop_monitoring(struct ctdb_context *ctdb)
        ctdb->monitor->monitor_context = NULL;
 
        ctdb->monitor->monitoring_mode  = CTDB_MONITORING_DISABLED;
-       ctdb->monitor->next_interval = 1;
+       ctdb->monitor->next_interval = 5;
        DEBUG(DEBUG_NOTICE,("Monitoring has been stopped\n"));
 }
 
@@ -310,7 +310,7 @@ void ctdb_start_monitoring(struct ctdb_context *ctdb)
        ctdb->monitor = talloc(ctdb, struct ctdb_monitor_state);
        CTDB_NO_MEMORY_FATAL(ctdb, ctdb->monitor);
 
-       ctdb->monitor->next_interval = 1;
+       ctdb->monitor->next_interval = 5;
 
        ctdb->monitor->monitor_context = talloc_new(ctdb->monitor);
        CTDB_NO_MEMORY_FATAL(ctdb, ctdb->monitor->monitor_context);
index 862168e97eab2c778d1eebc5592a2c5319cd5450..ccac8e62e6d723f9c6dfc9afd4501bd007e2e222 100644 (file)
@@ -963,7 +963,7 @@ int32_t ctdb_control_end_recovery(struct ctdb_context *ctdb,
        ctdb_disable_monitoring(ctdb);
 
        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         state, 
                                         ctdb_end_recovery_callback, 
                                         state, "recovered");
@@ -1017,7 +1017,7 @@ int32_t ctdb_control_start_recovery(struct ctdb_context *ctdb,
        ctdb_disable_monitoring(ctdb);
 
        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         state, 
                                         ctdb_start_recovery_callback, 
                                         state, "startrecovery");
@@ -1231,7 +1231,7 @@ int32_t ctdb_control_stop_node(struct ctdb_context *ctdb, struct ctdb_req_contro
        ctdb_disable_monitoring(ctdb);
 
        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         state, 
                                         ctdb_stop_node_callback, 
                                         state, "stopped");
index 559f7fbf166f82daa4b31009735e250c0bd2e9e1..a140578abed4633915090e43160e8e560d7cb750 100644 (file)
@@ -235,7 +235,7 @@ int32_t ctdb_control_takeover_ip(struct ctdb_context *ctdb,
                vnn->iface));
 
        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         state, takeover_ip_callback, state,
                                         "takeip %s %s %u",
                                         vnn->iface, 
@@ -391,7 +391,7 @@ int32_t ctdb_control_release_ip(struct ctdb_context *ctdb,
        state->vnn   = vnn;
 
        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         state, release_ip_callback, state,
                                         "releaseip %s %s %u",
                                         vnn->iface, 
@@ -2094,7 +2094,7 @@ int32_t ctdb_control_del_public_address(struct ctdb_context *ctdb, TDB_DATA inda
                        DLIST_REMOVE(ctdb->vnn, vnn);
 
                        ret = ctdb_event_script_callback(ctdb, 
-                                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                                        timeval_set(ctdb->tunable.script_timeout, 0),
                                         mem_ctx, delete_ip_callback, mem_ctx,
                                         "releaseip %s %s %u",
                                         vnn->iface, 
index 16cbaf86ce4402117e5dd3525505c1a7a75643cf..0fea281d500180f46e691dcc7037be55340a16d0 100644 (file)
@@ -32,6 +32,8 @@ static struct {
        const char *script_running;
 } child_state;
 
+static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te, struct timeval t, void *p);
+
 /*
   ctdbd sends us a SIGTERM when we should time out the current script
  */
@@ -63,6 +65,8 @@ struct ctdb_event_script_state {
        int fd[2];
        void *private_data;
        const char *options;
+        struct timed_event *te;
+       struct timeval timeout;
 };
 
 
@@ -77,11 +81,12 @@ struct ctdb_monitor_script_status {
        char *output;
 };
 
-struct ctdb_monitoring_status {
+struct ctdb_monitor_status {
        struct timeval start;
        struct timeval finished;
        int32_t status;
        struct ctdb_monitor_script_status *scripts;
+       struct ctdb_event_script_state *state;
 };
 
 
@@ -90,9 +95,7 @@ struct ctdb_monitoring_status {
  */
 int ctdb_log_event_script_output(struct ctdb_context *ctdb, char *str, uint16_t len)
 {
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
        struct ctdb_monitor_script_status *script;
 
        if (monitoring_status == NULL) {
@@ -118,21 +121,15 @@ int ctdb_log_event_script_output(struct ctdb_context *ctdb, char *str, uint16_t
  */
 int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb)
 {
-       struct ctdb_monitoring_status *monitoring_status;
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
 
        DEBUG(DEBUG_INFO, ("event script init called\n"));
-       if (ctdb->script_monitoring_ctx != NULL) {
-               talloc_free(ctdb->script_monitoring_ctx);
-               ctdb->script_monitoring_ctx = NULL;
-       }
 
-       monitoring_status = talloc_zero(ctdb, struct ctdb_monitoring_status);
        if (monitoring_status == NULL) {
-               DEBUG(DEBUG_ERR, (__location__ " ERROR: Failed to talloc script_monitoring context\n"));
-               return -1;
+               DEBUG(DEBUG_ERR,(__location__ " Init called when context is NULL\n"));
+               return 0;
        }
 
-       ctdb->script_monitoring_ctx = monitoring_status;
        monitoring_status->start = timeval_current();   
 
        return 0;
@@ -145,9 +142,8 @@ int32_t ctdb_control_event_script_init(struct ctdb_context *ctdb)
 int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA indata)
 {
        const char *name = (const char *)indata.dptr;
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
+       struct ctdb_event_script_state *state;
        struct ctdb_monitor_script_status *script;
 
        DEBUG(DEBUG_INFO, ("event script start called : %s\n", name));
@@ -169,6 +165,19 @@ int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA inda
        script->start = timeval_current();
        monitoring_status->scripts = script;
 
+       state = monitoring_status->state;
+       if (state != NULL) {
+               /* reset the timeout for the next eventscript */
+               if (!timeval_is_zero(&state->timeout)) {
+                       if (state->te != NULL) {
+                               talloc_free(state->te);
+                               state->te = NULL;
+                       }
+                       state->te = event_add_timed(ctdb->ev, state, timeval_current_ofs(state->timeout.tv_sec, state->timeout.tv_usec), ctdb_event_script_timeout, state);
+               }
+
+       }
+
        return 0;
 }
 
@@ -178,9 +187,7 @@ int32_t ctdb_control_event_script_start(struct ctdb_context *ctdb, TDB_DATA inda
 int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indata)
 {
        int32_t res = *((int32_t *)indata.dptr);
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
        struct ctdb_monitor_script_status *script;
 
        if (monitoring_status == NULL) {
@@ -207,9 +214,7 @@ int32_t ctdb_control_event_script_stop(struct ctdb_context *ctdb, TDB_DATA indat
 int32_t ctdb_control_event_script_disabled(struct ctdb_context *ctdb, TDB_DATA indata)
 {
        const char *name = (const char *)indata.dptr;
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
        struct ctdb_monitor_script_status *script;
 
        DEBUG(DEBUG_INFO, ("event script disabed called for script %s\n", name));
@@ -237,9 +242,7 @@ int32_t ctdb_control_event_script_disabled(struct ctdb_context *ctdb, TDB_DATA i
  */
 int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb)
 {
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
 
        DEBUG(DEBUG_INFO, ("event script finished called\n"));
 
@@ -250,11 +253,13 @@ int32_t ctdb_control_event_script_finished(struct ctdb_context *ctdb)
 
        monitoring_status->finished = timeval_current();        
        monitoring_status->status   = MONITOR_SCRIPT_OK;
-       if (ctdb->last_monitoring_ctx) {
-               talloc_free(ctdb->last_monitoring_ctx);
+
+       if (ctdb->last_monitor_ctx) {
+               talloc_free(ctdb->last_monitor_ctx);
+               ctdb->last_monitor_ctx = NULL;
        }
-       ctdb->last_monitoring_ctx = ctdb->script_monitoring_ctx;
-       ctdb->script_monitoring_ctx = NULL;
+       ctdb->last_monitor_ctx = talloc_steal(ctdb, ctdb->script_monitor_ctx);
+       ctdb->script_monitor_ctx = NULL;
 
        return 0;
 }
@@ -298,9 +303,7 @@ static struct ctdb_monitoring_wire *marshall_monitoring_scripts(TALLOC_CTX *mem_
 
 int32_t ctdb_control_get_event_script_status(struct ctdb_context *ctdb, TDB_DATA *outdata)
 {
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->last_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->last_monitor_ctx;
        struct ctdb_monitoring_wire *monitoring_scripts;
 
        if (monitoring_status == NULL) {
@@ -627,8 +630,6 @@ static void ctdb_event_script_handler(struct event_context *ev, struct fd_event
 {
        struct ctdb_event_script_state *state = 
                talloc_get_type(p, struct ctdb_event_script_state);
-       void (*callback)(struct ctdb_context *, int, void *) = state->callback;
-       void *private_data = state->private_data;
        struct ctdb_context *ctdb = state->ctdb;
        signed char rt = -1;
 
@@ -636,10 +637,13 @@ static void ctdb_event_script_handler(struct event_context *ev, struct fd_event
 
        DEBUG(DEBUG_INFO,(__location__ " Eventscript %s finished with state %d\n", state->options, rt));
 
+       if (state->callback) {
+               state->callback(ctdb, rt, state->private_data);
+               state->callback = NULL;
+       }
+
        talloc_set_destructor(state, NULL);
        talloc_free(state);
-       callback(ctdb, rt, private_data);
-
        ctdb->event_script_timeouts = 0;
 }
 
@@ -663,19 +667,20 @@ static void ctdb_event_script_timeout(struct event_context *ev, struct timed_eve
                                      struct timeval t, void *p)
 {
        struct ctdb_event_script_state *state = talloc_get_type(p, struct ctdb_event_script_state);
-       void (*callback)(struct ctdb_context *, int, void *) = state->callback;
        void *private_data = state->private_data;
        struct ctdb_context *ctdb = state->ctdb;
        char *options;
-       struct ctdb_monitoring_status *monitoring_status =
-               talloc_get_type(ctdb->script_monitoring_ctx,
-                       struct ctdb_monitoring_status);
+       struct ctdb_monitor_status *monitoring_status = (struct ctdb_monitor_status *)ctdb->script_monitor_ctx;
+
+       state->te = NULL;
 
        DEBUG(DEBUG_ERR,("Event script timed out : %s count : %u  pid : %d\n", state->options, ctdb->event_script_timeouts, state->child));
        if (kill(state->child, 0) != 0) {
                DEBUG(DEBUG_ERR,("Event script child process already dead, errno %s(%d)\n", strerror(errno), errno));
-               callback(ctdb, 0, private_data);
-
+               if (state->callback) {
+                       state->callback(ctdb, 0, private_data);
+                       state->callback = NULL;
+               }
                talloc_set_destructor(state, NULL);
                talloc_free(state);
                return;
@@ -696,24 +701,39 @@ static void ctdb_event_script_timeout(struct event_context *ev, struct timed_eve
                if (ctdb->event_script_timeouts > ctdb->tunable.script_ban_count) {
                        if (ctdb->tunable.script_unhealthy_on_timeout != 0) {
                                DEBUG(DEBUG_ERR, ("Maximum timeout count %u reached for eventscript. Making node unhealthy\n", ctdb->tunable.script_ban_count));
-                               callback(ctdb, -ETIME, private_data);
+                               if (state->callback) {
+                                       state->callback(ctdb, -ETIME, private_data);
+                                       state->callback = NULL;
+                               }
                        } else {
                                ctdb->event_script_timeouts = 0;
                                DEBUG(DEBUG_ERR, ("Maximum timeout count %u reached for eventscript. Banning self for %d seconds\n", ctdb->tunable.script_ban_count, ctdb->tunable.recovery_ban_period));
                                ctdb_ban_self(ctdb, ctdb->tunable.recovery_ban_period);
-                               callback(ctdb, -1, private_data);
+                               if (state->callback) {
+                                       state->callback(ctdb, -1, private_data);
+                                       state->callback = NULL;
+                               }
                        }
                } else {
-                       callback(ctdb, 0, private_data);
+                       if (state->callback) {
+                               state->callback(ctdb, 0, private_data);
+                               state->callback = NULL;
+                       }
                }
        } else if (!strcmp(options, "startup")) {
                DEBUG(DEBUG_ERR, (__location__ " eventscript for startup event timedout.\n"));
-               callback(ctdb, -1, private_data);
+               if (state->callback) {
+                       state->callback(ctdb, -1, private_data);
+                       state->callback = NULL;
+               }
        } else {
                /* if it is not a monitor event we ban ourself immediately */
                DEBUG(DEBUG_ERR, (__location__ " eventscript for NON-monitor/NON-startup event timedout. Immediately banning ourself for %d seconds\n", ctdb->tunable.recovery_ban_period));
                ctdb_ban_self(ctdb, ctdb->tunable.recovery_ban_period);
-               callback(ctdb, -1, private_data);
+               if (state->callback) {
+                       state->callback(ctdb, -1, private_data);
+                       state->callback = NULL;
+               }
        }
 
        if (monitoring_status != NULL) {
@@ -724,11 +744,12 @@ static void ctdb_event_script_timeout(struct event_context *ev, struct timed_eve
                        script->timedout = 1;
                }
                monitoring_status->status = MONITOR_SCRIPT_TIMEOUT;
-               if (ctdb->last_monitoring_ctx) {
-                       talloc_free(ctdb->last_monitoring_ctx);
-                       ctdb->last_monitoring_ctx = ctdb->script_monitoring_ctx;
-                       ctdb->script_monitoring_ctx = NULL;
+               if (ctdb->last_monitor_ctx) {
+                       talloc_free(ctdb->last_monitor_ctx);
+                       ctdb->last_monitor_ctx = NULL;
                }
+               ctdb->last_monitor_ctx = talloc_steal(ctdb, ctdb->script_monitor_ctx);
+               ctdb->script_monitor_ctx = NULL;
        }
 
        talloc_free(options);
@@ -741,6 +762,11 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
 {
        DEBUG(DEBUG_ERR,(__location__ " Sending SIGTERM to child pid:%d\n", state->child));
 
+       if (state->callback) {
+               state->callback(state->ctdb, -1, state->private_data);
+               state->callback = NULL;
+       }
+
        if (kill(state->child, SIGTERM) != 0) {
                DEBUG(DEBUG_ERR,("Failed to kill child process for eventscript, errno %s(%d)\n", strerror(errno), errno));
        }
@@ -754,28 +780,49 @@ static int event_script_destructor(struct ctdb_event_script_state *state)
  */
 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb, 
                                        struct timeval timeout,
-                                       TALLOC_CTX *mem_ctx,
                                        void (*callback)(struct ctdb_context *, int, void *),
                                        void *private_data,
                                        const char *fmt, va_list ap)
 {
+       struct ctdb_monitor_status *monitoring_status;
        struct ctdb_event_script_state *state;
        int ret;
 
-       state = talloc(mem_ctx, struct ctdb_event_script_state);
-       CTDB_NO_MEMORY(ctdb, state);
+       if (ctdb->script_monitor_ctx != NULL) {
+               talloc_free(ctdb->script_monitor_ctx);
+               ctdb->script_monitor_ctx = NULL;
+       }
+       monitoring_status = talloc_zero(ctdb, struct ctdb_monitor_status);
+       if (monitoring_status == NULL) {
+               DEBUG(DEBUG_ERR, (__location__ " ERROR: Failed to talloc script_monitoring context\n"));
+               return -1;
+       }
+
+       state = talloc(monitoring_status, struct ctdb_event_script_state);
+       if (state == NULL) {
+               DEBUG(DEBUG_ERR,(__location__ " could not allocate state\n"));
+               talloc_free(monitoring_status);
+               return -1;
+       }
+       monitoring_status->state = state;
 
        state->ctdb = ctdb;
        state->callback = callback;
        state->private_data = private_data;
        state->options = talloc_vasprintf(state, fmt, ap);
-       CTDB_NO_MEMORY(ctdb, state->options);
+       state->timeout = timeout;
+       state->te = NULL;
+       if (state->options == NULL) {
+               DEBUG(DEBUG_ERR, (__location__ " could not allocate state->options\n"));
+               talloc_free(monitoring_status);
+               return -1;
+       }
 
        DEBUG(DEBUG_INFO,(__location__ " Starting eventscript %s\n", state->options));
        
        ret = pipe(state->fd);
        if (ret != 0) {
-               talloc_free(state);
+               talloc_free(monitoring_status);
                return -1;
        }
 
@@ -784,7 +831,7 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
        if (state->child == (pid_t)-1) {
                close(state->fd[0]);
                close(state->fd[1]);
-               talloc_free(state);
+               talloc_free(monitoring_status);
                return -1;
        }
 
@@ -803,6 +850,7 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
        }
 
        talloc_set_destructor(state, event_script_destructor);
+       ctdb->script_monitor_ctx = monitoring_status;
 
        close(state->fd[1]);
        set_close_on_exec(state->fd[0]);
@@ -812,8 +860,8 @@ static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
        event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
                     ctdb_event_script_handler, state);
 
-       if (!timeval_is_zero(&timeout)) {
-               event_add_timed(ctdb->ev, state, timeout, ctdb_event_script_timeout, state);
+       if (!timeval_is_zero(&state->timeout)) {
+               state->te = event_add_timed(ctdb->ev, state, timeval_current_ofs(state->timeout.tv_sec, state->timeout.tv_usec), ctdb_event_script_timeout, state);
        } else {
                DEBUG(DEBUG_ERR, (__location__ " eventscript %s called with no timeout\n", state->options));
        }
@@ -837,7 +885,7 @@ int ctdb_event_script_callback(struct ctdb_context *ctdb,
        int ret;
 
        va_start(ap, fmt);
-       ret = ctdb_event_script_callback_v(ctdb, timeout, mem_ctx, callback, private_data, fmt, ap);
+       ret = ctdb_event_script_callback_v(ctdb, timeout, callback, private_data, fmt, ap);
        va_end(ap);
 
        return ret;
@@ -867,17 +915,15 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
 {
        va_list ap;
        int ret;
-       TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
        struct callback_status status;
 
        va_start(ap, fmt);
        ret = ctdb_event_script_callback_v(ctdb, 
-                       timeval_current_ofs(ctdb->tunable.script_timeout, 0),
-                       tmp_ctx, event_script_callback, &status, fmt, ap);
+                       timeval_set(ctdb->tunable.script_timeout, 0),
+                       event_script_callback, &status, fmt, ap);
        va_end(ap);
 
        if (ret != 0) {
-               talloc_free(tmp_ctx);
                return ret;
        }
 
@@ -886,8 +932,6 @@ int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
 
        while (status.done == false && event_loop_once(ctdb->ev) == 0) /* noop */;
 
-       talloc_free(tmp_ctx);
-
        return status.status;
 }
 
@@ -952,7 +996,7 @@ int32_t ctdb_run_eventscripts(struct ctdb_context *ctdb,
        ctdb_disable_monitoring(ctdb);
 
        ret = ctdb_event_script_callback(ctdb, 
-                        timeval_current_ofs(ctdb->tunable.script_timeout, 0),
+                        timeval_set(ctdb->tunable.script_timeout, 0),
                         state, run_eventscripts_callback, state,
                         "%s", (const char *)indata.dptr);