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, yet again
Date: Wed, 21 Sep 2005 16:50:31 -0500	[thread overview]
Message-ID: <dgskj8$o4m$1@sea.gmane.org> (raw)
In-Reply-To: <dgn2ks$usn$1@sea.gmane.org>

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

This version uses negative numbers for representing cases where exit was 
on account of a signal being received, as per Gerrit's previous suggestion.

[-- Attachment #2: runit-1.3.1-newer.patch --]
[-- Type: text/x-patch, Size: 10130 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.680226345 -0500
+++ runit-1.3.1.new/src/runsv.c	2005-09-19 10:00:44.751145982 -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.801889117 -0500
+++ runit-1.3.1.new/src/sv.c	2005-09-21 16:42:48.347484541 -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,114 @@
 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) {
+  if(exit_type != 1)
+    outs("-");
+  if(exit_type != 0)
+    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 +213,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 +237,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 +264,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 +441,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-21 21:50 UTC|newest]

Thread overview: 15+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-09-17  4:46 new "sv status" flags and exit-tracking patch, and misc 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
2005-09-21 21:50       ` Charles Duffy [this message]
2005-09-26 10:12       ` 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='dgskj8$o4m$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).