aboutsummaryrefslogtreecommitdiff
path: root/src/genrc.c
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org>2018-05-20 10:53:30 +0300
committerSergey Poznyakoff <gray@gnu.org>2018-05-20 10:53:30 +0300
commitddb46c6aa42ada061e51c635c0230e4dc8eab881 (patch)
treeb003ae6af354f553207981b4fc281e8f9e19c60e /src/genrc.c
parented8389beadb7cf1f8d95fe7addbc9ff2783f4d07 (diff)
downloadgenrc-ddb46c6aa42ada061e51c635c0230e4dc8eab881.tar.gz
genrc-ddb46c6aa42ada061e51c635c0230e4dc8eab881.tar.bz2
Sentinel mode: restart the program on certain conditions
* Makefile.am: Create the ChangeLog file from git log. * configure.ac: Request git2chg * src/com_start.c: Use sigaction instead of signal. * src/genrc.8: Document new options. * src/genrc.c: New options --restart-on-exit and --restart-on-signal. * src/genrc.h (str_to_sig, str_to_int): New prototypes. (add_restart_condition): New prototype. * src/sentinel.c (restart_on, add_restart_condition): (check_failure_rate): New functions. (wait_loop): Return if restart is requested. (sentinel): Restart the program if needed.
Diffstat (limited to 'src/genrc.c')
-rw-r--r--src/genrc.c41
1 files changed, 34 insertions, 7 deletions
diff --git a/src/genrc.c b/src/genrc.c
index ae3070d..9052987 100644
--- a/src/genrc.c
+++ b/src/genrc.c
@@ -22,13 +22,15 @@ int genrc_verbose;
22enum { 22enum {
23 OPT_USAGE = 256, 23 OPT_USAGE = 256,
24 OPT_VERSION, 24 OPT_VERSION,
25 OPT_SIGNAL_RELOAD, 25 OPT_SIGNAL_RELOAD,
26 OPT_NO_RELOAD, 26 OPT_NO_RELOAD,
27 OPT_SIGNAL_STOP, 27 OPT_SIGNAL_STOP,
28 OPT_CREATE_PIDFILE 28 OPT_CREATE_PIDFILE,
29 OPT_RESTART_ON_EXIT,
30 OPT_RESTART_ON_SIGNAL,
29}; 31};
30 32
31struct option longopts[] = { 33struct option longopts[] = {
32 { "help", no_argument, 0, 'h' }, 34 { "help", no_argument, 0, 'h' },
33 { "usage", no_argument, 0, OPT_USAGE }, 35 { "usage", no_argument, 0, OPT_USAGE },
34 { "command", required_argument, 0, 'c' }, 36 { "command", required_argument, 0, 'c' },
@@ -42,12 +44,14 @@ struct option longopts[] = {
42 { "sentinel", no_argument, 0, 'S' }, 44 { "sentinel", no_argument, 0, 'S' },
43 { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE }, 45 { "create-pidfile", required_argument, 0, OPT_CREATE_PIDFILE },
44 { "version", no_argument, 0, OPT_VERSION }, 46 { "version", no_argument, 0, OPT_VERSION },
45 { "verbose", no_argument, 0, 'v' }, 47 { "verbose", no_argument, 0, 'v' },
46 { "user", required_argument, 0, 'u' }, 48 { "user", required_argument, 0, 'u' },
47 { "group", required_argument, 0, 'g' }, 49 { "group", required_argument, 0, 'g' },
50 { "restart-on-exit", required_argument, 0, OPT_RESTART_ON_EXIT },
51 { "restart-on-signal", required_argument, 0, OPT_RESTART_ON_SIGNAL },
48 { NULL } 52 { NULL }
49}; 53};
50char shortopts[] = "c:hF:g:P:p:St:u:v"; 54char shortopts[] = "c:hF:g:P:p:St:u:v";
51 55
52struct sigdefn { 56struct sigdefn {
53 char const *sig_name; 57 char const *sig_name;
@@ -124,22 +128,28 @@ is_numeric_str(char const *s)
124 s++; 128 s++;
125 } 129 }
126 return 1; 130 return 1;
127} 131}
128 132
129int 133int
130sig_name_to_str(char const *s) 134str_to_int(char const *s)
131{ 135{
132 if (is_numeric_str(s)) {
133 char *end; 136 char *end;
134 unsigned long n; 137 unsigned long n;
135 errno = 0; 138 errno = 0;
136 n = strtoul(s, &end, 10); 139 n = strtoul(s, &end, 10);
137 if (errno || *end || n > UINT_MAX) 140 if (errno || *end || n > UINT_MAX)
138 return -1; 141 return -1;
139 return n; 142 return n;
143}
144
145int
146str_to_sig(char const *s)
147{
148 if (is_numeric_str(s)) {
149 return str_to_int(s);
140 } else { 150 } else {
141 struct sigdefn *sd; 151 struct sigdefn *sd;
142 152
143 for (sd = sigdefn; sd->sig_name; sd++) { 153 for (sd = sigdefn; sd->sig_name; sd++) {
144 if (s[0] == 's' || s[0] == 'S') { 154 if (s[0] == 's' || s[0] == 'S') {
145 if (strcasecmp(sd->sig_name, s) == 0) 155 if (strcasecmp(sd->sig_name, s) == 0)
@@ -180,23 +190,32 @@ char const *help_msg[] = {
180 " run with this group(s) privileges", 190 " run with this group(s) privileges",
181 "", 191 "",
182 "Additional configuration:", 192 "Additional configuration:",
183 "", 193 "",
184 " -t, --timeout=SECONDS time to wait for the program to start up or", 194 " -t, --timeout=SECONDS time to wait for the program to start up or",
185 " terminate", 195 " terminate",
186 " --sentinel PROGRAM runs in foreground; disconnect from the",
187 " controlling terminal, run it and act as a sentinel",
188 " -P, --pid-from=SOURCE where to look for PIDs of the running programs", 196 " -P, --pid-from=SOURCE where to look for PIDs of the running programs",
189 " -F, --pidfile=NAME name of the PID file", 197 " -F, --pidfile=NAME name of the PID file",
190 " (same as --pid-from=FILE:NAME)", 198 " (same as --pid-from=FILE:NAME)",
191 " --signal-reload=SIG signal to send on reload (default: SIGHUP)", 199 " --signal-reload=SIG signal to send on reload (default: SIGHUP)",
192 " setting to 0 is equivalent to --no-reload", 200 " setting to 0 is equivalent to --no-reload",
193 " --no-reload makes reload equivalent to restart", 201 " --no-reload makes reload equivalent to restart",
194 " --signal-stop=SIG signal to send in order to terminate the program", 202 " --signal-stop=SIG signal to send in order to terminate the program",
195 " (default: SIGTERM)", 203 " (default: SIGTERM)",
196 "", 204 "",
205 "Sentinel mode:",
206 "",
207 " --sentinel PROGRAM runs in foreground; disconnect from the",
208 " controlling terminal, run it and act as a sentinel",
209 " --restart-on-exit=[!]CODE[,...]",
210 " restart the program if it exits with one of the",
211 " listed status codes",
212 " --restart-on-signal=[!]SIG[,...]",
213 " restart the program if it terminates on one of the",
214 " listed signals",
215 "",
197 "Informational options:", 216 "Informational options:",
198 "", 217 "",
199 " -h, --help display this help list", 218 " -h, --help display this help list",
200 " --usage display short usage information", 219 " --usage display short usage information",
201 " --version display program version and exist", 220 " --version display program version and exist",
202 "", 221 "",
@@ -269,12 +288,14 @@ char const *usage_msg[] = {
269 "[--group GROUP[,GROUP...]]", 288 "[--group GROUP[,GROUP...]]",
270 "[--help]", 289 "[--help]",
271 "[--no-reload]", 290 "[--no-reload]",
272 "[--pid-from=SOURCE]", 291 "[--pid-from=SOURCE]",
273 "[--pidfile=PIDFILE]", 292 "[--pidfile=PIDFILE]",
274 "[--program=PROGRAM]", 293 "[--program=PROGRAM]",
294 "[--restart-on-exit=[!]CODE[,...]]",
295 "[--restart-on-signal=[!]SIG[,...]]",
275 "[--sentinel]", 296 "[--sentinel]",
276 "[--signal-reload=SIG]", 297 "[--signal-reload=SIG]",
277 "[--signal-stop=SIG]", 298 "[--signal-stop=SIG]",
278 "[--timeout=SECONDS]", 299 "[--timeout=SECONDS]",
279 "[--usage]", 300 "[--usage]",
280 "[--user=USER]", 301 "[--user=USER]",
@@ -419,12 +440,18 @@ main(int argc, char **argv)
419 case 't': 440 case 't':
420 setenv("GENRC_TIMEOUT", optarg, 1); 441 setenv("GENRC_TIMEOUT", optarg, 1);
421 break; 442 break;
422 case 'S': 443 case 'S':
423 setenv("GENRC_SENTINEL", "1", 1); 444 setenv("GENRC_SENTINEL", "1", 1);
424 break; 445 break;
446 case OPT_RESTART_ON_EXIT:
447 add_restart_condition(RESTART_ON_EXIT, optarg);
448 break;
449 case OPT_RESTART_ON_SIGNAL:
450 add_restart_condition(RESTART_ON_SIGNAL, optarg);
451 break;
425 case OPT_NO_RELOAD: 452 case OPT_NO_RELOAD:
426 no_reload = 1; 453 no_reload = 1;
427 break; 454 break;
428 case OPT_SIGNAL_RELOAD: 455 case OPT_SIGNAL_RELOAD:
429 setenv("GENRC_SIGNAL_RELOAD", optarg, 1); 456 setenv("GENRC_SIGNAL_RELOAD", optarg, 1);
430 break; 457 break;
@@ -447,21 +474,21 @@ main(int argc, char **argv)
447 if ((p = getenv("GENRC_PROGRAM")) != NULL) 474 if ((p = getenv("GENRC_PROGRAM")) != NULL)
448 genrc_program = p; 475 genrc_program = p;
449 476
450 if (no_reload) 477 if (no_reload)
451 genrc_no_reload = 1; 478 genrc_no_reload = 1;
452 else if ((p = getenv("GENRC_SIGNAL_RELOAD")) != NULL) { 479 else if ((p = getenv("GENRC_SIGNAL_RELOAD")) != NULL) {
453 genrc_signal_reload = sig_name_to_str(p); 480 genrc_signal_reload = str_to_sig(p);
454 if (genrc_signal_reload == -1) 481 if (genrc_signal_reload == -1)
455 usage_error("%s: invalid signal number", p); 482 usage_error("%s: invalid signal number", p);
456 else if (genrc_signal_reload == 0) 483 else if (genrc_signal_reload == 0)
457 genrc_no_reload = 1; 484 genrc_no_reload = 1;
458 } 485 }
459 486
460 if ((p = getenv("GENRC_SIGNAL_STOP")) != NULL) { 487 if ((p = getenv("GENRC_SIGNAL_STOP")) != NULL) {
461 genrc_signal_stop = sig_name_to_str(p); 488 genrc_signal_stop = str_to_sig(p);
462 if (genrc_signal_stop <= 0) 489 if (genrc_signal_stop <= 0)
463 usage_error("%s: invalid signal number", p); 490 usage_error("%s: invalid signal number", p);
464 } 491 }
465 492
466 if ((p = getenv("GENRC_TIMEOUT")) != NULL) { 493 if ((p = getenv("GENRC_TIMEOUT")) != NULL) {
467 char *end; 494 char *end;

Return to:

Send suggestions and report system problems to the System administrator.