diff --git a/src/include/66/constants.h b/src/include/66/constants.h index 97dad7d30380532052ad249371d55b3ac94ede0f..d08dbdff6f0a905f8cee3070dd577a58a3f700c3 100644 --- a/src/include/66/constants.h +++ b/src/include/66/constants.h @@ -31,6 +31,8 @@ #define SS_TREE_LEN (sizeof SS_TREE - 1) #define SS_NOTIFICATION "notification-fd" #define SS_NOTIFICATION_LEN (sizeof SS_NOTIFICATION - 1) +#define SS_MAXDEATHTALLY "max-death-tally" +#define SS_MAXDEATHTALLY_LEN (sizeof SS_MAXDEATHTALLY - 1) /**tree dir*/ #define SS_RULES "/rules" #define SS_RULES_LEN (sizeof SS_RULES - 1) diff --git a/src/include/66/svc.h b/src/include/66/svc.h index 1952762bf4ac48ec0fec2a6b52ab0ac62de99dba..d9fa724cf13999b696334febb0bb631140b312e1 100644 --- a/src/include/66/svc.h +++ b/src/include/66/svc.h @@ -23,7 +23,7 @@ #include <66/resolve.h> #include <66/ssexec.h> -typedef struct ss_resolve_sig_s ss_resolve_sig_t, *ss_resovle_sig_t_ref ; +typedef struct ss_resolve_sig_s ss_resolve_sig_t, *ss_resolve_sig_t_ref ; struct ss_resolve_sig_s { ss_resolve_t res ; @@ -77,7 +77,7 @@ enum sigactions_e extern int svc_switch_to(ssexec_t *info,unsigned int where) ; extern int svc_init(ssexec_t *info,char const *src, genalloc *ga) ; -extern int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv) ; +extern int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv,tain_t *deadline) ; extern int svc_send(ssexec_t *info,genalloc *ga,char const *sig,char const *const *envp) ; extern int svc_unsupervise(ssexec_t *info,genalloc *ga,char const *sig,char const *const *envp) ; diff --git a/src/lib66/ssexec_help.c b/src/lib66/ssexec_help.c index 1e2c46b33fd26f4b3821675dd4119d8aaf933752..2f3ca7b0aa80281bf0113ed8369b69a528cb3eca 100644 --- a/src/lib66/ssexec_help.c +++ b/src/lib66/ssexec_help.c @@ -100,7 +100,7 @@ char const *help_stop = " -K: kill the service(s) and keep it down\n" ; -char const *usage_svctl = "66-svctl [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -n death ] [ -u | U | d | D | r | R | K | X ] service(s)" ; +char const *usage_svctl = "66-svctl [ -h ] [ -v verbosity ] [ -l live ] [ -t tree ] [ -T timeout ] [ -n death ] [ -u | d | r | K | X ] service(s)" ; char const *help_svctl = "66-svctl <options> tree\n" @@ -113,11 +113,8 @@ char const *help_svctl = " -T: service timeout\n" " -n: number of death\n" " -u: bring up the service(s)\n" -" -U: really up\n" " -d: bring down the service(s)\n" -" -D: really down\n" " -r: reload\n" -" -R: reload and really up\n" " -X: bring down the service(s) and the kill his supervisor\n" " -K: kill the service(s) and keep it down\n" ; diff --git a/src/lib66/ssexec_start.c b/src/lib66/ssexec_start.c index 045d7936ffe453da8b9fa5d7784d5c91c0c780e9..d8d80de09b361454879ca0062461e14da10d76dd 100644 --- a/src/lib66/ssexec_start.c +++ b/src/lib66/ssexec_start.c @@ -13,7 +13,7 @@ */ #include <string.h> -//#include <stdio.h> +#include <stdio.h> #include <oblibs/obgetopt.h> #include <oblibs/error2.h> @@ -35,7 +35,7 @@ static int empty = 0 ; static unsigned int RELOAD = 0 ; static unsigned int DEADLINE = 0 ; -static char *SIG = "-U" ; +static char *SIG = "-u" ; static genalloc nclassic = GENALLOC_ZERO ; //resolve_t type static genalloc nrc = GENALLOC_ZERO ; //resolve_t type @@ -63,7 +63,7 @@ int svc_sanitize(ssexec_t *info, char const *const *envp) VERBO1 strerr_warnwu1sys("publish service graph") ; goto err ; } - if (!svc_unsupervise(info,&graph_reload_cl.sorted,"-D",envp)) goto err ; + if (!svc_unsupervise(info,&graph_reload_cl.sorted,"-d",envp)) goto err ; genalloc_reverse(ss_resolve_t,&graph_reload_cl.sorted) ; if (!svc_init(info,sares.s,&graph_reload_cl.sorted)) { @@ -202,7 +202,7 @@ int ssexec_start(int argc, char const *const *argv,char const *const *envp,ssexe // be sure that the global var are set correctly RELOAD = 0 ; DEADLINE = 0 ; - SIG = "-U" ; + SIG = "-u" ; if (info->timeout) DEADLINE = info->timeout ; @@ -228,7 +228,7 @@ int ssexec_start(int argc, char const *const *argv,char const *const *envp,ssexe switch (opt) { case 'r' : if (RELOAD) exitusage(usage_start) ; RELOAD = 1 ; SIG = "-r" ; break ; - case 'R' : if (RELOAD) exitusage(usage_start) ; RELOAD = 2 ; SIG = "-U" ; break ; + case 'R' : if (RELOAD) exitusage(usage_start) ; RELOAD = 2 ; SIG = "-u" ; break ; default : exitusage(usage_start) ; } } diff --git a/src/lib66/ssexec_stop.c b/src/lib66/ssexec_stop.c index f46124c48fe500bdae0d3b943ea5662fbc0fde75..97c66796365d2c78e0aea4bc9f4c42c130c9a09b 100644 --- a/src/lib66/ssexec_stop.c +++ b/src/lib66/ssexec_stop.c @@ -32,7 +32,7 @@ static unsigned int DEADLINE = 0 ; static unsigned int UNSUP = 0 ; -static char *SIG = "-D" ; +static char *SIG = "-d" ; static ss_resolve_graph_t graph_unsup_cl = RESOLVE_GRAPH_ZERO ; static ss_resolve_graph_t graph_cl = RESOLVE_GRAPH_ZERO ; @@ -115,7 +115,7 @@ int ssexec_stop(int argc, char const *const *argv,char const *const *envp,ssexec // be sure that the global var are set correctly DEADLINE = 0 ; UNSUP = 0 ; - SIG = "-D" ; + SIG = "-d" ; if (info->timeout) DEADLINE = info->timeout ; diff --git a/src/lib66/ssexec_svctl.c b/src/lib66/ssexec_svctl.c index 6655943b6778aa78d53fb647af7158466eb52dfb..e756defa9a98628b7b65c643e651dc2faa0caa6e 100644 --- a/src/lib66/ssexec_svctl.c +++ b/src/lib66/ssexec_svctl.c @@ -18,6 +18,7 @@ #include <signal.h> #include <unistd.h>//access //#include <stdio.h> +//#include <stdlib.h> #include <oblibs/obgetopt.h> #include <oblibs/error2.h> @@ -35,6 +36,7 @@ #include <s6/s6-supervise.h>//s6_svstatus_t #include <s6/ftrigr.h> + #include <66/utils.h> #include <66/constants.h> #include <66/svc.h> @@ -43,7 +45,18 @@ #include <66/state.h> unsigned int SV_DEADLINE = 3000 ; -unsigned int DEATHSV = 10 ; +unsigned int DEATHSV = 5 ; +ftrigr_t fifo = FTRIGR_ZERO ; + +typedef struct pidindex_s pidindex_t ; +struct pidindex_s +{ + ss_resolve_sig_t_ref sv ; + pid_t pid ; +} ; + +static pidindex_t *pidindex ; +static unsigned int npids = 0 ; static int read_file (char const *file, char *buf, size_t n) { @@ -134,153 +147,313 @@ static const uint8_t chtenum[128] = * We let s6-supervise make what it need to do with this file but * we take the same number to set the sv_signal.death value * accepted for every daemon before exiting if the SIGNAL is not reached. - * If this file doesn't exist a number of 3 death (death -> number + * If this file doesn't exist a number of 5 death (death -> number * of wrong signal received) is set by default. * This ndeath value can be set on commandline by the -n options. * * In all case the loop is broken to avoids infinite iopause * * The notication-fd file is used as the original one. If the file - * doesn't exist and the SIGNAL is U , we change SIGNAL to u and warn - * the user about it. - * - * In the send_svc function a reached timeout is not an absolute error - * because we can have a notification-file in the servicedirs of the - * service with a deamon which doesn't support readiness notification. - * In this case, we send U and only receive u as event, the daemon is - * running but not notified by the daemon itself. - * We accept this case as an "half" success. We exit with success but - * the user is warned about the state. */ + * exist and the SIGNAL is u , we change SIGNAL to U. + */ /**@Return 0 on success * @Return 1 on if signal is not complete (e.g. want U receive only u) * @Return 2 on fail * @Return 3 for PERMANENT failure */ -int handle_case(stralloc *sa, ss_resolve_sig_t *sv_signal) +int handle_case(stralloc *sa, ss_resolve_sig_t *svc) { int p, h, err ; unsigned int state, i = 0 ; - state = sv_signal->sig ; + state = svc->sig ; err = 2 ; - for (;i < sa->len ; i++) { p = chtenum[(unsigned char)sa->s[i]] ; - unsigned char action = actions[state][p] ; - - switch (action) { case GOTIT: - h = handle_signal_svc(sv_signal) ; + h = handle_signal_svc(svc) ; if (!h) { - err = 1 ; + err = 0 ; break ; } - err = 0 ; - return err ; - case WAIT: - err = 1 ; + return 1 ; + case WAIT: err = 0 ; break ; - case DEAD: - err = 2 ; - return err ; - case DONE: - err = 0 ; - return err ; - case PERM: - err = 3 ; - return err ; + case DEAD: return 2 ; + case DONE: return 1 ; + case PERM: return 3 ; default: VERBO3 strerr_warnw1x("invalid state, make a bug report"); - err = 2 ; - return err ; + return 2 ; } } return err ; } -static int handle_signal_pipe(ss_resolve_sig_t *svc) +static void write_state(ss_resolve_sig_t *svc) { - char *sv = svc->res.sa.s + svc->res.runat ; + ss_state_t sta = STATE_ZERO ; + char const *state = svc->res.sa.s + svc->res.state ; + char const *sv = svc->res.sa.s + svc->res.name ; + if (svc->sig <= 3) + { + if (svc->state <= 1) + { + ss_state_setflag(&sta,SS_FLAGS_PID,svc->pid) ; + ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_TRUE) ; + } + else + { + ss_state_setflag(&sta,SS_FLAGS_PID,SS_FLAGS_FALSE) ; + ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_FALSE) ; + } + } + else + { + if (svc->state <=1) + { + ss_state_setflag(&sta,SS_FLAGS_PID,SS_FLAGS_FALSE) ; + ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_FALSE) ; + } + else + { + ss_state_setflag(&sta,SS_FLAGS_PID,svc->pid) ; + ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_TRUE) ; + } + } + ss_state_setflag(&sta,SS_FLAGS_RELOAD,SS_FLAGS_FALSE) ; + ss_state_setflag(&sta,SS_FLAGS_INIT,SS_FLAGS_FALSE) ; + ss_state_setflag(&sta,SS_FLAGS_UNSUPERVISE,SS_FLAGS_FALSE) ; + VERBO2 strerr_warni2x("Write state file of: ",sv) ; + if (!ss_state_write(&sta,state,sv)) + { + VERBO1 strerr_warnwu2sys("write state file of: ",sv) ; + } + +} + +static int announce(ss_resolve_sig_t *svc) +{ + int r = svc->state ; + char *sv = svc->res.sa.s + svc->res.name ; + /** special case time out reached or number execeeded, + * last check with s6-svstat framboise*/ + if (r == 0 || r == 4) + { + int e = handle_signal_svc(svc) ; + if (!e) r = r == 0 ? 2 : 4 ; + else r = r == 0 ? 0 : 1 ; + svc->state = r ; + } + switch(r) + { + case 0: VERBO1 strerr_warni4x(sv," is ",(svc->sig > 3) ? "down" : "up"," but not notified by the daemon itself") ; + break ; + case 1: VERBO1 strerr_warni4x(sv,": ",(svc->sig > 3) ? "stopped" : "started"," successfully") ; + break ; + case 2: VERBO1 strerr_warnwu2x((svc->sig > 3) ? "stop " : "start ", sv) ; + break ; + case 3: VERBO1 strerr_warnw3x(sv," report permanent failure -- unable to ",(svc->sig > 1) ? "stop" : "start") ; + break ; + case 4: VERBO1 strerr_warnwu3x((svc->sig > 3) ? "stop: " : "start: ",sv, ": number of try exceeded") ; + break ; + case-1: VERBO1 strerr_warnw3x("unexpected data in state file of: ",sv," -- please make a bug report") ; + break ; + } + return r ; +} + +static inline void kill_all (void) +{ + unsigned int j = npids ; + while (j--) kill(pidindex[j].pid, SIGTERM) ; +} + +static int handle_signal_pipe(genalloc *gakeep) +{ + int ok = 1 ; for (;;) { switch (selfpipe_read()) { case -1 : strerr_warnwu1sys("selfpipe_read") ; return 0 ; - case 0 : return 1 ; + case 0 : goto end ; + case SIGCHLD: + for (;;) + { + unsigned int j = 0 ; + int wstat ; + pid_t r = wait_nohang(&wstat) ; + if (r < 0) + if (errno = ECHILD) break ; + else strerr_diefu1sys(111,"wait for children") ; + else if (!r) break ; + for (; j < npids ; j++) if (pidindex[j].pid == r) break ; + if (j < npids) + { + ss_resolve_sig_t_ref sv = pidindex[j].sv ; + pidindex[j] = pidindex[--npids] ; + if (!WIFSIGNALED(wstat) && !WEXITSTATUS(wstat)) + { + if (announce(sv) > 1) ok = 0 ; + write_state(sv) ; + } + else + { + ok = 0 ; announce(sv) ; write_state(sv) ; + } + } + } + break ; case SIGTERM: case SIGINT: - // TODO, little ugly for me VERBO2 strerr_warnw1x("received SIGINT, aborting service transition") ; - if (svc->sig <= SIGRR) - s6_svc_writectl(sv, S6_SUPERVISE_CTLDIR, "d", 1) ; - return 0 ; - default : strerr_warn1x("unexpected data in selfpipe") ; return 0 ; + kill_all() ; + break ; + default : strerr_warn1x("unexpected data in selfpipe") ; } } -} + end: + return ok ; -static void announce(ss_resolve_sig_t *sv_signal) +} +static int compute_timeout(tain_t *start,tain_t *tsv) { - - int r = sv_signal->state ; - char *sv = sv_signal->res.sa.s + sv_signal->res.runat ; - if (r == 3) { VERBO2 strerr_warnw3x(sv," report permanent failure -- unable to ",(sv_signal->sig > 1) ? "stop" : "start") ; } - else if (r == 2) { VERBO2 strerr_warnwu2x((sv_signal->sig > 3) ? "stop " : "start ", sv) ; } - else if (r == 1) { VERBO2 strerr_warni4x(sv," is ",(sv_signal->sig > 3) ? "down" : "up"," but not notified by the daemon itself") ; } - else if (!r) { VERBO2 strerr_warni4x(sv,": ",(sv_signal->sig > 3) ? "stopped" : "started"," successfully") ; } + tain_t now ; + tain_t tpass ; + tain_now(&now) ; + tain_sub(&tpass,&now,start) ; + if (tain_less(tsv,&tpass)) return 0 ; + return 1 ; } -int svc_listen(genalloc *gasv, ftrigr_t *fifo,int spfd,ss_resolve_sig_t *svc) +static void svc_listen_less(int state_val, int *state,unsigned int *did,unsigned int *loop,unsigned int pos) +{ + (*state) = state_val ; + did[pos] = 1 ; + (*loop)--; +} +static void svc_listen(unsigned int nsv) { int r ; - - stralloc sa = STRALLOC_ZERO ; - - iopause_fd x[2] = { { .fd = ftrigr_fd(fifo), .events = IOPAUSE_READ } , { .fd = spfd, .events = IOPAUSE_READ, .revents = 0 } } ; - tain_t t ; - tain_now_g() ; - tain_add_g(&t,&svc->deadline) ; - - VERBO3 strerr_warnt2x("start iopause for: ",svc->res.sa.s + svc->res.runat) ; - - for(;;) + tain_t start ; + stralloc sa = STRALLOC_ZERO ; + iopause_fd x = { .fd = ftrigr_fd(&fifo), .events = IOPAUSE_READ } ; + ss_resolve_sig_t_ref svc ; + int *state = 0 ; + unsigned int *ndeath = 0, i, j ; + unsigned int did[nsv] ; + i = j = nsv ; + tain_now(&start) ; + tain_from_millisecs(&t,SV_DEADLINE) ; + tain_add_g(&t,&t) ; + while(i--) + did[i] = 0 ; + + while(j) { - r = ftrigr_checksa(fifo,svc->ids, &sa) ; - if (r < 0) { VERBO3 strerr_warnwu1sys("ftrigr_check") ; return 0 ; } - if (r) - { - svc->state = handle_case(&sa,svc) ; - if (!svc->state){ announce(svc) ; goto end ; } - else if (svc->state >= 2){ announce(svc) ; goto end ; } - } - if (!(svc->ndeath)) - { - VERBO2 strerr_warnw2x("number of try exceeded for: ",svc->res.sa.s + svc->res.runat) ; - announce(svc) ; - goto end ; - } - - r = iopause_g(x, 2, &t) ; - if (r < 0){ VERBO3 strerr_warnwu1sys("iopause") ; return 0 ; } - /** timeout is not a error , the iopause process did right */ - else if (!r) { VERBO3 strerr_warnt2x("timed out reached for: ",svc->res.sa.s + svc->res.runat) ; announce(svc) ; break ; } - - if (x[1].revents & IOPAUSE_READ) return handle_signal_pipe(svc) ? 1 : 0 ; - - if (x[0].revents & IOPAUSE_READ) + r = iopause_g(&x, 1, &t) ; + if (r < 0) strerr_dief1sys(111,"listen iopause") ; + /** timeout is not a error , the iopause process did right*/ + else if (!r) strerr_dief1sys(111,"listen time out") ; + if (x.revents & IOPAUSE_READ) { - if (ftrigr_update(fifo) < 0){ VERBO3 strerr_warnwu1sys("ftrigr_update") ; return 0 ; } - svc->ndeath--; + i = 0 ; + if (ftrigr_update(&fifo) < 0) strerr_diefu1sys(111,"update fifo") ; + for (;i < nsv;i++) + { + if (did[i]) continue ; + svc = pidindex[i].sv ; + state = &svc->state ; + ndeath = &svc->ndeath ; + if (!compute_timeout(&start,&pidindex[i].sv->deadline)) + svc_listen_less(0,state,did,&j,i) ; + sa.len = 0 ; + r = ftrigr_checksa(&fifo,svc->ids, &sa) ; + if (r < 0) { VERBO3 strerr_warnwu1sys("check fifo") ; goto end ; } + else if (r) + { + (*ndeath)-- ; + (*state) = handle_case(&sa,svc) ; + if (!(*ndeath)) svc_listen_less(4,state,did,&j,i) ; + if ((*state) >= 1) svc_listen_less(*state,state,did,&j,i) ; + } + + } } } - end: - stralloc_free(&sa) ; - return svc->state ; + + end: + stralloc_free(&sa) ; +} +/* @return 111 unable to control + * @return 100 "something is wrong with the S6_SUPERVISE_CTLDIR directory. errno reported + * @return 99 supervisor not listening */ +static int svc_writectl(ss_resolve_sig_t *svc) +{ + int r ; + char *sv = svc->res.sa.s + svc->res.runat ; + size_t siglen = strlen(svc->sigtosend) ; + VERBO2 strerr_warnt6x("send signal: ",svc->sigtosend," to: ", sv,"/",S6_SUPERVISE_CTLDIR) ; + r = s6_svc_writectl(sv, S6_SUPERVISE_CTLDIR, svc->sigtosend, siglen) ; + if (r == -1) return 111 ; + else if (r == -2) return 100 ; + else if (!r) return 99 ; + return 0 ; +} + +static void svc_async(unsigned int i,unsigned int nsv) +{ + int r ; + pid_t pid ; + pid = fork() ; + if (pid < 0) return ; + if (!pid) + { + r = svc_writectl(pidindex[i].sv) ; + _exit(r) ; + } + + pidindex[npids].pid = pid ; + pidindex[npids++].sv = pidindex[i].sv ; + return ; +} + +int doit (int spfd, genalloc *gakeep, tain_t *dead) +{ + iopause_fd x = { .fd = spfd, .events = IOPAUSE_READ } ; + unsigned int nsv = genalloc_len(ss_resolve_sig_t,gakeep) ; + unsigned int i = 0 ; + int exitcode = 1 ; + pidindex_t pidindextable[nsv] ; + pidindex = pidindextable ; + /** keep the good order service declaration + * of the genalloc*/ + while(i<nsv){ + pidindex[i].sv = &genalloc_s(ss_resolve_sig_t,gakeep)[i] ; + pidindex[i].pid = 0 ; + i++ ; + } + i = 0 ; + while(i < nsv) + { + svc_async(i,nsv) ; + i++ ; + } + svc_listen(nsv) ; + while (npids) + { + int r = iopause_g(&x,1,dead) ; + if (r < 0) strerr_diefu1sys(111,"iopause") ; + if (!r) strerr_dief1x(111,"time out") ; + if (!handle_signal_pipe(gakeep)) exitcode = 0 ; + } + return exitcode ; } int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexec_t *info) @@ -288,12 +461,12 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe // be sure that the global var are set correctly SV_DEADLINE = 3000 ; - DEATHSV = 10 ; - tain_t ttmain ; + DEATHSV = 5 ; - int e, isup, ret, r ; + int e, isup, r, ret = 1 ; unsigned int death, tsv, reverse ; int SIGNAL = -1 ; + tain_t ttmain ; genalloc gakeep = GENALLOC_ZERO ; //type ss_resolve_sig stralloc sares = STRALLOC_ZERO ; @@ -303,11 +476,9 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe char *sig = 0 ; - ftrigr_t fifo = FTRIGR_ZERO ; - s6_svstatus_t status = S6_SVSTATUS_ZERO ; - tsv = death = ret = reverse = 0 ; + tsv = death = reverse = 0 ; //PROG = "66-svctl" ; { @@ -315,20 +486,17 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe for (;;) { - int opt = getopt_args(argc,argv, "n:udUDXrRK", &l) ; + int opt = getopt_args(argc,argv, "n:urdXK", &l) ; if (opt == -1) break ; if (opt == -2) strerr_dief1x(110,"options must be set first") ; switch (opt) { case 'n' : if (!uint0_scan(l.arg, &death)) exitusage(usage_svctl) ; break ; case 'u' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGUP ; sig ="u" ; break ; - case 'U' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGRUP ; sig = "uwU" ; break ; - case 'r' : if (SIGNAL > 0) ; SIGNAL = SIGR ; sig = "r" ; break ; - case 'R' : if (SIGNAL > 0) ; SIGNAL = SIGRR ; sig = "rwR" ; break ; - case 'd' : if (SIGNAL > 0) ; SIGNAL = SIGDOWN ; sig = "d" ; break ; - case 'D' : if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "dwD" ; break ; - case 'X' : if (SIGNAL > 0) ; SIGNAL = SIGX ; sig = "xd" ; break ; - case 'K' : if (SIGNAL > 0) ; SIGNAL = SIGRDOWN ; sig = "kd" ; break ; + case 'r' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGR ; sig = "r" ; break ; + case 'd' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGDOWN ; sig = "d" ; break ; + case 'X' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGX ; sig = "xd" ; break ; + case 'K' : if (SIGNAL > 0) exitusage(usage_svctl) ; SIGNAL = SIGRDOWN ; sig = "kd" ; break ; default : exitusage(usage_svctl) ; } @@ -337,15 +505,10 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe } if (argc < 1 || (SIGNAL < 0)) exitusage(usage_svctl) ; - if (info->timeout) tsv = info->timeout ; - if ((scandir_ok(info->scandir.s)) !=1 ) strerr_dief3sys(111,"scandir: ", info->scandir.s," is not running") ; - if (!ss_resolve_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_SRC)) strerr_diefu1sys(111,"set revolve pointer to source") ; - if (SIGNAL > SIGRUP) reverse = 1 ; - for(;*argv;argv++) { char const *name = *argv ; @@ -355,7 +518,7 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe if (!ss_resolve_graph_build(&graph,&res,sares.s,reverse)) strerr_diefu1sys(111,"build services graph") ; } - if (SIGNAL == SIGR || SIGNAL == SIGRR) reverse = 0 ; + if (SIGNAL == SIGR) reverse = 0 ; r = ss_resolve_graph_publish(&graph,reverse) ; if (r < 0) strerr_dief1x(111,"cyclic dependencies detected") ; if (!r) strerr_diefu1sys(111,"publish service graph") ; @@ -368,7 +531,7 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe char *svok = string + sv_signal.res.runat ; char *state = string + sv_signal.res.state ; size_t svoklen = strlen(svok) ; - char file[svoklen + 16 + 1] ; + char file[svoklen + SS_NOTIFICATION_LEN + 1 + 1] ; memcpy(file,svok,svoklen) ; if (!ss_state_check(state,string + sv_signal.res.name)) strerr_dief2x(111,"unitialized service: ",string + sv_signal.res.name) ; if (!ss_state_read(&sta,state,string + sv_signal.res.name)) strerr_diefu2sys(111,"read state of: ",string + sv_signal.res.name) ; @@ -376,7 +539,7 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe if (!s6_svstatus_read(svok,&status)) strerr_diefu2sys(111,"read status of: ",svok) ; isup = status.pid && !status.flagfinishing ; - if (isup && (SIGNAL <= SIGRUP)) + if (isup && (SIGNAL == SIGUP)) { VERBO1 strerr_warni2x("Already up: ",string + sv_signal.res.name) ; continue ; @@ -386,58 +549,38 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe VERBO1 strerr_warni2x("Already down: ",string + sv_signal.res.name) ; continue ; } - /*else if ((SIGNAL == SIGR) || (SIGNAL == SIGRR)) - { - SIGNAL = SIGRUP ; - }*/ - sv_signal.sigtosend = sig ; - sv_signal.sig = SIGNAL ; + sv_signal.sigtosend = sig ; sv_signal.sig = SIGNAL ; /** notification-fd */ - - memcpy(file + svoklen,"/notification-fd",16) ; - file[svoklen + 16] = 0 ; + memcpy(file + svoklen,"/" SS_NOTIFICATION,SS_NOTIFICATION_LEN + 1) ; + file[svoklen + SS_NOTIFICATION_LEN + 1] = 0 ; e = errno ; errno = 0 ; - if (access(file, F_OK) < 0) + if (access(file, F_OK) < 0 && errno != ENOENT) + strerr_warnw1sys("conflicting format of file: " SS_NOTIFICATION) ; + else if (errno != ENOENT) { - if (errno != ENOENT) strerr_diefu2sys(111, "access ", file) ; - if (SIGNAL == SIGRUP) - { - sv_signal.sig = SIGUP ; - sv_signal.sigtosend = "uwu" ; - VERBO1 strerr_warnw2x(file, " is not present - ignoring request for readiness notification") ; - } - if (SIGNAL == SIGRR) - { - sv_signal.sig = SIGR ; - sv_signal.sigtosend = "uwr" ; - VERBO1 strerr_warnw2x(file, " is not present - ignoring request for readiness notification") ; - } - if (SIGNAL == SIGRDOWN) - { - sv_signal.sig = SIGDOWN ; - sv_signal.sigtosend = "dwd" ; - VERBO1 strerr_warnw2x(file, " is not present - ignoring request for readiness notification") ; - } + + if (!read_uint(file,&sv_signal.notify)) strerr_diefu2sys(111,"read: ",file) ; + if (SIGNAL == SIGUP) + { sv_signal.sig = SIGRUP ; sv_signal.sigtosend = "uwU" ; } + else if (SIGNAL == SIGR) + { sv_signal.sig = SIGRR ; sv_signal.sigtosend = "uwR" ; } + else if (SIGNAL == SIGDOWN) + { sv_signal.sig = SIGRDOWN ; sv_signal.sigtosend = "dwD" ; } } - else if (!read_uint(file,&sv_signal.notify)) strerr_diefu2sys(111,"read: ",file) ; - /** max-death-tally */ if (!death) { - memcpy(file + svoklen,"/max-death-tally", 16) ; - file[svoklen + 16] = 0 ; + memcpy(file + svoklen,"/" SS_MAXDEATHTALLY, SS_MAXDEATHTALLY_LEN + 1) ; + file[svoklen + SS_MAXDEATHTALLY_LEN + 1] = 0 ; errno = 0 ; if (access(file, F_OK) < 0) - { if (errno != ENOENT) strerr_diefu2sys(111, "access ", file) ; - } + if (errno == ENOENT) - { sv_signal.ndeath = DEATHSV ; - } else { if (!read_uint(file,&sv_signal.ndeath)) strerr_diefu2sys(111,"read: ",file) ; @@ -452,118 +595,55 @@ int ssexec_svctl(int argc, char const *const *argv,char const *const *envp,ssexe else { /** timeout-{up/down} */ + char *tm = NULL ; + unsigned int t ; + if (SIGNAL <= SIGR) + tm="/timeout-up" ; + else tm="/timeout-down" ; + errno = 0 ; + size_t tmlen = strlen(tm) ; + memcpy(file + svoklen,tm, tmlen) ; + file[svoklen + tmlen] = 0 ; + if (access(file, F_OK) < 0) + if (errno != ENOENT) strerr_diefu2sys(111, "access ", file) ; + + if (errno == ENOENT) + tain_from_millisecs(&sv_signal.deadline, SV_DEADLINE) ; + else { - char *tm = NULL ; - unsigned int t ; - if (SIGNAL <= SIGRR) - { - tm="/timeout-up" ; - } - else - { - tm="/timeout-down" ; - } - errno = 0 ; - size_t tmlen = strlen(tm) ; - memcpy(file + svoklen,tm, tmlen) ; - file[svoklen + tmlen] = 0 ; - if (access(file, F_OK) < 0) - { - if (errno != ENOENT) strerr_diefu2sys(111, "access ", file) ; - } - if (errno == ENOENT) - { - tain_from_millisecs(&sv_signal.deadline, SV_DEADLINE) ; - } - else - { - if (!read_uint(file,&t)) strerr_diefu2sys(111,"read: ",file) ; + if (!read_uint(file,&t)) strerr_diefu2sys(111,"read: ",file) ; tain_from_millisecs(&sv_signal.deadline, t) ; - } } } - errno = e ; - if (!genalloc_append(ss_resolve_sig_t,&gakeep,&sv_signal)) strerr_diefu2sys(111,"append services selection with: ",string + sv_signal.res.name) ; } /** nothing to do */ if (!genalloc_len(ss_resolve_sig_t,&gakeep)) goto finish ; + ttmain = tain_infinite_relative ; + + tain_now_g() ; + tain_add_g(&ttmain,&ttmain) ; + int spfd = selfpipe_init() ; if (spfd < 0) strerr_diefu1sys(111, "selfpipe_trap") ; + if (selfpipe_trap(SIGCHLD) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; if (selfpipe_trap(SIGINT) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; if (selfpipe_trap(SIGTERM) < 0) strerr_diefu1sys(111, "selfpipe_trap") ; if (sig_ignore(SIGPIPE) < 0) strerr_diefu1sys(111,"ignore SIGPIPE") ; - if (!svc_init_pipe(&fifo,&gakeep)) strerr_diefu1x(111,"init pipe") ; - - for (unsigned int i = 0 ; i < genalloc_len(ss_resolve_sig_t,&gakeep) ; i++) - { - int nret = 0 ; - ss_resolve_sig_t *sv = &genalloc_s(ss_resolve_sig_t,&gakeep)[i] ; - char const *name = sv->res.sa.s + sv->res.name ; - char const *state = sv->res.sa.s + sv->res.state ; - nret = svc_listen(&gakeep,&fifo,spfd,sv) ; - if (nret > 1) ret = 111 ; - if (sv->sig <= 3) - { - if (nret <= 1) - { - ss_state_setflag(&sta,SS_FLAGS_PID,sv->pid) ; - ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_TRUE) ; - } - else - { - ss_state_setflag(&sta,SS_FLAGS_PID,SS_FLAGS_FALSE) ; - ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_FALSE) ; - } - } - else - { - if (nret <=1) - { - ss_state_setflag(&sta,SS_FLAGS_PID,SS_FLAGS_FALSE) ; - ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_FALSE) ; - } - else - { - ss_state_setflag(&sta,SS_FLAGS_PID,sv->pid) ; - ss_state_setflag(&sta,SS_FLAGS_STATE,SS_FLAGS_TRUE) ; - } - } - ss_state_setflag(&sta,SS_FLAGS_RELOAD,SS_FLAGS_FALSE) ; - ss_state_setflag(&sta,SS_FLAGS_INIT,SS_FLAGS_FALSE) ; - ss_state_setflag(&sta,SS_FLAGS_UNSUPERVISE,SS_FLAGS_FALSE) ; - VERBO2 strerr_warni2x("Write state file of: ",name) ; - if (!ss_state_write(&sta,state,name)) - { - VERBO1 strerr_warnwu2sys("write state file of: ",name) ; - ret = 111 ; - } - if (!nret) VERBO1 strerr_warni3x((sv->sig > 3) ? "Stopped" : "Started"," successfully: ",name) ; - } - - tain_now_g() ; - tain_addsec(&ttmain,&STAMP,2) ; - - for (unsigned int i = 0 ; i < genalloc_len(ss_resolve_sig_t,&gakeep) ; i++) - { - ss_resolve_sig_t *sv = &genalloc_s(ss_resolve_sig_t,&gakeep)[i] ; - if (!ftrigr_unsubscribe_g(&fifo, sv->ids, &ttmain)) - { - VERBO3 strerr_warnwu2sys("unsubscribe to fifo of: ",sv->res.sa.s + sv->res.name) ; - ret = 111 ; - } - } + if (!svc_init_pipe(&fifo,&gakeep,&ttmain)) strerr_diefu1x(111,"init pipe") ; + + ret = doit(spfd,&gakeep,&ttmain) ; finish: - ftrigr_end(&fifo) ; - selfpipe_finish() ; - stralloc_free(&sares) ; - ss_resolve_graph_free(&graph) ; - genalloc_free(ss_resolve_sig_t,&gakeep) ; - ss_resolve_free(&res) ; - - return (ret > 1) ? 111 : 0 ; + ftrigr_end(&fifo) ; + selfpipe_finish() ; + stralloc_free(&sares) ; + ss_resolve_graph_free(&graph) ; + genalloc_free(ss_resolve_sig_t,&gakeep) ; + ss_resolve_free(&res) ; + + return (!ret) ? 111 : 0 ; } diff --git a/src/lib66/svc_init_pipe.c b/src/lib66/svc_init_pipe.c index 054b844d510f271282ee5d7f1592e0b98a58e90e..7658cfafabb2abd31c3fec6d8994d9fe27c3fe0c 100644 --- a/src/lib66/svc_init_pipe.c +++ b/src/lib66/svc_init_pipe.c @@ -31,27 +31,18 @@ #include <66/resolve.h> -int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv) +int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv,tain_t *deadline) { - tain_t ttmain ; - - tain_now_g() ; - tain_addsec(&ttmain,&STAMP,2) ; - ss_resolve_sig_t *svc ; - //VERBO2 strerr_warni1x("initiate fifo: fifo") ; - if (!ftrigr_startf(fifo, &ttmain, &STAMP)) + if (!ftrigr_startf_g(fifo, deadline)) VERBO3 { strerr_warnwu1sys("initiate fifo") ; return 0 ; } for (unsigned int i = 0 ; i < genalloc_len(ss_resolve_sig_t,gasv) ; i++) { svc = &genalloc_s(ss_resolve_sig_t,gasv)[i] ; - int r ; - size_t siglen = strlen(svc->sigtosend) ; char *svok = svc->res.sa.s + svc->res.runat ; size_t scanlen = strlen(svok) ; - char svfifo[scanlen + 6 + 1] ; memcpy(svfifo, svok,scanlen) ; memcpy(svfifo + scanlen, "/event",6) ; @@ -65,31 +56,14 @@ int svc_init_pipe(ftrigr_t *fifo,genalloc *gasv) } VERBO3 strerr_warnt2x("subcribe to fifo: ",svfifo) ; - svc->ids = ftrigr_subscribe_g(fifo, svfifo, "[DuUdOxs]", FTRIGR_REPEAT, &ttmain) ; + svc->ids = ftrigr_subscribe_g(fifo, svfifo, "[DuUdOxs]", FTRIGR_REPEAT, deadline) ; if (!svc->ids) { VERBO3 strerr_warnwu2sys("subcribe to fifo: ",svfifo) ; goto end ; } - - VERBO3 strerr_warnt6x("send signal: ",svc->sigtosend," to: ", svok,"/",S6_SUPERVISE_CTLDIR) ; - r = s6_svc_writectl(svok, S6_SUPERVISE_CTLDIR, svc->sigtosend, siglen) ; - if (r < 0) - { - VERBO3 strerr_warnwu3sys("something is wrong with the ",svok, "/" S6_SUPERVISE_CTLDIR " directory. errno reported") ; - goto end ; - } - if (!r) - { - VERBO3 strerr_warnw3x("sv: ",svok, " is not supervised") ; - goto end ; - } } - - return 1 ; - end: - return 0 ; } diff --git a/src/lib66/svc_send.c b/src/lib66/svc_send.c index bf7b84ef4a0747752fb7a22b7af42a4633f37e6f..8519a437f9bb91f3bd2e1393613ae6bdfb05774e 100644 --- a/src/lib66/svc_send.c +++ b/src/lib66/svc_send.c @@ -22,15 +22,13 @@ #include <66/resolve.h> #include <66/ssexec.h> - - int svc_send(ssexec_t *info,genalloc *ga,char const *sig,char const *const *envp) { unsigned int i = 0 ; int nargc = 3 + genalloc_len(ss_resolve_t,ga) ; char const *newargv[nargc] ; unsigned int m = 0 ; - + newargv[m++] = "fake_name" ; newargv[m++] = sig ;