summaryrefslogtreecommitdiffstats
path: root/ctdb
diff options
context:
space:
mode:
authorAmitay Isaacs <amitay@gmail.com>2013-12-17 19:19:51 +1100
committerMartin Schwenke <martin@meltin.net>2014-01-16 12:11:37 +1100
commitd86662a925a072eb0374ad7743f4cf95c447bebb (patch)
tree994553dbbcb6cfe05ea7123eb706cfe4955f4761 /ctdb
parent69324b61f0669022c7204ee08a4c7104865d4e9b (diff)
downloadsamba-d86662a925a072eb0374ad7743f4cf95c447bebb.tar.gz
samba-d86662a925a072eb0374ad7743f4cf95c447bebb.tar.xz
samba-d86662a925a072eb0374ad7743f4cf95c447bebb.zip
ctdb-daemon: Replace ctdb_fork_with_logging with ctdb_vfork_with_logging (part 1)
Use ctdb_event_helper to run eventscripts. Signed-off-by: Amitay Isaacs <amitay@gmail.com> Reviewed-by: Martin Schwenke <martin@meltin.net>
Diffstat (limited to 'ctdb')
-rw-r--r--ctdb/server/eventscript.c110
1 files changed, 90 insertions, 20 deletions
diff --git a/ctdb/server/eventscript.c b/ctdb/server/eventscript.c
index 6140601022..2c5a612715 100644
--- a/ctdb/server/eventscript.c
+++ b/ctdb/server/eventscript.c
@@ -354,15 +354,91 @@ out:
return ret;
}
+/* There cannot be more than 10 arguments to command helper. */
+#define MAX_HELPER_ARGS (10)
+
+static bool child_helper_args(TALLOC_CTX *mem_ctx, struct ctdb_context *ctdb,
+ enum ctdb_eventscript_call call,
+ const char *options,
+ struct ctdb_script_wire *current, int fd,
+ int *argc, const char ***argv)
+{
+ const char **tmp;
+ int n, i;
+ char *t, *saveptr, *opt;
+
+ tmp = talloc_array(mem_ctx, const char *, 10+1);
+ if (tmp == NULL) goto failed;
+
+ tmp[0] = talloc_asprintf(tmp, "%d", fd);
+ tmp[1] = talloc_asprintf(tmp, "%s/%s", ctdb->event_script_dir, current->name);
+ tmp[2] = talloc_asprintf(tmp, "%s", ctdb_eventscript_call_names[call]);
+ n = 3;
+
+ /* Split options into individual arguments */
+ opt = talloc_strdup(mem_ctx, options);
+ if (opt == NULL) {
+ goto failed;
+ }
+
+ t = strtok_r(opt, " ", &saveptr);
+ while (t != NULL) {
+ tmp[n++] = talloc_strdup(tmp, t);
+ if (n > MAX_HELPER_ARGS) {
+ goto args_failed;
+ }
+ t = strtok_r(NULL, " ", &saveptr);
+ }
+
+ for (i=0; i<n; i++) {
+ if (tmp[i] == NULL) {
+ goto failed;
+ }
+ }
+
+ /* Last argument should be NULL */
+ tmp[n++] = NULL;
+
+ *argc = n;
+ *argv = tmp;
+ return true;
+
+
+args_failed:
+ DEBUG(DEBUG_ERR, (__location__ " too many arguments '%s' to eventscript '%s'\n",
+ options, ctdb_eventscript_call_names[call]));
+
+failed:
+ if (tmp) {
+ talloc_free(tmp);
+ }
+ return false;
+
+}
+
static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde,
uint16_t flags, void *p);
+static const char *helper_prog = NULL;
+
static int fork_child_for_script(struct ctdb_context *ctdb,
struct ctdb_event_script_state *state)
{
int r;
struct tevent_fd *fde;
struct ctdb_script_wire *current = get_current_script(state);
+ int argc;
+ const char **argv;
+ static const char *helper = BINDIR "/ctdb_event_helper";
+
+ if (helper_prog == NULL) {
+ const char *t = getenv("CTDB_EVENT_HELPER");
+ if (t != NULL) {
+ helper_prog = t;
+ } else {
+ helper_prog = helper;
+ }
+ }
current->start = timeval_current();
@@ -372,38 +448,32 @@ static int fork_child_for_script(struct ctdb_context *ctdb,
return -errno;
}
- if (!ctdb_fork_with_logging(state, ctdb, current->name, log_event_script_output,
- state, &state->child)) {
- r = -errno;
+ /* Arguments for helper */
+ if (!child_helper_args(state, ctdb, state->call, state->options, current,
+ state->fd[1], &argc, &argv)) {
+ DEBUG(DEBUG_ERR, (__location__ " failed to create arguments for eventscript helper\n"));
+ r = -ENOMEM;
close(state->fd[0]);
close(state->fd[1]);
return r;
}
- /* If we are the child, do the work. */
- if (state->child == 0) {
- int rt;
-
- debug_extra = talloc_asprintf(NULL, "eventscript-%s-%s:",
- current->name,
- ctdb_eventscript_call_names[state->call]);
+ if (!ctdb_vfork_with_logging(state, ctdb, current->name,
+ helper_prog, argc, argv,
+ log_event_script_output,
+ state, &state->child)) {
+ talloc_free(argv);
+ r = -errno;
close(state->fd[0]);
- set_close_on_exec(state->fd[1]);
- ctdb_set_process_name("ctdb_eventscript");
-
- rt = child_run_script(ctdb, state->call, state->options, current);
- /* We must be able to write PIPEBUF bytes at least; if this
- somehow fails, the read above will be short. */
- write(state->fd[1], &rt, sizeof(rt));
close(state->fd[1]);
- _exit(rt);
+ return r;
}
+ talloc_free(argv);
+
close(state->fd[1]);
set_close_on_exec(state->fd[0]);
- DEBUG(DEBUG_DEBUG, (__location__ " Created PIPE FD:%d to child eventscript process\n", state->fd[0]));
-
/* Set ourselves up to be called when that's done. */
fde = event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ,
ctdb_event_script_handler, state);