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