Welcome to little lamb

Code » anopa » commit dbc69f9

start: Fix handling already up but not ready services

author Olivier Brunel
2015-11-10 18:57:59 UTC
committer Olivier Brunel
2015-11-12 17:04:19 UTC
parent fc82d1b06712b613afda37211d3090e09430e14f

start: Fix handling already up but not ready services

If a service that supports readiness was already up but not yet ready, it would
be "ignored" (as "Already up"). We now properly include it in the "transaction"
and wait for it to become ready; "Already up" only applying when ready.

src/anopa/start-stop.c +17 -5
src/libanopa/exec_longrun.c +20 -4
src/libanopa/service.c +22 -8

diff --git a/src/anopa/start-stop.c b/src/anopa/start-stop.c
index 7cce2f7..e3c1c50 100644
--- a/src/anopa/start-stop.c
+++ b/src/anopa/start-stop.c
@@ -963,11 +963,23 @@ exec_cb (int si, aa_evt evt, pid_t pid)
         /* ugly hack thing; see aa_exec_service() */
         case 0:
             clear_draw ();
-            if (!(pid & AA_MODE_IS_DRY))
-                aa_bs_noflush (AA_OUT,
-                        (pid & AA_MODE_START) ? "Starting " : "Stopping ");
-            aa_bs_noflush (AA_OUT, aa_service_name (aa_service (si)));
-            aa_bs_flush (AA_OUT, (pid & AA_MODE_IS_DRY) ? "\n" : "...\n");
+            if ((pid & AA_MODE_START) && !(pid & AA_MODE_IS_DRY)
+                    /* see aa_ensure_service_loaded() for more */
+                    && s->st.type == AA_TYPE_LONGRUN
+                    && s->gets_ready
+                    && s->st.code == ERR_ALREADY_UP)
+            {
+                aa_bs_noflush (AA_OUT, aa_service_name (s));
+                aa_bs_flush (AA_OUT, ": Getting ready...\n");
+            }
+            else
+            {
+                if (!(pid & AA_MODE_IS_DRY))
+                    aa_bs_noflush (AA_OUT,
+                            (pid & AA_MODE_START) ? "Starting " : "Stopping ");
+                aa_bs_noflush (AA_OUT, aa_service_name (aa_service (si)));
+                aa_bs_flush (AA_OUT, (pid & AA_MODE_IS_DRY) ? "\n" : "...\n");
+            }
             break;
 
         case AA_EVT_STARTING:
diff --git a/src/libanopa/exec_longrun.c b/src/libanopa/exec_longrun.c
index d72b994..a17dc2e 100644
--- a/src/libanopa/exec_longrun.c
+++ b/src/libanopa/exec_longrun.c
@@ -76,10 +76,13 @@ _exec_longrun (int si, aa_mode mode)
     {
         tain_now_g ();
 
-        already = 1;
-        /* already there; unsubcribe */
-        ftrigr_unsubscribe_g (&_aa_ft, s->ft_id, &deadline);
-        s->ft_id = 0;
+        if (!is_start || !s->gets_ready || st6.flagready)
+        {
+            already = 1;
+            /* already there; unsubcribe */
+            ftrigr_unsubscribe_g (&_aa_ft, s->ft_id, &deadline);
+            s->ft_id = 0;
+        }
 
         /* make sure our status is correct, and timestamped before s6 */
         s->st.event = (is_start) ? AA_EVT_STARTING : AA_EVT_STOPPING;
@@ -97,6 +100,18 @@ _exec_longrun (int si, aa_mode mode)
          * happening right now. Also in STOP_ALL this sends the 'x' event to
          * s6-supervise as needed as well.
          */
+
+        if (is_start && s->gets_ready)
+            /* However, on START sending the command is possibly problematic
+             * regarding (externally set) readiness.
+             * E.g. if the service is ready, and readiness was set externally
+             * (e.g. via aa-setready) it would result in said readiness being
+             * "lost" when s6-supervise rewrites the status file.
+             * Similarly, if readiness was originally set via s6-supervise
+             * (notification-fd) and then unset externally, it could come back
+             * if s6-supervise was to rewrite the status file.
+             */
+            event = NULL;
     }
     else
     {
@@ -117,6 +132,7 @@ _exec_longrun (int si, aa_mode mode)
         }
     }
 
+    if (event)
     {
         char dir[l_sn + 1 + sizeof (S6_SUPERVISE_CTLDIR) + 8];
         int r;
diff --git a/src/libanopa/service.c b/src/libanopa/service.c
index eda7af5..1c1d940 100644
--- a/src/libanopa/service.c
+++ b/src/libanopa/service.c
@@ -248,6 +248,8 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_autoload_cb al_
             {
                 chk_st = 0;
                 is_up = st6.pid && !st6.flagfinishing;
+                if (is_up && aa_service (si)->gets_ready && st6.flagready)
+                    is_up = 2;
             }
             else if (errno != ENOENT)
             {
@@ -267,15 +269,27 @@ aa_ensure_service_loaded (int si, aa_mode mode, int no_wants, aa_autoload_cb al_
          * the right state, so skip that bit then */
         if (!(mode & AA_MODE_IS_DRY_FULL))
         {
-            if ((mode & AA_MODE_START) && is_up)
+            if (mode & AA_MODE_START)
             {
-                /* if already good, we "fail" because there's no need to load the
-                 * service, it's already good. This error will be silently ignored
-                 * */
-                aa_service (si)->ls = AA_LOAD_FAIL;
-                /* this isn't actually true, but we won't save it to file */
-                svst->code = ERR_ALREADY_UP;
-                return -ERR_ALREADY_UP;
+                /* if it is a longrun w/ readiness support that isn't yet ready,
+                 * we load the service to add it to the "transaction" since
+                 * we'll need to wait for its readyness.
+                 * We set the code to 0 or ERR_ALREADY_UP to indicate whether it
+                 * was alreayd up or not, so when starting it (in exec_cb) it
+                 * can actually be said "Starting" or "Getting ready" as needed.
+                 */
+                if (svst->type == AA_TYPE_LONGRUN && aa_service (si)->gets_ready && is_up < 2)
+                    svst->code = (is_up == 1) ? ERR_ALREADY_UP : 0;
+                else if (is_up)
+                {
+                    /* if already good, we "fail" because there's no need to
+                     * load the service, it's already good. This error will be
+                     * silently ignored */
+                    aa_service (si)->ls = AA_LOAD_FAIL;
+                    /* this isn't actually true, but we won't save it to file */
+                    svst->code = ERR_ALREADY_UP;
+                    return -ERR_ALREADY_UP;
+                }
             }
             else if ((mode & (AA_MODE_STOP | AA_MODE_STOP_ALL)) && !is_up)
             {