diff options
author | Amitay Isaacs <amitay@gmail.com> | 2013-12-17 19:19:51 +1100 |
---|---|---|
committer | Martin Schwenke <martin@meltin.net> | 2014-01-16 12:11:37 +1100 |
commit | d86662a925a072eb0374ad7743f4cf95c447bebb (patch) | |
tree | 994553dbbcb6cfe05ea7123eb706cfe4955f4761 /ctdb | |
parent | 69324b61f0669022c7204ee08a4c7104865d4e9b (diff) | |
download | samba-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.c | 110 |
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); |