From 8cc581b465820800cc004b48a40200877fe09098 Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Sun, 13 Mar 2022 18:58:00 +1100 Subject: [PATCH] handle start/down of trees asynchronously except for dependency/requiredby. At least it build --- src/lib66/exec/ssexec_all.c | 673 ++++++++++++++++++++++++++---------- 1 file changed, 483 insertions(+), 190 deletions(-) diff --git a/src/lib66/exec/ssexec_all.c b/src/lib66/exec/ssexec_all.c index be758090..1a1e257c 100644 --- a/src/lib66/exec/ssexec_all.c +++ b/src/lib66/exec/ssexec_all.c @@ -27,20 +27,61 @@ #include <oblibs/sastr.h> #include <oblibs/obgetopt.h> #include <oblibs/files.h> +#include <oblibs/graph.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/iopause.h> #include <66/ssexec.h> #include <66/constants.h> #include <66/tree.h> #include <66/utils.h>//scandir_ok #include <66/db.h> +#include <66/graph.h> #include <s6-rc/s6rc-servicedir.h> + +#define FLAGS_STARTING 1 // starting not really up +#define FLAGS_STOPPING 2 // stopping not really down +#define FLAGS_UP 3 // really up +#define FLAGS_DOWN 4 // really down +/* +#define FLAGS_BLOCK 5 // all deps are not up/down +#define FLAGS_UNBLOCK 6 // all deps up/down +#define FLAGS_FATAL 7 // process crashed +#define FLAGS_EXITED 8 // process exited +*/ + +/** return 1 if set, else 0*/ +#define FLAGS_ISSET(has, want) \ + ((~(has) & (want)) == 0) + +typedef struct pidvertex_s pidvertex_t, *pidvertex_t_ref ; +struct pidvertex_s +{ + pid_t pid ; + 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 +} ; +#define PIDINDEX_ZERO { 0, 0, 0, 0, 0 } + +static pidvertex_t *apidvertex ; +static unsigned int napid = 0 ; +static unsigned int npid = 0 ; +static int flag ; +static int flag_run ; + +static void async(unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph) ; +static int unsupervise(ssexec_t *info, int what) ; + static inline unsigned int lookup (char const *const *table, char const *signal) { log_flow() ; @@ -54,113 +95,158 @@ static inline unsigned int parse_signal (char const *signal) { log_flow() ; - static char const *const signal_table[] = - { + 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 ; + unsigned int i = lookup(signal_table, signal) ; + if (!signal_table[i]) log_usage(usage_all) ; + return i ; } -int all_doit(ssexec_t *info, unsigned int what, char const *const *envp) +static void redir_fd(void) { log_flow() ; - int r ; + int fd ; + while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0) { - stralloc salist = STRALLOC_ZERO ; - char const *exclude[2] = { SS_LIVETREE_INIT, 0 } ; + if (fd >= 3) + break ; + } - char ownerstr[UID_FMT] ; - size_t ownerlen = uid_fmt(ownerstr,info->owner) ; - ownerstr[ownerlen] = 0 ; + dup2 (fd,0) ; + dup2 (fd,1) ; + dup2 (fd,2) ; + fd_close(fd) ; - char src[info->live.len + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len + 1 + SS_LIVETREE_INIT_LEN + 1] ; - auto_strings(src,info->live.s,SS_STATE,"/",ownerstr,"/",info->treename.s,"/",SS_LIVETREE_INIT) ; + if (setsid() < 0) + log_dieusys(LOG_EXIT_SYS,"setsid") ; - r = scan_mode(src,S_IFREG) ; - if (r == -1) log_die(LOG_EXIT_SYS,src," conflicted format") ; - if (!r) { - log_warn ("uninitialized tree: ", info->treename.s) ; - goto freed ; - } + if ((chdir("/")) < 0) + log_dieusys(LOG_EXIT_SYS,"chdir") ; + + ioctl(0,TIOCSCTTY,1) ; + + umask(022) ; +} - src[info->live.len + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len] = 0 ; - if (!sastr_dir_get(&salist,src,exclude,S_IFREG)) - log_dieusys(LOG_EXIT_SYS,"get contents of directory: ",src) ; +static int doit(ssexec_t *info, char const *treename, unsigned int what) +{ + log_flow() ; + + int r, e = 1 ; - if (salist.len) { - size_t pos = 0, len = sastr_len(&salist) ; - int n = what == 2 ? 3 : 2 ; - int nargc = n + len ; - char const *newargv[nargc] ; - unsigned int m = 0 ; + info->treename.len = 0 ; - newargv[m++] = "fake_name" ; - if (what == 2) - newargv[m++] = "-u" ; + if (!auto_stra(&info->treename, treename)) + log_die_nomem("stralloc") ; - FOREACH_SASTR(&salist,pos) { + info->tree.len = 0 ; - newargv[m++] = salist.s + pos ; - } + if (!auto_stra(&info->tree, treename)) + log_die_nomem("stralloc") ; + + r = tree_sethome(info) ; + if (r <= 0) + log_warnu_return(LOG_EXIT_ONE, "find tree: ", info->treename.s) ; + + if (!tree_get_permissions(info->tree.s, info->owner)) + log_warn_return(LOG_EXIT_ONE, "You're not allowed to use the tree: ", info->tree.s) ; + + } - newargv[m++] = 0 ; + if (!tree_isinitialized(info->base.s, info->treename.s)) { if (!what) { - if (ssexec_start(nargc,newargv,envp,info)) - goto err ; + int nargc = 3 ; + char const *newargv[nargc] ; + unsigned int m = 0 ; + + newargv[m++] = "fake_name" ; + newargv[m++] = "b" ; + newargv[m++] = 0 ; + + if (ssexec_init(nargc, newargv, (char const *const *)environ, info)) + log_warnu_return(LOG_EXIT_ONE, "initiate services of tree: ", info->treename.s) ; + + log_trace("reload scandir: ", info->scandir.s) ; + if (scandir_send_signal(info->scandir.s, "h") <= 0) + log_warnu_return(LOG_EXIT_ONE, "reload scandir: ", info->scandir.s) ; } else { - if (ssexec_stop(nargc,newargv,envp,info)) - goto err ; + log_warn ("uninitialized tree: ", info->treename.s) ; + goto freed ; } } - else - log_info("Empty tree: ",info->treename.s," -- nothing to do") ; - freed: - stralloc_free(&salist) ; - return 1 ; - err: - stralloc_free(&salist) ; - return 0 ; -} + if (what == 2) { -static void all_redir_fd(void) -{ - log_flow() ; + if (unsupervise(info, what)) + goto err ; - 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) ; + } else { - if (setsid() < 0) - log_dieusys(LOG_EXIT_SYS,"setsid") ; + char const *exclude[1] = { 0 } ; + char ownerstr[UID_FMT] ; + size_t ownerlen = uid_fmt(ownerstr, info->owner) ; + ownerstr[ownerlen] = 0 ; - if ((chdir("/")) < 0) - log_dieusys(LOG_EXIT_SYS,"chdir") ; + stralloc salist = STRALLOC_ZERO ; - ioctl(0,TIOCSCTTY,1) ; + char src[info->live.len + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len + 1] ; - umask(022) ; + auto_strings(src, info->live.s, SS_STATE, "/", ownerstr, "/", info->treename.s) ; + + if (!sastr_dir_get(&salist, src, exclude, S_IFREG)) + log_warnusys_return(LOG_EXIT_ONE, "get contents of directory: ", src) ; + + if (salist.len) { + + size_t pos = 0, len = sastr_len(&salist) ; + int n = what == 2 ? 3 : 2 ; + int nargc = n + len ; + char const *newargv[nargc] ; + unsigned int m = 0 ; + + newargv[m++] = "fake_name" ; + if (what == 2) + newargv[m++] = "-u" ; + + FOREACH_SASTR(&salist, pos) + newargv[m++] = salist.s + pos ; + + newargv[m++] = 0 ; + + if (!what) { + + if (ssexec_start(nargc, newargv, (char const *const *)environ, info)) + goto err ; + + } else { + + if (ssexec_stop(nargc, newargv, (char const *const *)environ, info)) + goto err ; + } + + } else log_info("Empty tree: ", info->treename.s, " -- nothing to do") ; + + stralloc_free(&salist) ; + } + + freed: + e = 0 ; + err: + return e ; } -void all_unsupervise(ssexec_t *info, char const *const *envp,int what) +static int unsupervise(ssexec_t *info, int what) { log_flow() ; @@ -168,75 +254,305 @@ void all_unsupervise(ssexec_t *info, char const *const *envp,int what) char const *exclude[1] = { 0 } ; char ownerstr[UID_FMT] ; - size_t ownerlen = uid_fmt(ownerstr,info->owner) ; + size_t ownerlen = uid_fmt(ownerstr, info->owner) ; ownerstr[ownerlen] = 0 ; stralloc salist = STRALLOC_ZERO ; /** set what we need */ char prefix[info->treename.len + 2] ; - auto_strings(prefix,info->treename.s,"-") ; + auto_strings(prefix, info->treename.s, "-") ; char livestate[info->live.len + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len + 1] ; - auto_strings(livestate,info->live.s,SS_STATE + 1,"/",ownerstr,"/",info->treename.s) ; + auto_strings(livestate, info->live.s, SS_STATE + 1, "/", ownerstr, "/", info->treename.s) ; /** bring down service */ - if (!all_doit(info,what,envp)) + if (all_doit(info, info->treename.s, what)) log_warnusys("stop services") ; - if (db_find_compiled_state(info->livetree.s,info->treename.s) >=0) - { + if (db_find_compiled_state(info->livetree.s, info->treename.s) >=0) { + salist.len = 0 ; char livetree[newlen + info->treename.len + SS_SVDIRS_LEN + 1] ; - auto_strings(livetree,info->livetree.s,"/",info->treename.s,SS_SVDIRS) ; + auto_strings(livetree, info->livetree.s, "/", info->treename.s, SS_SVDIRS) ; - if (!sastr_dir_get(&salist,livetree,exclude,S_IFDIR)) log_dieusys(LOG_EXIT_SYS,"get service list at: ",livetree) ; + if (!sastr_dir_get(&salist,livetree,exclude,S_IFDIR)) + log_warnusys_return(LOG_EXIT_ONE, "get service list at: ", livetree) ; livetree[newlen + info->treename.len] = 0 ; pos = 0 ; FOREACH_SASTR(&salist,pos) { - s6rc_servicedir_unsupervise(livetree,prefix,salist.s + pos,0) ; + s6rc_servicedir_unsupervise(livetree, prefix, salist.s + pos, 0) ; } char *realsym = realpath(livetree, 0) ; if (!realsym) - log_dieusys(LOG_EXIT_SYS,"find realpath of: ",livetree) ; + log_warnusys_return(LOG_EXIT_ONE, "find realpath of: ", livetree) ; if (rm_rf(realsym) == -1) - log_dieusys(LOG_EXIT_SYS,"remove: ", realsym) ; + log_warnusys_return(LOG_EXIT_ONE, "remove: ", realsym) ; free(realsym) ; if (rm_rf(livetree) == -1) - log_dieusys(LOG_EXIT_SYS,"remove: ", livetree) ; + log_warnusys_return(LOG_EXIT_ONE, "remove: ", livetree) ; /** remove the symlink itself */ unlink_void(livetree) ; } if (scandir_send_signal(info->scandir.s,"h") <= 0) - log_dieusys(LOG_EXIT_SYS,"reload scandir: ",info->scandir.s) ; + log_warnusys_return(LOG_EXIT_ONE, "reload scandir: ", info->scandir.s) ; /** remove /run/66/state/uid/treename directory */ - log_trace("delete: ",livestate,"..." ) ; + log_trace("delete: ", livestate, "..." ) ; if (rm_rf(livestate) < 0) - log_dieusys(LOG_EXIT_SYS,"delete ",livestate) ; + log_warnusys_return(LOG_EXIT_ONE, "delete ", livestate) ; - log_info("Unsupervised successfully tree: ",info->treename.s) ; + log_info("Unsupervised successfully tree: ", info->treename.s) ; stralloc_free(&salist) ; + + return 0 ; } -int ssexec_all(int argc, char const *const *argv,char const *const *envp,ssexec_t *info) +static pidvertex_t pidvertex_init(unsigned int len) { + log_flow() ; + + pidvertex_t pidv = PIDINDEX_ZERO ; + + pidv.edge = (unsigned int *)malloc(len*sizeof(unsigned int)) ; + + graph_array_init_single(pidv.edge, len) ; + + return pidv ; +} + +static void pidvertex_free(pidvertex_t *pidv) +{ + free(pidv->edge) ; +} + +static void pidvertex_init_array(pidvertex_t *apidvertex, graph_t *g, unsigned int *list, unsigned int count, ssexec_t *info, uint8_t requiredby) +{ + log_flow() ; + + int r = -1 ; + size_t pos = 0 ; + + for (; pos < count ; pos++) { + + char *name = g->data.s + genalloc_s(graph_hash_t,&g->hash)[list[pos]].vertex ; + + pidvertex_t pidv = pidvertex_init(g->mlen) ; - int r, what, shut = 0, fd ; + pidv.nedge = graph_matrix_get_edge_g_sorted_list(pidv.edge, g, name, requiredby) ; - size_t statesize, pos = 0 ; + if (pidv.nedge < 0) + log_dieu(LOG_EXIT_SYS,"get sorted ", requiredby ? "required by" : "dependency", " list of tree: ", name) ; - stralloc contents = STRALLOC_ZERO ; + pidv.vertex = list[pos] ; + + if (pidv.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) + pidv.state |= FLAGS_UP ; + else + pidv.state |= FLAGS_DOWN ; + + apidvertex[pos] = pidv ; + } + +} + +static void pidvertex_array_free(pidvertex_t *apidvertex, unsigned int len) +{ + log_flow() ; + + size_t pos = 0 ; + + for(; pos < len ; pos++) + pidvertex_free(&apidvertex[pos]) ; + +} + +static int pidvertex_get_id(pidvertex_t *apidvertex, unsigned int id) +{ + log_flow() ; + + unsigned int pos = 0 ; + + for (; pos < napid ; pos++) { + if (apidvertex[pos].vertex == id) + return (unsigned int) pos ; + } + return -1 ; +} + +static void async_deps(unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph) +{ + log_flow() ; + + unsigned int pos = 0 ; + while (apidvertex[i].nedge) { + /** TODO: the pidvertex_get_id() function make a loop + * through the apidvertex array to find the corresponding + * index of the edge at the apidvertex array. + * This is clearly a waste of time and need to be optimized. */ + unsigned int id = pidvertex_get_id(apidvertex, apidvertex[i].edge[pos]) ; + if (id < 0) + log_dieu(LOG_EXIT_SYS, "get apidvertex id -- please make a bug report") ; + async(id, what, info, graph) ; + apidvertex[i].nedge-- ; + pos++ ; + } + + +} + +static void async(unsigned int i, unsigned int what, ssexec_t *info, graph_t *graph) +{ + /** + * @i: apidvertex array index + * */ + + log_flow() ; + + int r ; + pid_t pid ; + char *treename = graph->data.s + genalloc_s(graph_hash_t,&graph->hash)[apidvertex[i].vertex].vertex ; + + if (FLAGS_ISSET(apidvertex[i].state, flag) || FLAGS_ISSET(apidvertex[i].state, flag_run)) { + + pid = fork() ; + + if (pid < 0) + log_dieusys(LOG_EXIT_SYS, "fork") ; + + if (!pid) { + + if (!apidvertex[i].nedge) { + /** Mark as processing */ + apidvertex[i].state |= flag_run ; + r = doit(info, treename, what) ; + _exit(r) ; + + } else { + + async_deps(i, what, info, graph) ; + } + } + + apidvertex[i].pid = pid ; + + } else { + + log_trace("skipping: ", treename, " -- already ", FLAGS_ISSET(flag,FLAGS_DOWN) ? "down" : "up") ; + } + + return ; +} + +static int handle_signal(pidvertex_t *apidvertex) +{ + log_flow() ; + + int ok = 1 ; + + for (;;) { + + switch (selfpipe_read()) { + + case -1 : log_warnusys_return(LOG_EXIT_ZERO,"selfpipe_read") ; + case 0 : return ok ; + case SIGCHLD : + + for (;;) { + + unsigned int j = 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 (; j < npid ; j++) + if (apidvertex[j].pid == r) + break ; + + if (j < npid) { + + if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) { + + apidvertex[j].state &= ~flag & ~flag_run ; + + } else { + + ok = 0 ; + apidvertex[j].state &= ~flag & ~flag_run ; + } + + apidvertex[j] = apidvertex[--npid] ; + } + } + break ; + case SIGTERM : + case SIGINT : + log_warn("received SIGINT, aborting service transition") ; + break ; + default : log_warn("unexpected data in selfpipe") ; + } + } + return ok ; +} + +static int waitit(int spfd, pidvertex_t *apidvertex, graph_t *graph, unsigned int what, tain *deadline, ssexec_t *info) +{ + iopause_fd x = { .fd = spfd, .events = IOPAUSE_READ } ; + unsigned int e = 1, pos = 0 ; + int r ; + npid = napid ; + + for (; pos < npid ; pos++) + async(pos, what, info, graph) ; + + while (npid) { + + r = iopause_g(&x, 1, deadline) ; + if (r < 0) + log_dieusys(LOG_EXIT_SYS, "iopause") ; + if (!r) + log_die(LOG_EXIT_SYS,"time out") ; + if (!handle_signal(apidvertex)) + e = 0 ; + } + return e ; +} + +int ssexec_all(int argc, char const *const *argv,char const *const *envp, ssexec_t *info) +{ + + int r, shut = 0, fd ; + tain deadline ; + unsigned int what ; + + uint8_t requiredby = 0 ; + graph_t graph = GRAPH_ZERO ; { subgetopt l = SUBGETOPT_ZERO ; @@ -257,148 +573,125 @@ int ssexec_all(int argc, char const *const *argv,char const *const *envp,ssexec_ if (argc != 1) log_usage(usage_all) ; + if (info->timeout) + tain_from_millisecs(&deadline, info->timeout) ; + else + deadline = tain_infinite_relative ; + what = parse_signal(*argv) ; - if ((scandir_ok(info->scandir.s)) <= 0) - log_die(LOG_EXIT_SYS,"scandir: ", info->scandir.s," is not running") ; + if (what) { - char ste[info->base.len + SS_SYSTEM_LEN + SS_STATE_LEN + 1] ; - auto_strings(ste,info->base.s,SS_SYSTEM,SS_STATE) ; + requiredby = 1 ; + flag = FLAGS_UP ; + flag_run = FLAGS_STOPPING ; - r = scan_mode(ste,S_IFREG) ; - if (r < 0) log_die(LOG_EXIT_SYS,"conflict format for: ",ste) ; - if (!r) log_dieusys(LOG_EXIT_SYS,"find: ",ste) ; + } else { - /** only one tree?*/ - if (info->treename.len) - { - if (!auto_stra(&contents,info->treename.s)) - log_die_nomem("stralloc") ; + flag = FLAGS_DOWN ; + flag_run = FLAGS_STARTING ; } - else - { - statesize = file_get_size(ste) ; - r = openreadfileclose(ste,&contents,statesize) ; - if(!r) log_dieusys(LOG_EXIT_SYS,"open: ", ste) ; + if ((scandir_ok(info->scandir.s)) <= 0) + log_die(LOG_EXIT_SYS,"scandir: ", info->scandir.s," is not running") ; - /** ensure that we have an empty line at the end of the string*/ - if (!stralloc_cats(&contents,"\n") || - !stralloc_0(&contents)) log_die_nomem("stralloc") ; + if (!graph_build_g(&graph, info->base.s, info->treename.s, DATA_TREE)) + log_dieu(LOG_EXIT_SYS,"build the graph") ; - if (!sastr_clean_element(&contents)) { - log_info("nothing to do") ; - goto end ; - } + /** initialize and allocate apidvertex array */ - } + pidvertex_t apidv[graph.mlen] ; - if (shut) - { - pid_t dpid ; - int wstat = 0 ; + apidvertex = apidv ; - dpid = fork() ; + /** only on tree */ + if (info->treename.len) { - if (dpid < 0) log_dieusys(LOG_EXIT_SYS,"fork") ; - else if (dpid > 0) - { - if (waitpid_nointr(dpid,&wstat, 0) < 0) - log_dieusys(LOG_EXIT_SYS,"wait for child") ; + unsigned int *alist ; - if (wstat) - log_die(LOG_EXIT_SYS,"child fail") ; + alist = (unsigned int *)malloc(graph.mlen*sizeof(unsigned int)) ; - goto end ; - } - else all_redir_fd() ; - } + graph_array_init_single(alist, graph.mlen) ; - /** Down/unsupervise process? reverse in that case to respect tree start order*/ - if (what) - if (!sastr_reverse(&contents)) log_dieu(LOG_EXIT_SYS,"reserve tree order") ; + napid = graph_matrix_get_edge_g_sorted_list(alist, &graph, info->treename.s, requiredby) ; - FOREACH_SASTR(&contents,pos) { + if (napid < 0) + log_dieu(LOG_EXIT_SYS, "get ", requiredby ? "required" : "dependencies", " sorted list of: ", info->treename.s) ; - info->treename.len = 0 ; + alist[napid++] = (unsigned int)graph_hash_vertex_get_id(&graph, info->treename.s) ; - if (!auto_stra(&info->treename,contents.s + pos)) - log_die_nomem("stralloc") ; + pidvertex_init_array(apidvertex, &graph, alist, napid, info, requiredby) ; - info->tree.len = 0 ; + free(alist) ; - if (!auto_stra(&info->tree,contents.s + pos)) - log_die_nomem("stralloc") ; - /** - * - * - * - * - * - * - * - * Attention ici avec le nouveau format de tree_sethome() - * - * - * - * - * - * - * - * - * - * - * - * - * */ - r = tree_sethome(info) ; - if (r <= 0) log_dieusys(LOG_EXIT_SYS,"find tree: ", info->treename.s) ; + } else { - if (!tree_get_permissions(info->tree.s,info->owner)) - log_die(LOG_EXIT_USER,"You're not allowed to use the tree: ",info->tree.s) ; + napid = graph.sort_count ; - if (!what) - { - int nargc = 3 ; - char const *newargv[nargc] ; - unsigned int m = 0 ; + pidvertex_init_array(apidvertex, &graph, graph.sort, graph.sort_count, info, requiredby) ; + } - newargv[m++] = "fake_name" ; - newargv[m++] = "b" ; - newargv[m++] = 0 ; + if (shut) { + + pid_t pid ; + int wstat = 0 ; - if (ssexec_init(nargc,newargv,envp,info)) - log_dieu(LOG_EXIT_SYS,"initiate services of tree: ",info->treename.s) ; + pid = fork() ; - log_trace("reload scandir: ",info->scandir.s) ; - if (scandir_send_signal(info->scandir.s,"h") <= 0) - log_dieusys(LOG_EXIT_SYS,"reload scandir: ",info->scandir.s) ; - } + if (pid < 0) + log_dieusys(LOG_EXIT_SYS,"fork") ; - if (what < 2) { + if (!pid) { - if (!all_doit(info,what,envp)) - log_dieu(LOG_EXIT_SYS,(what) ? "start" : "stop" , " services of tree: ",info->treename.s) ; + redir_fd() ; } else { - all_unsupervise(info,envp,what) ; + 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 ; } } + + 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(SIGTERM)) + log_dieusys(LOG_EXIT_SYS, "selfpipe_trap") ; + + r = waitit(spfd, apidvertex, &graph, what, &deadline, info) ; + end: - if (shut) - { + selfpipe_finish() ; + + if (shut) { + while((fd = open("/dev/tty",O_RDWR|O_NOCTTY)) >= 0) - { - if (fd >= 3) break ; - } + if (fd >= 3) + break ; + dup2 (fd,0) ; dup2 (fd,1) ; dup2 (fd,2) ; fd_close(fd) ; } - stralloc_free(&contents) ; + graph_free_all(&graph) ; + pidvertex_array_free(apidvertex, napid) ; - return 0 ; + + return (!r) ? 111 : 0 ; } -- GitLab