From mboxrd@z Thu Jan 1 00:00:00 1970 X-Msuck: nntp://news.gmane.io/gmane.comp.sysutils.supervision.general/884 Path: news.gmane.org!not-for-mail From: Charles Duffy Newsgroups: gmane.comp.sysutils.supervision.general Subject: Re: new "sv status" flags and exit-tracking patch, and misc. Date: Mon, 19 Sep 2005 14:13:30 -0500 Message-ID: References: <20050919082620.21268.qmail@162d9f02f26a34.315fe32.mid.smarden.org> NNTP-Posting-Host: main.gmane.org Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="------------070201090804040604030809" X-Trace: sea.gmane.org 1127157794 1000 80.91.229.2 (19 Sep 2005 19:23:14 GMT) X-Complaints-To: usenet@sea.gmane.org NNTP-Posting-Date: Mon, 19 Sep 2005 19:23:14 +0000 (UTC) Original-X-From: supervision-return-1120-gcsg-supervision=m.gmane.org@list.skarnet.org Mon Sep 19 21:23:13 2005 Return-path: Original-Received: from antah.skarnet.org ([212.85.147.14]) by ciao.gmane.org with smtp (Exim 4.43) id 1EHRBK-00055Q-Nt for gcsg-supervision@gmane.org; Mon, 19 Sep 2005 21:20:02 +0200 Original-Received: (qmail 19317 invoked by uid 76); 19 Sep 2005 19:20:24 -0000 Mailing-List: contact supervision-help@list.skarnet.org; run by ezmlm List-Post: List-Help: List-Unsubscribe: List-Subscribe: List-Archive: Original-Received: (qmail 19311 invoked from network); 19 Sep 2005 19:20:23 -0000 X-Injected-Via-Gmane: http://gmane.org/ Original-To: supervision@list.skarnet.org Original-Lines: 409 Original-X-Complaints-To: usenet@sea.gmane.org X-Gmane-NNTP-Posting-Host: fwext1-ext.isgenesis.com User-Agent: Mozilla Thunderbird 1.0.6 (X11/20050716) X-Accept-Language: en-us, en In-Reply-To: Original-Sender: news Xref: news.gmane.org gmane.comp.sysutils.supervision.general:884 Archived-At: This is a multi-part message in MIME format. --------------070201090804040604030809 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit 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. --------------070201090804040604030809 Content-Type: text/x-patch; name="runit-1.3.1.new-smaller.patch" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="runit-1.3.1.new-smaller.patch" 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 +#include #include #include #include @@ -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 #include +#include #include #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++; --------------070201090804040604030809--