4 Copyright (C) Andrew Tridgell 2007
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, see <http://www.gnu.org/licenses/>.
21 #include "system/filesys.h"
22 #include "system/wait.h"
23 #include "../include/ctdb_private.h"
24 #include "lib/events/events.h"
27 run the event script - varargs version
29 static int ctdb_event_script_v(struct ctdb_context *ctdb, const char *fmt, va_list ap)
31 char *options, *cmdstr;
36 if (stat(ctdb->takeover.event_script, &st) != 0 &&
38 DEBUG(0,("No event script found at '%s'\n", ctdb->takeover.event_script));
43 options = talloc_vasprintf(ctdb, fmt, ap2);
45 CTDB_NO_MEMORY(ctdb, options);
47 cmdstr = talloc_asprintf(ctdb, "%s %s", ctdb->takeover.event_script, options);
48 CTDB_NO_MEMORY(ctdb, cmdstr);
52 ret = WEXITSTATUS(ret);
61 struct ctdb_event_script_state {
62 struct ctdb_context *ctdb;
64 void (*callback)(struct ctdb_context *, int, void *);
69 /* called when child is finished */
70 static void ctdb_event_script_handler(struct event_context *ev, struct fd_event *fde,
71 uint16_t flags, void *p)
73 struct ctdb_event_script_state *state =
74 talloc_get_type(p, struct ctdb_event_script_state);
76 void (*callback)(struct ctdb_context *, int, void *) = state->callback;
77 void *private_data = state->private_data;
78 struct ctdb_context *ctdb = state->ctdb;
80 waitpid(state->child, &status, 0);
82 status = WEXITSTATUS(status);
84 talloc_set_destructor(state, NULL);
86 callback(ctdb, status, private_data);
90 /* called when child times out */
91 static void ctdb_event_script_timeout(struct event_context *ev, struct timed_event *te,
92 struct timeval t, void *p)
94 struct ctdb_event_script_state *state = talloc_get_type(p, struct ctdb_event_script_state);
95 void (*callback)(struct ctdb_context *, int, void *) = state->callback;
96 void *private_data = state->private_data;
97 struct ctdb_context *ctdb = state->ctdb;
99 DEBUG(0,("event script timed out\n"));
101 callback(ctdb, -1, private_data);
105 destroy a running event script
107 static int event_script_destructor(struct ctdb_event_script_state *state)
109 kill(state->child, SIGKILL);
110 waitpid(state->child, NULL, 0);
115 run the event script in the background, calling the callback when
118 static int ctdb_event_script_callback_v(struct ctdb_context *ctdb,
119 struct timeval timeout,
121 void (*callback)(struct ctdb_context *, int, void *),
123 const char *fmt, va_list ap)
125 struct ctdb_event_script_state *state;
128 state = talloc(mem_ctx, struct ctdb_event_script_state);
129 CTDB_NO_MEMORY(ctdb, state);
132 state->callback = callback;
133 state->private_data = private_data;
135 ret = pipe(state->fd);
141 state->child = fork();
143 if (state->child == (pid_t)-1) {
150 if (state->child == 0) {
152 if (ctdb->do_setsched) {
153 ctdb_restore_scheduler(ctdb);
155 set_close_on_exec(state->fd[1]);
156 ret = ctdb_event_script_v(ctdb, fmt, ap);
160 talloc_set_destructor(state, event_script_destructor);
164 event_add_fd(ctdb->ev, state, state->fd[0], EVENT_FD_READ|EVENT_FD_AUTOCLOSE,
165 ctdb_event_script_handler, state);
167 if (!timeval_is_zero(&timeout)) {
168 event_add_timed(ctdb->ev, state, timeout, ctdb_event_script_timeout, state);
176 run the event script in the background, calling the callback when
179 int ctdb_event_script_callback(struct ctdb_context *ctdb,
180 struct timeval timeout,
182 void (*callback)(struct ctdb_context *, int, void *),
184 const char *fmt, ...)
190 ret = ctdb_event_script_callback_v(ctdb, timeout, mem_ctx, callback, private_data, fmt, ap);
197 struct callback_status {
203 called when ctdb_event_script() finishes
205 static void event_script_callback(struct ctdb_context *ctdb, int status, void *private_data)
207 struct callback_status *s = (struct callback_status *)private_data;
213 run the event script, waiting for it to complete. Used when the caller doesn't want to
214 continue till the event script has finished.
216 int ctdb_event_script(struct ctdb_context *ctdb, const char *fmt, ...)
220 TALLOC_CTX *tmp_ctx = talloc_new(ctdb);
221 struct callback_status status;
224 ret = ctdb_event_script_callback_v(ctdb, timeval_zero(), tmp_ctx, event_script_callback, &status, fmt, ap);
228 talloc_free(tmp_ctx);
235 while (status.done == false && event_loop_once(ctdb->ev) == 0) /* noop */;
237 talloc_free(tmp_ctx);
239 return status.status;