diff --git a/src/lib66/exec/deps-lib/deps b/src/lib66/exec/deps-lib/deps index 831144d870a4fafef87d85f6c2d87c435bc87e12..5570d296e1a0480df8ecd80215431cefa62e6fff 100644 --- a/src/lib66/exec/deps-lib/deps +++ b/src/lib66/exec/deps-lib/deps @@ -1,4 +1,3 @@ -ssexec_all.o ssexec_boot.o ssexec_copy.o ssexec_disable.o diff --git a/src/lib66/exec/ssexec_all.c b/src/lib66/exec/ssexec_all.c deleted file mode 100644 index 6510344164a075f92e292833f4fdefa4eb77566f..0000000000000000000000000000000000000000 --- a/src/lib66/exec/ssexec_all.c +++ /dev/null @@ -1,1006 +0,0 @@ -/* - * ssexec_all.c - * - * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org> - * - * All rights reserved. - * - * This file is part of Obarun. It is subject to the license terms in - * the LICENSE file found in the top-level directory of this - * distribution. - * This file may not be copied, modified, propagated, or distributed - * except according to the terms contained in the LICENSE file./ - */ - -#include <sys/stat.h>//S_IFREG,umask -#include <sys/types.h>//pid_t -#include <fcntl.h>//O_RDWR -#include <unistd.h>//dup2,setsid,chdir,fork -#include <sys/ioctl.h> -#include <stdint.h>//uint8_t -#include <stdlib.h>//realpath -#include <string.h>//strdup - -#include <oblibs/string.h> -#include <oblibs/types.h> -#include <oblibs/log.h> -#include <oblibs/sastr.h> -#include <oblibs/obgetopt.h> -#include <oblibs/files.h> -#include <oblibs/graph.h> -#include <oblibs/directory.h> - -#include <skalibs/types.h> -#include <skalibs/stralloc.h> -#include <skalibs/djbunix.h> -#include <skalibs/posixplz.h> -#include <skalibs/tai.h> -#include <skalibs/selfpipe.h> -#include <skalibs/sig.h> -#include <skalibs/iopause.h> - -#include <66/ssexec.h> -#include <66/constants.h> -#include <66/tree.h> -#include <66/svc.h>//scandir_ok -#include <66/utils.h> -#include <66/graph.h> - -#include <s6/ftrigr.h> -#include <s6/ftrigw.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 -#define FLAGS_DOWN (1 << 3) // 8 really down -#define FLAGS_BLOCK (1 << 4) // 16 all deps are not up/down -#define FLAGS_UNBLOCK (1 << 5) // 32 all deps up/down -#define FLAGS_FATAL (1 << 6) // 64 process crashed - -static unsigned int napid = 0 ; -static unsigned int npid = 0 ; - -static resolve_tree_t_ref pares = 0 ; -static unsigned int *pareslen = 0 ; -static uint8_t reloadmsg = 0 ; - -typedef struct pidtree_s pidtree_t, *pidtree_t_ref ; -struct pidtree_s -{ - int pipe[2] ; - pid_t pid ; - int aresid ; // id at array ares - unsigned int vertex ; // id at graph_hash_t struct - uint8_t state ; - int nedge ; - 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 tree is started/stopped */ - unsigned int notif[SS_MAX_SERVICE + 1] ; -} ; -#define PIDTREE_ZERO { { -1, -1 }, -1, -1, 0, 0, 0, { 0 } } - -typedef enum fifo_e fifo_t, *fifo_t_ref ; -enum fifo_e -{ - FIFO_u = 0, - FIFO_U, - FIFO_d, - FIFO_D, - FIFO_F, - FIFO_b, - FIFO_B -} ; - -typedef enum tree_action_e tree_action_t, *tree_action_t_ref ; -enum tree_action_e -{ - TREE_ACTION_GOTIT = 0, - TREE_ACTION_WAIT, - TREE_ACTION_FATAL, - TREE_ACTION_UNKNOWN -} ; - -static const unsigned char actions[2][7] = { - // u U d D F b B - { TREE_ACTION_WAIT, TREE_ACTION_GOTIT, TREE_ACTION_UNKNOWN, TREE_ACTION_UNKNOWN, TREE_ACTION_FATAL, TREE_ACTION_WAIT, TREE_ACTION_WAIT }, // !what -> up - { TREE_ACTION_UNKNOWN, TREE_ACTION_UNKNOWN, TREE_ACTION_WAIT, TREE_ACTION_GOTIT, TREE_ACTION_FATAL, TREE_ACTION_WAIT, TREE_ACTION_WAIT } // what -> down - -} ; - -// convert signal into enum number -static const unsigned int char2enum[128] = -{ - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //8 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //16 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //24 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //32 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //40 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //48 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //56 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //64 - 0 , 0 , FIFO_B , 0 , FIFO_D , 0 , FIFO_F , 0 , //72 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //80 - 0 , 0 , 0 , 0 , 0 , FIFO_U, 0 , 0 , //88 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //96 - 0 , 0 , FIFO_b , 0 , FIFO_d , 0 , 0 , 0 , //104 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , //112 - 0 , 0 , 0 , 0 , 0 , FIFO_u , 0 , 0 , //120 - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 //128 -} ; - -static inline unsigned int lookup (char const *const *table, char const *signal) -{ - log_flow() ; - - unsigned int i = 0 ; - for (; table[i] ; i++) if (!strcmp(signal, table[i])) break ; - return i ; -} - -static inline unsigned int parse_signal (char const *signal) -{ - log_flow() ; - - static char const *const signal_table[] = { - "up", - "down", - "unsupervise", - 0 - } ; - unsigned int i = lookup(signal_table, signal) ; - if (!signal_table[i]) log_usage(usage_all) ; - return i ; -} - -static void all_redir_fd(void) -{ - log_flow() ; - - int fd ; - while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0) { - - if (fd >= 3) - break ; - } - - dup2 (fd,0) ; - dup2 (fd,1) ; - dup2 (fd,2) ; - fd_close(fd) ; - - if (setsid() < 0) - log_dieusys(LOG_EXIT_SYS,"setsid") ; - - if ((chdir("/")) < 0) - log_dieusys(LOG_EXIT_SYS,"chdir") ; - - ioctl(0,TIOCSCTTY,1) ; - - umask(022) ; -} - -void tree_resolve_array_free(resolve_tree_t *ares, unsigned int areslen) -{ - - unsigned int pos = 0 ; - for (; pos < areslen ; pos++) - stralloc_free(&ares[pos].sa) ; -} - -static inline void kill_all(pidtree_t *apidt) -{ - log_flow() ; - - unsigned int j = napid ; - while (j--) kill(apidt[j].pid, SIGKILL) ; -} - -static pidtree_t pidtree_init(unsigned int len) -{ - log_flow() ; - - pidtree_t pids = PIDTREE_ZERO ; - - if (len > SS_MAX_SERVICE) - log_die(LOG_EXIT_SYS, "too many trees") ; - - graph_array_init_single(pids.edge, len) ; - - return pids ; -} - - -static int pidtree_get_id(pidtree_t *apidt, unsigned int id) -{ - log_flow() ; - - unsigned int pos = 0 ; - - for (; pos < napid ; pos++) { - if (apidt[pos].vertex == id) - return (unsigned int) pos ; - } - return -1 ; -} - - -static void notify(pidtree_t *apidt, unsigned int pos, char const *sig, unsigned int what) -{ - log_flow() ; - - unsigned int i = 0, idx = 0 ; - char fmt[UINT_FMT] ; - uint8_t flag = what ? FLAGS_DOWN : FLAGS_UP ; - - for (; i < apidt[pos].nnotif ; i++) { - - for (idx = 0 ; idx < napid ; idx++) { - - if (apidt[pos].notif[i] == apidt[idx].vertex && !FLAGS_ISSET(apidt[idx].state, flag)) { - - size_t nlen = uint_fmt(fmt, apidt[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[apidt[idx].aresid].sa.s + pares[apidt[idx].aresid].name, " from: ", pares[apidt[pos].aresid].sa.s + pares[apidt[pos].aresid].name) ; - - if (write(apidt[idx].pipe[1], s, strlen(s)) < 0) - log_dieusys(LOG_EXIT_SYS, "send notif to: ", pares[apidt[idx].aresid].sa.s + pares[apidt[idx].aresid].name) ; - } - } - } -} - -/** - * @what: up or down - * @success: 0 fail, 1 win - * */ -static void announce(unsigned int pos, pidtree_t *apidt, char const *base, unsigned int what, unsigned int success, unsigned int exitcode) -{ - log_flow() ; - - char fmt[UINT_FMT] ; - char const *treename = pares[apidt[pos].aresid].sa.s + pares[apidt[pos].aresid].name ; - - resolve_tree_t tres = RESOLVE_TREE_ZERO ; - resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ; - - uint8_t flag = what ? FLAGS_DOWN : FLAGS_UP ; - - if (!resolve_modify_field_g(wres, base, treename, E_RESOLVE_TREE_INIT, what ? (success ? "1" : "0") : (success ? "0" : "1"))) - log_dieusys(LOG_EXIT_SYS, "modify resolve file of: ", treename) ; - - if (success) { - - notify(apidt, pos, "F", what) ; - - fmt[uint_fmt(fmt, exitcode)] = 0 ; - - log_1_warnu(reloadmsg == 0 ? "start" : reloadmsg > 1 ? "unsupervise" : what == 0 ? "start" : "stop", " tree: ", treename, " -- exited with signal: ", fmt) ; - - FLAGS_SET(apidt[pos].state, FLAGS_BLOCK|FLAGS_FATAL) ; - - } else { - - notify(apidt, pos, what ? "D" : "U", what) ; - - FLAGS_CLEAR(apidt[pos].state, FLAGS_BLOCK) ; - FLAGS_SET(apidt[pos].state, flag|FLAGS_UNBLOCK) ; - - log_info("Successfully ", reloadmsg == 0 ? "started" : reloadmsg > 1 ? "unsupervised" : what == 0 ? "started" : "stopped", " tree: ", treename) ; - } - - resolve_free(wres) ; - -} - -static void pidtree_init_array(unsigned int *list, unsigned int listlen, pidtree_t *apidt, graph_t *g, resolve_tree_t *ares, unsigned int areslen, ssexec_t *info, uint8_t requiredby) -{ - log_flow() ; - - int r = 0 ; - unsigned int pos = 0 ; - - for (; pos < listlen ; pos++) { - - pidtree_t pids = pidtree_init(g->mlen) ; - - char *name = g->data.s + genalloc_s(graph_hash_t,&g->hash)[list[pos]].vertex ; - - pids.aresid = tree_resolve_array_search(ares, areslen, name) ; - - if (pids.aresid < 0) - log_dieu(LOG_EXIT_SYS,"find ares id of: ", name, " -- please make a bug reports") ; - - 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) ; - - 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 tree: ", name) ; - - pids.vertex = graph_hash_vertex_get_id(g, name) ; - - if (pids.vertex < 0) - log_dieu(LOG_EXIT_SYS, "get vertex id -- please make a bug report") ; - - r = tree_isinitialized(info->base.s, name) ; - - if (r < 0) - log_dieu(LOG_EXIT_SYS, "read resolve file of tree: ", name) ; - - if (r) - FLAGS_SET(pids.state, FLAGS_UP) ; - else - FLAGS_SET(pids.state, FLAGS_DOWN) ; - - apidt[pos] = pids ; - } -} - -static int handle_signal(pidtree_t *apidt, unsigned int what, graph_t *graph, ssexec_t *info) -{ - log_flow() ; - - int ok = 0 ; - - for (;;) { - - int s = selfpipe_read() ; - switch (s) { - - case -1 : log_dieusys(LOG_EXIT_SYS,"selfpipe_read") ; - case 0 : return ok ; - case SIGCHLD : - - for (;;) { - - unsigned int pos = 0 ; - int wstat ; - pid_t r = wait_nohang(&wstat) ; - - if (r < 0) { - - if (errno = ECHILD) - break ; - else - log_dieusys(LOG_EXIT_SYS,"wait for children") ; - - } else if (!r) break ; - - for (; pos < napid ; pos++) - if (apidt[pos].pid == r) - break ; - - if (pos < napid) { - - if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) { - - announce(pos, apidt, info->base.s, what, 0, 0) ; - - } else { - - ok = WIFSIGNALED(wstat) ? WTERMSIG(wstat) : WEXITSTATUS(wstat) ; - announce(pos, apidt, info->base.s, what, 1, ok) ; - - kill_all(apidt) ; - break ; - } - - npid-- ; - } - } - break ; - case SIGTERM : - case SIGKILL : - case SIGINT : - log_1_warn("received SIGINT, aborting transaction") ; - kill_all(apidt) ; - ok = 111 ; - break ; - default : log_die(LOG_EXIT_SYS, "unexpected data in selfpipe") ; - } - } - - return ok ; -} - -/** this following function come from: - * https://git.skarnet.org/cgi-bin/cgit.cgi/s6-rc/tree/src/s6-rc/s6-rc.c#n111 - * under license ISC where parameters was modified */ -static uint32_t compute_timeout (uint32_t timeout, tain *deadline) -{ - uint32_t t = timeout ; - int globalt ; - tain globaltto ; - tain_sub(&globaltto, deadline, &STAMP) ; - globalt = tain_to_millisecs(&globaltto) ; - if (!globalt) globalt = 1 ; - if (globalt > 0 && (!t || (unsigned int)globalt < t)) - t = (uint32_t)globalt ; - return t ; -} - -static int ssexec_callback(stralloc *sa, ssexec_t *info, unsigned int what) -{ - size_t pos = 0, len = sastr_len(sa), e = 1 ; - - int n = what == 2 ? 2 : 1 ; - int nargc = n + len ; - char const *prog = PROG ; - char const *newargv[nargc] ; - unsigned int m = 0 ; - - newargv[m++] = "all" ; - if (what == 2) - newargv[m++] = "-u" ; - - FOREACH_SASTR(sa, pos) - newargv[m++] = sa->s + pos ; - - newargv[m] = 0 ; - - if (!what) { - - PROG = "start" ; - e = ssexec_start(nargc, newargv, info) ; - PROG = prog ; - - } else { - - PROG = "stop" ; - e = ssexec_stop(nargc, newargv, info) ; - PROG = prog ; - } - - return e ; -} - -static int doit(char const *treename, ssexec_t *sinfo, unsigned int what, tain *deadline) -{ - log_flow() ; - - int r, e = 0 ; - ssexec_t info = SSEXEC_ZERO ; - - ssexec_copy(&info, sinfo) ; - - { - info.treename.len = 0 ; - - if (!auto_stra(&info.treename, treename)) - log_die_nomem("stralloc") ; - - info.tree.len = 0 ; - - if (!auto_stra(&info.tree, treename)) - log_die_nomem("stralloc") ; - - r = tree_sethome(&info) ; - if (r <= 0) - log_warnu_return(LOG_EXIT_ZERO, "find tree: ", info.treename.s) ; - - if (!tree_get_permissions(info.tree.s, info.owner)) - log_warn_return(LOG_EXIT_ZERO, "You're not allowed to use the tree: ", info.tree.s) ; - - } - - if (!tree_isinitialized(info.base.s, info.treename.s) && !what) { - - if (!what) { - - int nargc = 3 ; - char const *prog = PROG ; - char const *newargv[nargc] ; - unsigned int m = 0 ; - - newargv[m++] = "all (child)" ; - newargv[m++] = info.treename.s ; - newargv[m++] = 0 ; - - PROG = "init" ; - if (ssexec_init(nargc, newargv, &info)) - log_warnu_return(LOG_EXIT_ZERO, "initiate services of tree: ", info.treename.s) ; - PROG = prog ; - - } else { - - log_warn ("uninitialized tree: ", info.treename.s) ; - goto end ; - } - } - - { - stralloc sa = STRALLOC_ZERO ; - char const *exclude[2] = { SS_MASTER + 1 , 0 } ; - size_t treelen = info.tree.len + SS_SVDIRS_LEN + SS_RESOLVE_LEN ; - char tree[treelen + 1] ; - - auto_strings(tree, info.tree.s, SS_SVDIRS, SS_RESOLVE) ; - - if (!sastr_dir_get(&sa, tree, exclude, S_IFREG)) - log_dieu(LOG_EXIT_SYS, "get services list from tree: ", info.treename.s) ; - - if (!sa.len) { - - log_info("Empty tree: ", info.treename.s, " -- nothing to do") ; - - } else { - - if (!ssexec_callback(&sa, &info, what)) - goto err ; - - if (what == 2) - log_info("Unsupervised successfully tree: ", info.treename.s) ; - } - - stralloc_free(&sa) ; - } - end: - e = 1 ; - err: - ssexec_free(&info) ; - return e ; -} - -static int check_action(pidtree_t *apidt, unsigned int pos, unsigned int receive, unsigned int what) -{ - unsigned int p = char2enum[receive] ; - unsigned char action = actions[what][p] ; - - switch(action) { - - case TREE_ACTION_GOTIT: - FLAGS_SET(apidt[pos].state, (!what ? FLAGS_UP : FLAGS_DOWN)) ; - return 1 ; - - case TREE_ACTION_FATAL: - FLAGS_SET(apidt[pos].state, FLAGS_FATAL) ; - return -1 ; - - case TREE_ACTION_WAIT: - return 0 ; - - case TREE_ACTION_UNKNOWN: - default: - log_die(LOG_EXIT_ZERO,"invalid action -- please make a bug report") ; - } - -} - -static int async_deps(pidtree_t *apidt, unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph, tain *deadline) -{ - log_flow() ; - - int r ; - unsigned int pos = 0, id = 0, ilog = 0, idx = 0 ; - char buf[(UINT_FMT*2)*SS_MAX_SERVICE + 1] ; - - tain dead ; - tain_now_set_stopwatch_g() ; - tain_add_g(&dead, deadline) ; - - iopause_fd x = { .fd = apidt[i].pipe[0], .events = IOPAUSE_READ, 0 } ; - - unsigned int n = apidt[i].nedge ; - unsigned int visit[n] ; - - graph_array_init_single(visit, n) ; - - while (pos < n) { - - r = iopause_g(&x, 1, &dead) ; - - if (r < 0) - log_dieusys(LOG_EXIT_SYS, "iopause") ; - - if (!r) { - errno = ETIMEDOUT ; - log_dieusys(LOG_EXIT_SYS,"time out", pares[apidt[i].aresid].sa.s + pares[apidt[i].aresid].name) ; - } - - if (x.revents & IOPAUSE_READ) { - - memset(buf, 0, sizeof(buf)) ; - r = read(apidt[i].pipe[0], buf, sizeof(buf)) ; - if (r < 0) - log_dieu(LOG_EXIT_SYS, "read from pipe") ; - buf[r] = 0 ; - - idx = 0 ; - - 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) - /* no more signal */ - goto next ; - - char line[r + 1] ; - memcpy(line, buf + idx, r) ; - line[r] = 0 ; - - idx += r + 1 ; - - /** - * the received string have the format: - * index_of_the_ares_array_of_the_tree_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 c = line[sep + 1] ; - char pc[2] = { c, 0 } ; - line[sep] = 0 ; - - if (!uint0_scan(line, &id)) - log_dieusys(LOG_EXIT_SYS, "retrieve service number -- please make a bug report") ; - - ilog = id ; - - log_trace(pares[apidt[i].aresid].sa.s + pares[apidt[i].aresid].name, " acknowledges: ", pc, " from: ", pares[ilog].sa.s + pares[ilog].name) ; - - if (!visit[pos]) { - - id = pidtree_get_id(apidt, id) ; - if (id < 0) - log_dieu(LOG_EXIT_SYS, "get apidtree id -- please make a bug report") ; - - id = check_action(apidt, id, c, what) ; - if (id < 0) - log_die(LOG_EXIT_SYS, "tree dependency: ", pares[ilog].sa.s + pares[ilog].name, " of: ", pares[apidt[i].aresid].sa.s + pares[apidt[i].aresid].name," crashed") ; - - if (!id) - continue ; - - visit[pos++]++ ; - } - } - } - next: - - } - - return 1 ; -} - -static int async(pidtree_t *apidt, unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph, tain *deadline) -{ - log_flow() ; - - int e = 0 ; - - char *name = graph->data.s + genalloc_s(graph_hash_t,&graph->hash)[apidt[i].vertex].vertex ; - - log_trace("beginning of the process of: ", name) ; - - if (FLAGS_ISSET(apidt[i].state, (!what ? FLAGS_DOWN : FLAGS_UP)) || - /** force to pass through unsupersive process even - * if the tree is marked down */ - FLAGS_ISSET(apidt[i].state, (what ? FLAGS_DOWN : FLAGS_UP)) && what == 2) { - - if (!FLAGS_ISSET(apidt[i].state, FLAGS_BLOCK)) { - - FLAGS_SET(apidt[i].state, FLAGS_BLOCK) ; - - if (apidt[i].nedge) - if (!async_deps(apidt, i, what, info, graph, deadline)) - log_warnu_return(LOG_EXIT_ZERO, !what ? "start" : "stop", " dependencies of tree: ", name) ; - - e = doit(name, info, what, deadline) ; - - } else { - - log_trace("skipping tree: ", name, " -- already in ", what ? "stopping" : "starting", " process") ; - - notify(apidt, i, what ? "d" : "u", what) ; - - } - - } else { - - /** do not notify here, the handle will make it for us */ - log_trace("skipping service: ", name, " -- already ", what ? "down" : "up") ; - - } - - return e ; -} - -static int waitit(pidtree_t *apidt, unsigned int what, graph_t *graph, tain *deadline, ssexec_t *info) -{ - log_flow() ; - - unsigned int e = 0, pos = 0 ; - int r ; - pid_t pid ; - pidtree_t apidtreetable[napid] ; - pidtree_t_ref apidtree = apidtreetable ; - - tain_now_set_stopwatch_g() ; - tain_add_g(deadline, deadline) ; - - int spfd = selfpipe_init() ; - - if (spfd < 0) - log_dieusys(LOG_EXIT_SYS, "selfpipe_init") ; - - if (!selfpipe_trap(SIGCHLD) || - !selfpipe_trap(SIGINT) || - !selfpipe_trap(SIGKILL) || - !selfpipe_trap(SIGTERM) || - !sig_altignore(SIGPIPE)) - log_dieusys(LOG_EXIT_SYS, "selfpipe_trap") ; - - - iopause_fd x = { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } ; - - for (; pos < napid ; pos++) { - - apidtree[pos] = apidt[pos] ; - - if (pipe(apidtree[pos].pipe) < 0) - log_dieusys(LOG_EXIT_SYS, "pipe"); - - } - - for (pos = 0 ; pos < napid ; pos++) { - - pid = fork() ; - - if (pid < 0) - log_dieusys(LOG_EXIT_SYS, "fork") ; - - if (!pid) { - - selfpipe_finish() ; - - close(apidtree[pos].pipe[1]) ; - - e = async(apidtree, pos, what, info, graph, deadline) ; - - goto end ; - } - - apidtree[pos].pid = pid ; - - close(apidtree[pos].pipe[0]) ; - - npid++ ; - } - - while (npid) { - - r = iopause_g(&x, 1, deadline) ; - - if (r < 0) - log_dieusys(LOG_EXIT_SYS, "iopause") ; - - if (!r) { - errno = ETIMEDOUT ; - log_diesys(LOG_EXIT_SYS,"time out") ; - } - - if (x.revents & IOPAUSE_READ) { - e = handle_signal(apidtree, what, graph, info) ; - - if (e) - break ; - } - } - - - selfpipe_finish() ; - end: - for (pos = 0 ; pos < napid ; pos++) { - close(apidtree[pos].pipe[1]) ; - close(apidtree[pos].pipe[0]) ; - } - - return e ; -} - -int ssexec_all(int argc, char const *const *argv, ssexec_t *info) -{ - log_flow() ; - - int r, shut = 0, fd ; - tain deadline ; - uint8_t what = 0, requiredby = 0, found = 0 ; - stralloc sa = STRALLOC_ZERO ; - size_t pos = 0 ; - - unsigned int areslen = 0, list[SS_MAX_SERVICE], visit[SS_MAX_SERVICE] ; - resolve_tree_t ares[SS_MAX_SERVICE] ; - resolve_wrapper_t_ref wres = 0 ; - - graph_t graph = GRAPH_ZERO ; - - { - subgetopt l = SUBGETOPT_ZERO ; - - for (;;) - { - int opt = subgetopt_r(argc, argv, OPTS_ALL, &l) ; - if (opt == -1) break ; - - switch (opt) - { - case 'f' : shut = 1 ; break ; - default : log_usage(usage_all) ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - if (argc < 1) - log_usage(usage_all) ; - - info->treename.len = 0 ; - - if (argv[1]) { - if (!auto_stra(&info->treename, argv[1])) - log_die_nomem("stralloc") ; - } - - if (info->timeout) - tain_from_millisecs(&deadline, info->timeout) ; - else - deadline = tain_infinite_relative ; - - what = parse_signal(*argv) ; - - reloadmsg = what ; - - if (what) - requiredby = 1 ; - - if ((svc_scandir_ok(info->scandir.s)) <= 0) - log_die(LOG_EXIT_SYS,"scandir: ", info->scandir.s," is not running") ; - - graph_build_tree(&graph, info->base.s, E_RESOLVE_TREE_MASTER_ENABLED) ; - - if (!graph.mlen) - log_die(LOG_EXIT_USER, "trees selection is not created -- creates its first") ; - - graph_array_init_single(visit, SS_MAX_SERVICE) ; - - if (!graph_matrix_sort_tosa(&sa, &graph)) - log_dieu(LOG_EXIT_SYS, "get list of trees for graph -- please make a bug report") ; - - FOREACH_SASTR(&sa, pos) { - - char *treename = sa.s + pos ; - - /** only on tree */ - if (info->treename.len) { - - if (!strcmp(info->treename.s, treename)) - found = 1 ; - else continue ; - } - - if (tree_resolve_array_search(ares, areslen, treename) < 0) { - - resolve_tree_t tres = RESOLVE_TREE_ZERO ; - /** need to make a copy of the resolve due of the freed - * of the wres struct at the end of the process */ - resolve_tree_t cp = RESOLVE_TREE_ZERO ; - wres = resolve_set_struct(DATA_TREE, &tres) ; - - if (!resolve_read_g(wres, info->base.s, treename)) - log_dieu(LOG_EXIT_SYS, "read resolve file of: ", treename, " -- please make a bug report") ; - - tree_resolve_copy(&cp, &tres) ; - - ares[areslen++] = cp ; - - resolve_free(wres) ; - } - - unsigned int l[graph.mlen], c = 0, pos = 0, idx = 0 ; - - idx = graph_hash_vertex_get_id(&graph, treename) ; - - if (!visit[idx]) { - /** avoid double entry */ - list[napid++] = idx ; - visit[idx] = 1 ; - - } - - /** find dependencies of the tree from the graph, do it recursively */ - c = graph_matrix_get_edge_g_sorted_list(l, &graph, treename, requiredby, 1) ; - - /** append to the list to deal with */ - for (; pos < c ; pos++) { - if (!visit[l[pos]]) { - list[napid++] = l[pos] ; - visit[l[pos]] = 1 ; - } - } - if (found) - break ; - } - - pidtree_t apidt[graph.mlen] ; - - pares = ares ; - pareslen = &areslen ; - - pidtree_init_array(list, napid, apidt, &graph, ares, areslen, info, requiredby) ; - - if (shut) { - - pid_t pid ; - int wstat = 0 ; - - pid = fork() ; - - if (pid < 0) - log_dieusys(LOG_EXIT_SYS,"fork") ; - - if (!pid) { - - all_redir_fd() ; - - } else { - - if (waitpid_nointr(pid,&wstat, 0) < 0) - log_dieusys(LOG_EXIT_SYS,"wait for child") ; - - if (wstat) - log_die(LOG_EXIT_SYS,"child fail") ; - - r = 1 ; - - goto end ; - } - } - - if (!areslen) { - log_warn("empty trees -- nothing to do") ; - r = 0 ; - goto end ; - } - - r = waitit(apidt, what, &graph, &deadline, info) ; - - end: - - if (shut) { - - while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0) - if (fd >= 3) - break ; - - dup2 (fd,0) ; - dup2 (fd,1) ; - dup2 (fd,2) ; - fd_close(fd) ; - } - - graph_free_all(&graph) ; - stralloc_free(&sa) ; - tree_resolve_array_free(ares, areslen) ; - - return r ; -}