supervision - discussion about system services, daemon supervision, init, runlevel management, and tools such as s6 and runit
 help / color / mirror / Atom feed
From: Charles Duffy <cduffy@spamcop.net>
Subject: Re: new "sv status" flags and exit-tracking patch, and misc.
Date: Mon, 19 Sep 2005 14:13:30 -0500	[thread overview]
Message-ID: <dgn2ks$usn$1@sea.gmane.org> (raw)
In-Reply-To: <dgmnjf$o3s$1@sea.gmane.org>

[-- Attachment #1: Type: text/plain, Size: 477 bytes --]

Charles Duffy wrote:
> Attached is a patch which attempts to stick to the items we agreed on.

Erk -- actually, that one was a little too overreaching as well, since 
it changed "sv status" to provide the last exit status of finish (if 
curently in run) or run (if currently in finish), if that program exited 
with a status other than 0. Since the requested spec was that the output 
of "sv status" (when called without flags) not be altered... well, 
here's another attempt.

[-- Attachment #2: runit-1.3.1.new-smaller.patch --]
[-- Type: text/x-patch, Size: 10284 bytes --]

diff -ru runit-1.3.1/src/runsv.c runit-1.3.1.new/src/runsv.c
--- runit-1.3.1/src/runsv.c	2005-08-24 15:14:39.427019666 -0500
+++ runit-1.3.1.new/src/runsv.c	2005-09-19 10:00:44.490650789 -0500
@@ -1,4 +1,5 @@
 #include <sys/types.h>
+#include <sys/wait.h>
 #include <sys/stat.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -39,6 +40,11 @@
 #define W_UP 0
 #define W_DOWN 1
 #define W_EXIT 2
+/* exit type */
+#define ET_NOEXIT 0
+#define ET_NORMAL 1
+#define ET_SIGNAL 2
+#define ET_UNKNOWN 127
 
 struct svdir {
   int pid;
@@ -50,6 +56,10 @@
   int fdcontrol;
   int fdcontrolwrite;
   int islog;
+  unsigned char runexit_type;
+  unsigned char runexit_val;
+  unsigned char finexit_type;
+  unsigned char finexit_val;
 };
 struct svdir svd[2];
 
@@ -86,7 +96,7 @@
 void update_status(struct svdir *s) {
   unsigned long l;
   int fd;
-  char status[20];
+  char status[24];
   char bspace[64];
   buffer b;
   char spid[FMT_ULONG];
@@ -180,6 +190,10 @@
   else
     status[18] =0;
   status[19] =s->state;
+  status[20] =s->runexit_type;
+  status[21] =s->runexit_val;
+  status[22] =s->finexit_type;
+  status[23] =s->finexit_val;
   if ((fd =open_trunc("supervise/status.new")) == -1) {
     warn("unable to open supervise/status.new");
     return;
@@ -399,6 +413,10 @@
   svd[0].ctrl =C_NOOP;
   svd[0].want =W_UP;
   svd[0].islog =0;
+  svd[0].runexit_type =0;
+  svd[0].runexit_val =0;
+  svd[0].finexit_type =0;
+  svd[0].finexit_val =0;
   svd[1].pid =0;
   taia_now(&svd[0].start);
   if (stat("down", &s) != -1) svd[0].want =W_DOWN;
@@ -416,6 +434,10 @@
       svd[1].ctrl =C_NOOP;
       svd[1].want =W_UP;
       svd[1].islog =1;
+      svd[1].runexit_type =0;
+      svd[1].runexit_val =0;
+      svd[1].finexit_type =0;
+      svd[1].finexit_val =0;
       taia_now(&svd[1].start);
       if (stat("log/down", &s) != -1)
         svd[1].want =W_DOWN;
@@ -540,13 +562,39 @@
         svd[0].pid =0;
         pidchanged =1;
         svd[0].ctrl &=~C_TERM;
-        if (svd[0].state != S_FINISH)
+        if (svd[0].state != S_FINISH) {
+          if (WIFEXITED(wstat)) {
+            svd[0].runexit_type = ET_NORMAL;
+            svd[0].runexit_val = WEXITSTATUS(wstat);
+          } else if (WIFSIGNALED(wstat)) {
+            svd[0].runexit_type = ET_SIGNAL;
+            svd[0].runexit_val = WTERMSIG(wstat);
+          } else if(WIFSTOPPED(wstat)) {
+            /* do nothing */
+          } else {
+            svd[0].runexit_type = ET_UNKNOWN;
+            svd[0].runexit_val = 0;
+          }
           if ((fd =open_read("finish")) != -1) {
             close(fd);
             svd[0].state =S_FINISH;
             update_status(&svd[0]);
             continue;
           }
+        } else {
+          if (WIFEXITED(wstat)) {
+            svd[0].finexit_type = ET_NORMAL;
+            svd[0].finexit_val = WEXITSTATUS(wstat);
+          } else if (WIFSIGNALED(wstat)) {
+            svd[0].finexit_type = ET_SIGNAL;
+            svd[0].finexit_val = WTERMSIG(wstat);
+          } else if(WIFSTOPPED(wstat)) {
+            /* do nothing */
+          } else {
+            svd[0].finexit_type = ET_UNKNOWN;
+            svd[0].finexit_val = 0;
+          }
+        }
         svd[0].state =S_DOWN;
         taia_uint(&deadline, 1);
         taia_add(&deadline, &svd[0].start, &deadline);
diff -ru runit-1.3.1/src/sv.c runit-1.3.1.new/src/sv.c
--- runit-1.3.1/src/sv.c	2005-08-24 15:14:39.901422814 -0500
+++ runit-1.3.1.new/src/sv.c	2005-09-19 14:08:48.592763295 -0500
@@ -1,5 +1,6 @@
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <string.h>
 #include <unistd.h>
 #include "str.h"
 #include "strerr.h"
@@ -48,7 +49,7 @@
 int (*cbk)(char*) =0;
 
 int curdir, fd, r;
-char svstatus[20];
+char svstatus[24];
 char sulong[FMT_ULONG];
 
 void usage() {
@@ -63,6 +64,10 @@
   strerr_warn4(FATAL, m1, m2, ": ", &strerr_sys);
   done(lsb ? 151 : 100);
 }
+void fatal2x(char *m1, char *m2) {
+  strerr_warn3(FATAL, m1, m2, 0);
+  done(lsb ? 151 : 100);
+}
 void out(char *p, char *m1) {
   buffer_puts(buffer_1, p);
   buffer_puts(buffer_1, *service);
@@ -86,6 +91,124 @@
 void outs2(const char *s) { buffer_puts(buffer_2, s); }
 void flush2(const char *s) { outs2(s); buffer_flush(buffer_2); }
 
+typedef int (*flagprint_fn)();
+typedef struct statusflag {
+  char flagchar;
+  flagprint_fn printfunc;
+} statusflag_t;
+
+#define MAX_FLAGPRINTFUNCS 16
+flagprint_fn flagprintfuncs[MAX_FLAGPRINTFUNCS] = { 0, };
+int flagprintfunccount = 0;  /* number of printfuncs currently requested */
+
+static inline int getPID() {
+  int pid =(unsigned char) svstatus[15];
+  pid <<=8; pid +=(unsigned char)svstatus[14];
+  pid <<=8; pid +=(unsigned char)svstatus[13];
+  pid <<=8; pid +=(unsigned char)svstatus[12];
+  return pid;
+}
+
+static int printULong(unsigned long ulong) {
+  char sulong[FMT_ULONG];
+  memset(sulong, 0, FMT_ULONG);
+  fmt_ulong(sulong, ulong);
+  outs(sulong);
+  return 1;
+}
+
+static inline int printExitData(int exit_type, int exit_val) {
+  switch(exit_type) {
+    case 0:
+      outs("none:");
+      break;
+    case 1:
+      outs("exit:");
+      break;
+    case 2:
+      outs("signal:");
+      break;
+    default:
+      outs("unknown:");
+  }
+  printULong(exit_val);
+  return 1;
+}
+
+static int printRunExit() {
+  return printExitData(svstatus[20], svstatus[21]);
+}
+
+static int printFinExit() {
+  return printExitData(svstatus[22], svstatus[23]);
+}
+
+static int printPID() {
+  int pid = getPID(svstatus);
+  if(pid) printULong(pid);
+  else outs("-");
+  return 1;
+}
+
+static int printCurrentState() {
+  switch(svstatus[19]) {
+    case 0:
+      outs("down");
+      break;
+    case 1:
+      outs("run");
+      break;
+    case 2:
+      outs("finish");
+      break;
+    default:
+      outs("error");
+      return -1;
+  }
+  return 1;
+}
+
+static int printWantState() {
+  switch(svstatus[17]) {
+    case 'u':
+      outs("up");
+      break;
+    case 'd':
+      outs("down");
+      break;
+    case 'x':
+      outs("exit");
+      break;
+    default:
+      outs("error");
+      return -1;
+  }
+  return 1;
+}
+
+static int printUptime() {
+  struct tai svtai;		/* from structure */
+  struct tai now;		/* current time*/
+
+  tai_now(&now);
+  tai_unpack(svstatus, &svtai);
+  if (tai_less(&now,&svtai)) svtai = now;
+  tai_sub(&svtai,&now,&svtai);
+  printULong(tai_approx(&svtai));
+  return 1;
+}
+
+const statusflag_t statusflags[] = {
+  {'r', printRunExit},
+  {'f', printFinExit},
+  {'p', printPID},
+  {'s', printCurrentState},
+  {'w', printWantState},
+  {'u', printUptime},
+  {0, 0},
+};
+
+
 int svstatus_get() {
   if ((fd =open_write("supervise/ok")) == -1) {
     if (errno == error_nodevice) {
@@ -100,10 +223,12 @@
     warn("unable to open supervise/status");
     return(-1);
   }
-  r =read(fd, svstatus, 20);
+  memset(svstatus, 0, 24);
+  r =read(fd, svstatus, 24);
   close(fd);
   switch(r) {
   case 20: break;
+  case 24: break;
   case -1: warn("unable to read supervise/status"); return(-1);
   default: warnx("unable to read supervise/status: bad format"); return(-1);
   }
@@ -122,10 +247,7 @@
     }
     normallyup =1;
   }
-  pid =(unsigned char) svstatus[15];
-  pid <<=8; pid +=(unsigned char)svstatus[14];
-  pid <<=8; pid +=(unsigned char)svstatus[13];
-  pid <<=8; pid +=(unsigned char)svstatus[12];
+  pid =getPID();
   tai_unpack(svstatus, &tstatus);
   if (pid) {
     switch (svstatus[19]) {
@@ -152,18 +274,28 @@
 int status(char *unused) {
   r =svstatus_get();
   switch(r) { case -1: if (lsb) done(4); case 0: return(0); }
-  r =svstatus_print(*service);
-  if (chdir("log") == -1) {
-    if (errno != error_noent) {
-      outs("; log: "); outs(WARN);
-      outs("unable to change to log service directory: ");
-      outs(error_str(errno));
+
+  if(flagprintfunccount == 0) {
+    r =svstatus_print(*service);
+    if (chdir("log") == -1) {
+      if (errno != error_noent) {
+        outs("; log: "); outs(WARN);
+        outs("unable to change to log service directory: ");
+        outs(error_str(errno));
+      }
     }
-  }
-  else
-    if (svstatus_get()) {
-      outs("; "); svstatus_print("log");
+    else
+      if (svstatus_get()) {
+        outs("; "); svstatus_print("log");
+      }
+  } else {
+    int i;
+    outs(*service);
+    for(i = 0; i < flagprintfunccount; i++) {
+      outs(" ");
+      flagprintfuncs[i]();
     }
+  }
   flush("\n");
   if (lsb) switch(r) { case 1: done(0); case 2: done(3); case 0: done(4); }
   return(r);
@@ -319,17 +451,42 @@
 
   servicex =service;
   for (i =0; i < services; ++i) {
-    if ((**service != '/') && (**service != '.')) {
-      if ((chdir(varservice) == -1) || (chdir(*service) == -1)) {
-        fail("unable to change to service directory");
-        *service =0;
+    if ((act == &status) && (**service == '-')) {
+      char *flag = (*service)+1;
+      while(*flag != 0) {
+        /* search for a function associated with this flag */
+        int fnidx, foundFlag = 0;
+        for(fnidx = 0; statusflags[fnidx].flagchar != 0; fnidx++) {
+          if(flagprintfunccount == MAX_FLAGPRINTFUNCS) {
+            fatal("Excessive number of flag-based parameters provided");
+          }
+          if(statusflags[fnidx].flagchar == *flag) {
+            flagprintfuncs[flagprintfunccount++] = statusflags[fnidx].printfunc;
+            foundFlag = 1;
+            break;
+          }
+        }
+        if(!foundFlag) {
+          char badFlag[3] = {'-', 'X', 0};
+          badFlag[1] = *flag;
+          fatal2x("Invalid status flag provided: ", badFlag);
+        }
+        flag++;
       }
+      *service = 0;
     }
     else
-      if (chdir(*service) == -1) {
-        fail("unable to change to service directory");
-        *service =0;
+      if ((**service != '/') && (**service != '.')) {
+        if ((chdir(varservice) == -1) || (chdir(*service) == -1)) {
+          fail("unable to change to service directory");
+          *service =0;
+        }
       }
+      else
+        if (chdir(*service) == -1) {
+          fail("unable to change to service directory");
+          *service =0;
+        }
     if (*service) if (act(acts) == -1) *service =0;
     if (fchdir(curdir) == -1) fatal("unable to change to original directory");
     service++;

  reply	other threads:[~2005-09-19 19:13 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-17  4:46 Charles Duffy
2005-09-17  5:17 ` Mike Bell
2005-09-19  8:35   ` Gerrit Pape
2005-09-17  8:53 ` Laurent Bercot
2005-09-19  8:31 ` Gerrit Pape
2005-09-19 16:04   ` Charles Duffy
2005-09-19 19:13     ` Charles Duffy [this message]
2005-09-21 21:50       ` new "sv status" flags and exit-tracking patch, yet again Charles Duffy
2005-09-26 10:12       ` new "sv status" flags and exit-tracking patch, and misc Gerrit Pape
2005-09-26 15:31         ` duplicate processes Jussi Ramo
2005-09-26 15:42           ` Charlie Brady
2005-12-08 11:08         ` new "sv status" flags and exit-tracking patch, and misc Gerrit Pape
2005-12-08 19:37           ` Charles Duffy
2005-12-09 14:29             ` Gerrit Pape
2005-12-09 14:50               ` Rafal Bisingier

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='dgn2ks$usn$1@sea.gmane.org' \
    --to=cduffy@spamcop.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).