From 60715a98331bdbd22e64d21cbac2caea5298a51e Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Sat, 5 Nov 2022 09:18:56 +1100 Subject: [PATCH] less heavier passing through pipe instead of named pipe --- src/lib66/exec/ssexec_svctl.c | 622 +++++++++++++++++----------------- 1 file changed, 313 insertions(+), 309 deletions(-) diff --git a/src/lib66/exec/ssexec_svctl.c b/src/lib66/exec/ssexec_svctl.c index da474133..56db3f24 100644 --- a/src/lib66/exec/ssexec_svctl.c +++ b/src/lib66/exec/ssexec_svctl.c @@ -52,18 +52,6 @@ #include <66/enum.h> #include <66/graph.h> - - - - - - -#include <stdio.h> - - - - - #define FLAGS_STARTING 1 // 1 starting not really up #define FLAGS_STOPPING (1 << 1) // 2 stopping not really down #define FLAGS_UP (1 << 2) // 4 really up @@ -74,7 +62,6 @@ #define DATASIZE 63 -static ftrigr_t FIFO = FTRIGR_ZERO ; static unsigned int napid = 0 ; static unsigned int npid = 0 ; @@ -89,15 +76,19 @@ static uint8_t reloadmsg = 0 ; typedef struct pidservice_s pidservice_t, *pidservice_t_ref ; struct pidservice_s { + int pipe[2] ; pid_t pid ; - uint16_t ids ; int aresid ; // id at array ares unsigned int vertex ; // id at graph_hash_t struct uint8_t state ; int nedge ; - unsigned int *edge ; // array of id at graph_hash_t struct + unsigned int edge[SS_MAX_SERVICE + 1] ; // array of id at graph_hash_t struct + int nnotif ; + /** id at graph_hash_t struct of depends/requiredby service + * to notify when a service is started/stopped */ + unsigned int notif[SS_MAX_SERVICE + 1] ; } ; -#define PIDSERVICE_ZERO { 0, 0, -1, 0, 0, 0, 0 } +#define PIDSERVICE_ZERO { { -1, -1 }, -1, -1, 0, 0, 0, { 0 } } typedef enum fifo_e fifo_t, *fifo_t_ref ; enum fifo_e @@ -122,8 +113,8 @@ enum service_action_e static const unsigned char actions[2][7] = { // u U d D F b B - { SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_FATAL, SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT }, // !what -> up - { SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT, SERVICE_ACTION_FATAL, SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT } // what -> down + { SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_FATAL, SERVICE_ACTION_WAIT, SERVICE_ACTION_WAIT }, // !what -> up + { SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_UNKNOWN, SERVICE_ACTION_WAIT, SERVICE_ACTION_GOTIT, SERVICE_ACTION_FATAL, SERVICE_ACTION_WAIT, SERVICE_ACTION_WAIT } // what -> down } ; @@ -148,13 +139,22 @@ static const unsigned int char2enum[128] = 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 //128 } ; +static inline void kill_all(pidservice_t *apids) +{ + log_flow() ; + + unsigned int j = napid ; + while (j--) kill(apids[j].pid, SIGKILL) ; +} + static pidservice_t pidservice_init(unsigned int len) { log_flow() ; pidservice_t pids = PIDSERVICE_ZERO ; - pids.edge = (unsigned int *)malloc(len * sizeof(unsigned int)) ; + if (len > SS_MAX_SERVICE) + log_die(LOG_EXIT_SYS, "too many services") ; graph_array_init_single(pids.edge, len) ; @@ -174,21 +174,104 @@ static int pidservice_get_id(pidservice_t *apids, unsigned int id) return -1 ; } -static void pidservice_free(pidservice_t *pids) +void notify(pidservice_t *apids, unsigned int pos, char const *sig, unsigned int what) { log_flow() ; - free(pids->edge) ; + unsigned int i = 0, idx = 0 ; + char fmt[UINT_FMT] ; + uint8_t flag = what ? FLAGS_DOWN : FLAGS_UP ; + + for (; i < apids[pos].nnotif ; i++) { + + for (idx = 0 ; idx < napid ; idx++) { + + if (apids[pos].notif[i] == apids[idx].vertex && !FLAGS_ISSET(apids[idx].state, flag)) { + + size_t nlen = uint_fmt(fmt, apids[pos].aresid) ; + fmt[nlen] = 0 ; + size_t len = nlen + 1 + 2 ; + char s[len + 1] ; + auto_strings(s, fmt, ":", sig, "@") ; + + log_trace("sends notification ", sig, " to: ", pares[apids[idx].aresid].sa.s + pares[apids[idx].aresid].name, " from: ", pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].name) ; + + if (write(apids[idx].pipe[1], s, strlen(s)) < 0) + log_dieusys(LOG_EXIT_SYS, "send notif to: ", pares[apids[idx].aresid].sa.s + pares[apids[idx].aresid].name) ; + } + } + } } -static void pidservice_array_free(pidservice_t *apids, unsigned int len) +/** + * @what: up or down + * @success: 0 fail, 1 win + * */ +static void announce(unsigned int pos, pidservice_t *apids, unsigned int what, unsigned int success, unsigned int exitcode) { log_flow() ; - size_t pos = 0 ; + int fd = 0 ; + char fmt[UINT_FMT] ; + char const *name = pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].name ; + char const *base = pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].path.home ; + char const *scandir = pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].live.scandir ; + size_t scandirlen = strlen(scandir) ; + char file[scandirlen + 6] ; + + auto_strings(file, scandir, "/down") ; + + uint8_t flag = what ? FLAGS_DOWN : FLAGS_UP ; + + if (success) { + + if (pares[apids[pos].aresid].type == TYPE_CLASSIC) { + + fd = open_trunc(file) ; + if (fd < 0) + log_dieusys(LOG_EXIT_SYS, "create file: ", scandir) ; + fd_close(fd) ; + } + + notify(apids, pos, "F", what) ; + + fmt[uint_fmt(fmt, exitcode)] = 0 ; + + log_1_warn("Unable to ", reloadmsg ? "reload" : what ? "stop" : "start", " service: ", name, " -- exited with signal: ", fmt) ; + + FLAGS_SET(apids[pos].state, FLAGS_BLOCK|FLAGS_FATAL) ; + + } else { - for(; pos < len ; pos++) - pidservice_free(&apids[pos]) ; + if (!state_messenger(base, name, STATE_FLAGS_ISUP, what ? STATE_FLAGS_FALSE : STATE_FLAGS_TRUE)) + log_dieusys(LOG_EXIT_SYS, "send message to state of: ", name) ; + + if (!pares[apids[pos].aresid].execute.down && pares[apids[pos].aresid].type == TYPE_CLASSIC) { + + if (!what) { + + if (!access(scandir, F_OK)) { + log_trace("delete down file: ", file) ; + if (unlink(file) < 0 && errno != ENOENT) + log_warnusys("delete down file: ", file) ; + } + + } else { + + fd = open_trunc(file) ; + if (fd < 0) + log_dieusys(LOG_EXIT_SYS, "create file: ", file) ; + fd_close(fd) ; + } + } + + notify(apids, pos, what ? "D" : "U", what) ; + + FLAGS_CLEAR(apids[pos].state, FLAGS_BLOCK) ; + FLAGS_SET(apids[pos].state, flag|FLAGS_UNBLOCK) ; + + log_info("Successfully ", reloadmsg ? "reloaded" : what ? "stopped" : "started", " service: ", name) ; + } } static void pidservice_init_array(unsigned int *list, unsigned int listlen, pidservice_t *apids, graph_t *g, resolve_service_t *ares, unsigned int areslen, ssexec_t *info, uint8_t requiredby, uint32_t flag) { @@ -210,17 +293,17 @@ static void pidservice_init_array(unsigned int *list, unsigned int listlen, pids log_dieu(LOG_EXIT_SYS,"find ares id of: ", name, " -- please make a bug reports") ; if (FLAGS_ISSET(flag, STATE_FLAGS_TOPROPAGATE)) { - /** - * This is should be recursive as long as the user ask for the propagation. - * So, call graph_matrix_get_edge_g_sorted_list() with recursive mode. - * This is overkill if we come from other 66 tools. Its call with the complete - * service selection to deal with. - * No choice here, we want a complete 66-svctl independence - * */ + pids.nedge = graph_matrix_get_edge_g_sorted_list(pids.edge, g, name, requiredby, 1) ; if (pids.nedge < 0) - log_dieu(LOG_EXIT_SYS,"get sorted ", requiredby ? "required by" : "dependency", " list of tree: ", name) ; + log_dieu(LOG_EXIT_SYS,"get sorted ", requiredby ? "required by" : "dependency", " list of service: ", name) ; + + pids.nnotif = graph_matrix_get_edge_g_sorted_list(pids.notif, g, name, !requiredby, 1) ; + + if (pids.nnotif < 0) + log_dieu(LOG_EXIT_SYS,"get sorted ", !requiredby ? "required by" : "dependency", " list of service: ", name) ; + } pids.vertex = graph_hash_vertex_get_id(g, name) ; @@ -258,143 +341,14 @@ static void pidservice_init_array(unsigned int *list, unsigned int listlen, pids apids[pos] = pids ; } -} -static void pidservice_init_fifo(pidservice_t *apids, graph_t *graph, ssexec_t *info, unsigned int deadline) -{ - log_flow() ; - - unsigned int pos = 0 ; - gid_t gid ; - - tain dead ; - tain_from_millisecs(&dead, deadline) ; - tain_now_set_stopwatch_g() ; - tain_add_g(&dead, &dead) ; - - if (!yourgid(&gid, info->owner)) - log_dieusys(LOG_EXIT_SYS, "get gid") ; - - if (!ftrigr_startf_g(&FIFO, &dead)) - log_dieusys(LOG_EXIT_SYS, "ftrigr_startf") ; - - for (; pos < napid ; pos++) { - - char *notifdir = pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].live.notifdir ; - - if (!dir_create_parent(notifdir, 0700)) - log_dieusys(LOG_EXIT_SYS, "create directory: ", notifdir) ; - - if (!ftrigw_fifodir_make(notifdir, gid, 0)) - log_dieusys(LOG_EXIT_SYS, "make fifo directory: ", notifdir) ; - - /** may already exist, cleans it */ - if (!ftrigw_clean(notifdir)) - log_dieusys(LOG_EXIT_SYS, "clean fifo directory: ", notifdir) ; - - apids[pos].ids = ftrigr_subscribe_g(&FIFO, notifdir, "[uUdDFbB]", FTRIGR_REPEAT, &dead) ; - - if (!apids[pos].ids) - log_dieusys(LOG_EXIT_SYS, "subcribe to: ", notifdir) ; - } -} - -static inline void kill_all(pidservice_t *apids) -{ - log_flow() ; - - unsigned int j = napid ; - while (j--) kill(apids[j].pid, SIGKILL) ; -} - -/** - * @what: up or down - * @success: 0 fail, 1 win - * */ -static void announce(pidservice_t *apids, unsigned int what, unsigned int success, unsigned int exitcode) -{ - log_flow() ; - - int fd = 0 ; - char const *notifdir = pares[apids->aresid].sa.s + pares[apids->aresid].live.notifdir ; - char const *name = pares[apids->aresid].sa.s + pares[apids->aresid].name ; - char const *base = pares[apids->aresid].sa.s + pares[apids->aresid].path.home ; - char const *scandir = pares[apids->aresid].sa.s + pares[apids->aresid].live.scandir ; - size_t scandirlen = strlen(scandir) ; - char file[scandirlen + 6] ; - - auto_strings(file, scandir, "/down") ; - - uint8_t flag = what ? FLAGS_DOWN : FLAGS_UP ; - - if (success) { - - FLAGS_SET(apids->state, FLAGS_BLOCK|FLAGS_FATAL) ; - - fd = open_trunc(file) ; - if (fd < 0) - log_dieusys(LOG_EXIT_SYS, "create file: ", scandir) ; - fd_close(fd) ; - - log_trace("sends notification F to: ", notifdir) ; - if (ftrigw_notify(notifdir, 'F') < 0) - log_dieusys(LOG_EXIT_SYS, "notifies event directory: ", notifdir) ; - - char fmt[UINT_FMT] ; - fmt[uint_fmt(fmt, exitcode)] = 0 ; - - log_1_warn("Unable to ", reloadmsg ? "reload" : what ? "stop" : "start", " service: ", name, " -- exited with signal: ", fmt) ; - - - - } else { - - if (!state_messenger(base, name, STATE_FLAGS_ISUP, what ? STATE_FLAGS_FALSE : STATE_FLAGS_TRUE)) - log_dieusys(LOG_EXIT_SYS, "send message to state of: ", name) ; - - FLAGS_SET(apids->state, flag|FLAGS_UNBLOCK) ; - - if (!pares[apids->aresid].execute.down && pares[apids->aresid].type == TYPE_CLASSIC) { - - if (!what) { - - if (!access(scandir, F_OK)) { - log_trace("delete down file: ", file) ; - if (unlink(file) < 0 && errno != ENOENT) - log_warnusys("delete down file: ", file) ; - } - - } else { - - fd = open_trunc(file) ; - if (fd < 0) - log_dieusys(LOG_EXIT_SYS, "create file: ", file) ; - fd_close(fd) ; - } - } - - log_trace("sends notification ", what ? "D" : "U", " to: ", notifdir) ; - if (ftrigw_notify(notifdir, what ? 'D' : 'U') < 0) - log_dieusys(LOG_EXIT_SYS, "notifies event directory: ", notifdir) ; - - log_info("Successfully ", reloadmsg ? "reloaded" : what ? "stopped" : "started", " service: ", name) ; - - } - - tain dead ; - tain_from_millisecs(&dead, 3000) ; - tain_now_set_stopwatch_g() ; - tain_add_g(&dead, &dead) ; - - if (!ftrigr_unsubscribe_g(&FIFO, apids->ids, &dead)) - log_dieusys(LOG_EXIT_SYS, "unsubcribe: ", name) ; } static int handle_signal(pidservice_t *apids, unsigned int what, graph_t *graph, ssexec_t *info) { log_flow() ; - int ok = 1 ; + int ok = 0 ; for (;;) { @@ -420,7 +374,6 @@ static int handle_signal(pidservice_t *apids, unsigned int what, graph_t *graph, } else if (!r) break ; - for (; pos < napid ; pos++) if (apids[pos].pid == r) break ; @@ -429,12 +382,15 @@ static int handle_signal(pidservice_t *apids, unsigned int what, graph_t *graph, if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) { - announce(&apids[pos], what, 0, 0) ; + announce(pos, apids, what, 0, 0) ; } else { - ok = 0 ; - announce(&apids[pos], what, 1, WIFSIGNALED(wstat) ? WTERMSIG(wstat) : WEXITSTATUS(wstat)) ; + ok = WIFSIGNALED(wstat) ? WTERMSIG(wstat) : WEXITSTATUS(wstat) ; + announce(pos, apids, what, 1, ok) ; + + kill_all(apids) ; + break ; } npid-- ; @@ -442,9 +398,11 @@ static int handle_signal(pidservice_t *apids, unsigned int what, graph_t *graph, } break ; case SIGTERM : + case SIGKILL : case SIGINT : - log_1_warn("received SIGINT, aborting tree transition") ; + log_1_warn("received SIGINT, aborting transaction") ; kill_all(apids) ; + ok = 111 ; break ; default : log_die(LOG_EXIT_SYS, "unexpected data in selfpipe") ; } @@ -460,16 +418,16 @@ static int doit(pidservice_t *sv, unsigned int what, unsigned int deadline) uint8_t type = pares[sv->aresid].type ; pid_t pid ; - int wstat, e = 0 ; + int wstat ; if (type == TYPE_MODULE || type == TYPE_BUNDLE) /** * Those type are not real services. Passing here with * this kind of service means that the dependencies - * of the service was made anyway. So, we can consider it as + * of the service was passed anyway. So, we can consider it as * already up/down. * */ - return 1 ; + return 0 ; if (type == TYPE_CLASSIC) { @@ -500,7 +458,7 @@ static int doit(pidservice_t *sv, unsigned int what, unsigned int deadline) newargv[m++] = scandir ; newargv[m++] = 0 ; - log_info("sending ", opt_updown ? newargv[2] : "", opt_updown ? " " : "", data, " to: ", scandir) ; + log_trace("sending ", opt_updown ? newargv[2] : "", opt_updown ? " " : "", data, " to: ", scandir) ; pid = child_spawn0(newargv[0], newargv, (char const *const *) environ) ; @@ -508,155 +466,203 @@ static int doit(pidservice_t *sv, unsigned int what, unsigned int deadline) log_warnusys_return(LOG_EXIT_ZERO, "wait for s6-svc") ; if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) - e = 1 ; - - } else if (type == TYPE_ONESHOT) { - - char *sa = pares[sv->aresid].sa.s ; - char *name = sa + pares[sv->aresid].name ; - size_t namelen = strlen(name) ; - char *tree = pares[sv->aresid].sa.s + pares[sv->aresid].path.tree ; - size_t treelen = strlen(tree) ; - unsigned int timeout = 0 ; - if (!what) - timeout = pares[sv->aresid].execute.timeout.up ; + return WEXITSTATUS(wstat) ; else - timeout = pares[sv->aresid].execute.timeout.down ; + return WIFSIGNALED(wstat) ? WTERMSIG(wstat) : WEXITSTATUS(wstat) ; - char script[treelen + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen + 7 + 1] ; - auto_strings(script, tree, SS_SVDIRS, SS_SVC, "/", name) ; - char tfmt[UINT32_FMT] ; - tfmt[uint_fmt(tfmt, timeout)] = 0 ; + } - char *oneshotdir = pares[sv->aresid].sa.s + pares[sv->aresid].live.oneshotddir ; - char *scandir = pares[sv->aresid].sa.s + pares[sv->aresid].live.scandir ; - char oneshot[strlen(oneshotdir) + 2 + 1] ; - auto_strings(oneshot, oneshotdir, "/s") ; + char *sa = pares[sv->aresid].sa.s ; + char *name = sa + pares[sv->aresid].name ; + size_t namelen = strlen(name) ; + char *tree = pares[sv->aresid].sa.s + pares[sv->aresid].path.tree ; + size_t treelen = strlen(tree) ; + unsigned int timeout = 0 ; + if (!what) + timeout = pares[sv->aresid].execute.timeout.up ; + else + timeout = pares[sv->aresid].execute.timeout.down ; + + char script[treelen + SS_SVDIRS_LEN + SS_SVC_LEN + 1 + namelen + 7 + 1] ; + auto_strings(script, tree, SS_SVDIRS, SS_SVC, "/", name) ; + + char tfmt[UINT32_FMT] ; + tfmt[uint_fmt(tfmt, timeout)] = 0 ; + + char *oneshotdir = pares[sv->aresid].sa.s + pares[sv->aresid].live.oneshotddir ; + char *scandir = pares[sv->aresid].sa.s + pares[sv->aresid].live.scandir ; + char oneshot[strlen(oneshotdir) + 2 + 1] ; + auto_strings(oneshot, oneshotdir, "/s") ; + + char const *newargv[11] ; + unsigned int m = 0 ; + newargv[m++] = "s6-sudo" ; + newargv[m++] = VERBOSITY >= 4 ? "-vel0" : "-el0" ; + newargv[m++] = "-t" ; + newargv[m++] = "30000" ; + newargv[m++] = "-T" ; + newargv[m++] = tfmt ; + newargv[m++] = "--" ; + newargv[m++] = oneshot ; + newargv[m++] = !what ? "up" : "down" ; + newargv[m++] = script ; + newargv[m++] = 0 ; + + log_trace("sending ", !what ? "up" : "down", " to: ", scandir) ; + + pid = child_spawn0(newargv[0], newargv, (char const *const *) environ) ; + + if (waitpid_nointr(pid, &wstat, 0) < 0) + log_warnusys_return(LOG_EXIT_ZERO, "wait for s6-sudo") ; + + if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) + return WEXITSTATUS(wstat) ; + else + return WIFSIGNALED(wstat) ? WTERMSIG(wstat) : WEXITSTATUS(wstat) ; +} - char const *newargv[11] ; - unsigned int m = 0 ; - newargv[m++] = "s6-sudo" ; - newargv[m++] = VERBOSITY >= 4 ? "-vel0" : "-el0" ; - newargv[m++] = "-t" ; - newargv[m++] = "30000" ; - newargv[m++] = "-T" ; - newargv[m++] = tfmt ; - newargv[m++] = "--" ; - newargv[m++] = oneshot ; - newargv[m++] = !what ? "up" : "down" ; - newargv[m++] = script ; - newargv[m++] = 0 ; +static int check_action(pidservice_t *apids, unsigned int pos, unsigned int receive, unsigned int what) +{ + unsigned int p = char2enum[receive] ; + unsigned char action = actions[what][p] ; - log_info("sending ", !what ? "up" : "down", " to: ", scandir) ; + switch(action) { - pid = child_spawn0(newargv[0], newargv, (char const *const *) environ) ; + case SERVICE_ACTION_GOTIT: + FLAGS_SET(apids[pos].state, (!what ? FLAGS_UP : FLAGS_DOWN)) ; + return 1 ; - if (waitpid_nointr(pid, &wstat, 0) < 0) - log_warnusys_return(LOG_EXIT_ZERO, "wait for s6-sudo") ; + case SERVICE_ACTION_FATAL: + FLAGS_SET(apids[pos].state, FLAGS_FATAL) ; + return -1 ; + case SERVICE_ACTION_WAIT: + return 0 ; - if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) - e = 1 ; + case SERVICE_ACTION_UNKNOWN: + default: + log_die(LOG_EXIT_ZERO,"invalid action -- please make a bug report") ; } - return e ; } static int async_deps(pidservice_t *apids, unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph, unsigned int deadline) { log_flow() ; - int e = 0, r ; - unsigned int pos = 0 ; + int r ; + unsigned int pos = 0, id = 0, ilog = 0, idx = 0 ; + char buf[(UINT_FMT*2)*SS_MAX_SERVICE + 1] ; tain dead ; tain_from_millisecs(&dead, deadline) ; tain_now_set_stopwatch_g() ; tain_add_g(&dead, &dead) ; - iopause_fd x = { .fd = ftrigr_fd(&FIFO), .events = IOPAUSE_READ } ; - stralloc sa = STRALLOC_ZERO ; + iopause_fd x = { .fd = apids[i].pipe[0], .events = IOPAUSE_READ, 0 } ; - while (apids[i].nedge) { + unsigned int n = apids[i].nedge ; + unsigned int visit[n] ; - /** TODO: the pidvertex_get_id() function make a loop - * through the apids array to find the corresponding - * index of the edge at the apids array. - * This is clearly a waste of time and should be optimized. */ - unsigned int id = pidservice_get_id(apids, apids[i].edge[pos]) ; + graph_array_init_single(visit, n) ; - if (id < 0) - log_dieu(LOG_EXIT_SYS, "get apidservice id -- please make a bug report") ; + while (pos < n) { r = iopause_g(&x, 1, &dead) ; + if (r < 0) log_dieusys(LOG_EXIT_SYS, "iopause") ; - if (!r) - log_die(LOG_EXIT_SYS,"time out") ; + + if (!r) { + errno = ETIMEDOUT ; + log_dieusys(LOG_EXIT_SYS,"time out", pares[apids[i].aresid].sa.s + pares[apids[i].aresid].name) ; + } if (x.revents & IOPAUSE_READ) { - if (ftrigr_update(&FIFO) < 0) - log_dieusys(LOG_EXIT_SYS, "ftrigr_update") ; + memset(buf, 0, sizeof(buf)) ; + r = read(apids[i].pipe[0], buf, sizeof(buf)) ; + if (r < 0) + log_dieu(LOG_EXIT_SYS, "read from pipe") ; + buf[r] = 0 ; - for(pos = 0 ; pos < napid ; pos++) { + idx = 0 ; - sa.len = 0 ; - r = ftrigr_checksa(&FIFO, apids[pos].ids, &sa) ; + while (r != -1) { + /** The buf might contain multiple signal coming + * from the dependencies if they finished before + * the start of this read process. Check every + * signal received.*/ + r = get_len_until(buf + idx, '@') ; if (r < 0) - log_dieusys(LOG_EXIT_SYS, "ftrigr_check") ; + /* no more signal */ + goto next ; - else if (r) { + char line[r + 1] ; + memcpy(line, buf + idx, r) ; + line[r] = 0 ; - size_t l = 0 ; + idx += r + 1 ; - for (; l < sa.len ; l++) { + /** + * the receiving string have the format: + * index_of_the_ares_array_of_the_service_dependency:signal_receive + * + * typically: + * - 10:D + * - 30:u + * - ... + * + * Split it and check the signal receive.*/ + int sep = get_len_until(line, ':') ; + if (sep < 0) + log_die(LOG_EXIT_SYS, "received bad signal format -- please make a bug report") ; - unsigned int p = char2enum[(unsigned int)sa.s[l]] ; - unsigned char action = actions[what][p] ; - char s[2] = { sa.s[l], 0 } ; - log_trace("received signal: ", s, " from: ", pares[apids[pos].aresid].sa.s + pares[apids[pos].aresid].name) ; - switch(action) { + char c = line[sep + 1] ; + line[sep] = 0 ; - case SERVICE_ACTION_GOTIT: - FLAGS_SET(apids[pos].state, (!what ? FLAGS_UP : FLAGS_DOWN)) ; - goto next ; + if (!uint0_scan(line, &id)) + log_dieusys(LOG_EXIT_SYS, "retrieve service number -- please make a bug report") ; - case SERVICE_ACTION_FATAL: - FLAGS_SET(apids[pos].state, FLAGS_FATAL) ; - goto err ; + ilog = id ; - case SERVICE_ACTION_WAIT: - goto next ; + log_trace(pares[apids[i].aresid].sa.s + pares[apids[i].aresid].name, " acknowledges: ", &c, " from: ", pares[ilog].sa.s + pares[ilog].name, " ", &c,"-> ", line) ; - case SERVICE_ACTION_UNKNOWN: - default: - log_die(LOG_EXIT_ZERO,"invalid action -- please make a bug report") ; - } - } + if (!visit[pos]) { + + id = pidservice_get_id(apids, id) ; + if (id < 0) + log_dieu(LOG_EXIT_SYS, "get apidservice id -- please make a bug report") ; + + id = check_action(apids, id, c, what) ; + if (id < 0) + log_die(LOG_EXIT_SYS, "service dependency: ", pares[ilog].sa.s + pares[ilog].name, " of: ", pares[apids[i].aresid].sa.s + pares[apids[i].aresid].name," crashed") ; + + if (!id) + continue ; + + visit[pos++]++ ; } } } next: - apids[i].nedge-- ; + } - e = 1 ; - err: - stralloc_free(&sa) ; - return e ; + return 1 ; } static int async(pidservice_t *apids, unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph, unsigned int deadline) { log_flow() ; - int e = 1 ; + int e = 0 ; char *name = graph->data.s + genalloc_s(graph_hash_t,&graph->hash)[apids[i].vertex].vertex ; - char *notifdir = pares[apids[i].aresid].sa.s + pares[apids[i].aresid].live.notifdir ; + + log_info("beginning of the process of: ", name) ; if (FLAGS_ISSET(apids[i].state, (!what ? FLAGS_DOWN : FLAGS_UP))) { @@ -674,20 +680,15 @@ static int async(pidservice_t *apids, unsigned int i, unsigned int what, ssexec_ log_info("Skipping service: ", name, " -- already in ", what ? "stopping" : "starting", " process") ; - log_trace("sends notification ", what ? "d" : "u", " to : ", notifdir) ; - if (ftrigw_notify(notifdir, what ? 'd' : 'u') < 0) - log_warnusys_return(LOG_EXIT_ZERO, "notifies event directory: ", notifdir) ; + notify(apids, i, what ? "d" : "u", what) ; } } else { + /** do not notify here, the handle will make it for us */ log_info("Skipping service: ", name, " -- already ", what ? "down" : "up") ; - //log_trace("sends notification ", what ? "D" : "U", " to : ", notifdir) ; - //if (ftrigw_notify(notifdir, what ? 'D' : 'U') < 0) - // log_warnusys_return(LOG_EXIT_ZERO, "notifies event directory: ", notifdir) ; - } return e ; @@ -697,7 +698,7 @@ static int waitit(pidservice_t *apids, unsigned int what, graph_t *graph, unsign { log_flow() ; - unsigned int e = 1, pos = 0 ; + unsigned int e = 0, pos = 0 ; int r ; pid_t pid ; pidservice_t apidservicetable[napid] ; @@ -715,15 +716,22 @@ static int waitit(pidservice_t *apids, unsigned int what, graph_t *graph, unsign if (!selfpipe_trap(SIGCHLD) || !selfpipe_trap(SIGINT) || + !selfpipe_trap(SIGKILL) || !selfpipe_trap(SIGTERM) || !sig_altignore(SIGPIPE)) log_dieusys(LOG_EXIT_SYS, "selfpipe_trap") ; - pidservice_init_fifo(apids, graph, info, deadline) ; + iopause_fd x = { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } ; + + for (; pos < napid ; pos++) { - for (pos = 0 ; pos < napid ; pos++) apidservice[pos] = apids[pos] ; + if (pipe(apidservice[pos].pipe) < 0) + log_dieusys(LOG_EXIT_SYS, "pipe"); + + } + for (pos = 0 ; pos < napid ; pos++) { pid = fork() ; @@ -732,34 +740,52 @@ static int waitit(pidservice_t *apids, unsigned int what, graph_t *graph, unsign log_dieusys(LOG_EXIT_SYS, "fork") ; if (!pid) { + + selfpipe_finish() ; + + close(apidservice[pos].pipe[1]) ; + e = async(apidservice, pos, what, info, graph, deadline) ; - goto freed ; + + goto end ; } apidservice[pos].pid = pid ; + close(apidservice[pos].pipe[0]) ; + npid++ ; } - iopause_fd x = { .fd = spfd, .events = IOPAUSE_READ } ; - while (npid) { r = iopause_g(&x, 1, &dead) ; + if (r < 0) log_dieusys(LOG_EXIT_SYS, "iopause") ; - if (!r) - log_die(LOG_EXIT_SYS,"time out") ; - if (x.revents & IOPAUSE_READ) - if (!handle_signal(apidservice, what, graph, info)) - e = 0 ; + if (!r) { + errno = ETIMEDOUT ; + log_diesys(LOG_EXIT_SYS,"time out") ; + } + + if (x.revents & IOPAUSE_READ) { + e = handle_signal(apidservice, what, graph, info) ; + + if (e) + break ; + } } - freed: - ftrigr_end(&FIFO) ; + + selfpipe_finish() ; + end: + for (pos = 0 ; pos < napid ; pos++) { + close(apidservice[pos].pipe[1]) ; + close(apidservice[pos].pipe[0]) ; + } - return e ; + return e ; } int ssexec_svctl(int argc, char const *const *argv, ssexec_t *info) @@ -780,7 +806,7 @@ int ssexec_svctl(int argc, char const *const *argv, ssexec_t *info) * do not send signal to the depends/requiredby of the service. * * STATE_FLAGS_TOPROPAGATE = 1 - * also send signal to the depends/requiredby of the service + * send signal to the depends/requiredby of the service * * When we come from 66-start/stop tool we always want to * propagate the signal. But we may need/want to send a e.g. SIGHUP signal @@ -873,31 +899,9 @@ int ssexec_svctl(int argc, char const *const *argv, ssexec_t *info) if ((svc_scandir_ok(info->scandir.s)) != 1) log_diesys(LOG_EXIT_SYS,"scandir: ", info->scandir.s," is not running") ; - /** build the graph of the entire system - * - * - * ici tu passe dans le graph sans controle de savoir si le service - * est au minima parsed voir initialized - * - * */ + /** build the graph of the entire system.*/ graph_build_service(&graph, ares, &areslen, info, gflag) ; -/* - { - stralloc sa = STRALLOC_ZERO ; - char const *exclude[1] = { 0 } ; - char solve[info->base.len + SS_SYSTEM_LEN + SS_RESOLVE_LEN + 1 + SS_SERVICE_LEN + 1] ; - - auto_strings(solve, info->base.s, SS_SYSTEM, SS_RESOLVE, "/", SS_SERVICE) ; - - if (!sastr_dir_get_recursive(&sa,solve,exclude,S_IFREG, 0)) - log_dieu(LOG_EXIT_SYS, "get resolve files") ; - - service_graph_g(sa.s, sa.len, &graph, ares, &areslen, info, STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_WANTUP|STATE_FLAGS_WANTDOWN) ; - - stralloc_free(&sa) ; - } -*/ if (!graph.mlen) log_die(LOG_EXIT_USER, "services selection is not supervised -- initiate its first") ; @@ -910,7 +914,7 @@ int ssexec_svctl(int argc, char const *const *argv, ssexec_t *info) unsigned int l[graph.mlen], c = 0, pos = 0 ; /** find dependencies of the service from the graph, do it recursively */ - c = graph_matrix_get_edge_g_sorted_list(l, &graph, *argv, !!requiredby, 1) ; + c = graph_matrix_get_edge_g_sorted_list(l, &graph, *argv, requiredby, 1) ; /** append to the list to deal with */ for (; pos < c ; pos++) @@ -931,8 +935,8 @@ int ssexec_svctl(int argc, char const *const *argv, ssexec_t *info) r = waitit(apids, what, &graph, deadline, info) ; graph_free_all(&graph) ; - pidservice_array_free(apids, napid) ; + service_resolve_array_free(ares, areslen) ; - return (!r) ? 111 : 0 ; + return r ; } -- GitLab