summaryrefslogtreecommitdiffstats
path: root/watchfrr
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2018-09-27 04:18:48 +0200
committerDavid Lamparter <equinox@opensourcerouting.org>2018-10-02 12:27:47 +0200
commit0a7c7856e3eb6db017d3d0c4d19d55c6cdb212e9 (patch)
tree4a6cb7cee5c17e1e51ba8fe6b81e5c1b40e628ba /watchfrr
parentMerge pull request #3102 from ton31337/feature/match_blackhole_nexthops (diff)
downloadfrr-0a7c7856e3eb6db017d3d0c4d19d55c6cdb212e9.tar.xz
frr-0a7c7856e3eb6db017d3d0c4d19d55c6cdb212e9.zip
watchfrr, lib: cleanup & delay detaching
This cleans up watchfrr to be more "normal" like the other daemons in terms of what it does in main(), i.e. using the full frr_*() call set. Also, this changes the startup behaviour on watchfrr to stay attached on the daemon's parent process until startup is really complete. This should allow removing the "watchfrr.started" hack at some point. Signed-off-by: David Lamparter <equinox@diac24.net>
Diffstat (limited to 'watchfrr')
-rw-r--r--watchfrr/watchfrr.c165
-rw-r--r--watchfrr/watchfrr.h4
2 files changed, 69 insertions, 100 deletions
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index ec922490e..e32bf3359 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -55,9 +55,11 @@
#define PING_TOKEN "PING"
+DEFINE_MGROUP(WATCHFRR, "watchfrr")
+DEFINE_MTYPE_STATIC(WATCHFRR, WATCHFRR_DAEMON, "watchfrr daemon entry")
+
/* Needs to be global, referenced somewhere inside libfrr. */
struct thread_master *master;
-static char pidfile_default[256];
static bool watch_only = false;
@@ -230,7 +232,7 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
name of the daemon should be substituted.\n\
--dry Do not start or restart anything, just log.\n\
-p, --pid-file Set process identifier file name\n\
- (default is %s).\n\
+ (default is %s/watchfrr.pid).\n\
-b, --blank-string\n\
When the supplied argument string is found in any of the\n\
various shell command arguments (-r, -s, or -k), replace\n\
@@ -240,7 +242,7 @@ Otherwise, the interval is doubled (but capped at the -M value).\n\n",
-h, --help Display this help and exit\n",
frr_vtydir, DEFAULT_LOGLEVEL, LOG_EMERG, LOG_DEBUG, LOG_DEBUG,
DEFAULT_MIN_RESTART, DEFAULT_MAX_RESTART, DEFAULT_PERIOD,
- DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, pidfile_default);
+ DEFAULT_TIMEOUT, DEFAULT_RESTART_TIMEOUT, frr_vtydir);
}
static pid_t run_background(char *shell_cmd)
@@ -609,12 +611,13 @@ static void daemon_send_ready(void)
if (!sent && gs.numdown == 0) {
FILE *fp;
+ zlog_notice("all daemons up, doing startup-complete notify");
+ frr_detach();
+
fp = fopen(DAEMON_VTY_DIR "/watchfrr.started", "w");
if (fp)
fclose(fp);
#if defined HAVE_SYSTEMD
- zlog_notice(
- "Watchfrr: Notifying Systemd we are up and running");
systemd_send_started(master, 0);
#endif
sent = 1;
@@ -961,6 +964,53 @@ static char *translate_blanks(const char *cmd, const char *blankstr)
return res;
}
+static void watchfrr_init(int argc, char **argv)
+{
+ const char *special = "zebra";
+ int i;
+ struct daemon *dmn, **add = &gs.daemons;
+ char alldaemons[512] = "", *p = alldaemons;
+
+ for (i = optind; i < argc; i++) {
+ dmn = XCALLOC(MTYPE_WATCHFRR_DAEMON, sizeof(*dmn));
+
+ dmn->name = dmn->restart.name = argv[i];
+ dmn->state = DAEMON_INIT;
+ gs.numdaemons++;
+ gs.numdown++;
+ dmn->fd = -1;
+ dmn->t_wakeup = NULL;
+ thread_add_timer_msec(master, wakeup_init, dmn,
+ 100 + (random() % 900),
+ &dmn->t_wakeup);
+ dmn->restart.interval = gs.min_restart_interval;
+ *add = dmn;
+ add = &dmn->next;
+
+ if (!strcmp(dmn->name, special))
+ gs.special = dmn;
+ }
+
+ if (!gs.daemons) {
+ fprintf(stderr,
+ "Must specify one or more daemons to monitor.\n\n");
+ frr_help_exit(1);
+ }
+ if (!watch_only && !gs.special) {
+ fprintf(stderr, "\"%s\" daemon must be in daemon lists\n\n",
+ special);
+ frr_help_exit(1);
+ }
+
+ for (dmn = gs.daemons; dmn; dmn = dmn->next) {
+ snprintf(p, alldaemons + sizeof(alldaemons) - p, "%s%s",
+ (p == alldaemons) ? "" : " ", dmn->name);
+ p += strlen(p);
+ }
+ zlog_notice("%s %s watching [%s]%s", progname, FRR_VERSION, alldaemons,
+ watch_only ? ", monitor mode" : "");
+}
+
struct zebra_privs_t watchfrr_privs = {
#ifdef VTY_GROUP
.vty_group = VTY_GROUP,
@@ -984,7 +1034,8 @@ static struct quagga_signal_t watchfrr_signals[] = {
FRR_DAEMON_INFO(watchfrr, WATCHFRR,
.flags = FRR_NO_PRIVSEP | FRR_NO_TCPVTY | FRR_LIMITED_CLI
- | FRR_NO_CFG_PID_DRY | FRR_NO_ZCLIENT,
+ | FRR_NO_CFG_PID_DRY | FRR_NO_ZCLIENT
+ | FRR_DETACH_LATER,
.printhelp = printhelp,
.copyright = "Copyright 2004 Andrew J. Schorr",
@@ -999,13 +1050,8 @@ FRR_DAEMON_INFO(watchfrr, WATCHFRR,
int main(int argc, char **argv)
{
int opt;
- const char *pidfile = pidfile_default;
- const char *special = "zebra";
const char *blankstr = NULL;
- snprintf(pidfile_default, sizeof(pidfile_default), "%s/watchfrr.pid",
- frr_vtydir);
-
frr_preinit(&watchfrr_di, argc, argv);
progname = watchfrr_di.progname;
@@ -1087,7 +1133,7 @@ int main(int argc, char **argv)
gs.period = 1000 * period;
} break;
case 'p':
- pidfile = optarg;
+ watchfrr_di.pid_file = optarg;
break;
case 'r':
if (!valid_command(optarg)) {
@@ -1167,99 +1213,18 @@ int main(int argc, char **argv)
master = frr_init();
watchfrr_error_init();
+ watchfrr_init(argc, argv);
+ watchfrr_vty_init();
+
+ frr_config_fork();
zlog_set_level(ZLOG_DEST_MONITOR, ZLOG_DISABLED);
- if (watchfrr_di.daemon_mode) {
+ if (watchfrr_di.daemon_mode)
zlog_set_level(ZLOG_DEST_SYSLOG, MIN(gs.loglevel, LOG_DEBUG));
- if (daemon(0, 0) < 0) {
- fprintf(stderr, "Watchfrr daemon failed: %s",
- strerror(errno));
- exit(1);
- }
- } else
+ else
zlog_set_level(ZLOG_DEST_STDOUT, MIN(gs.loglevel, LOG_DEBUG));
- watchfrr_vty_init();
-
- frr_vty_serv();
-
- {
- int i;
- struct daemon *tail = NULL;
-
- for (i = optind; i < argc; i++) {
- struct daemon *dmn;
-
- if (!(dmn = (struct daemon *)calloc(1, sizeof(*dmn)))) {
- fprintf(stderr, "calloc(1,%u) failed: %s\n",
- (unsigned int)sizeof(*dmn),
- safe_strerror(errno));
- return 1;
- }
- dmn->name = dmn->restart.name = argv[i];
- dmn->state = DAEMON_INIT;
- gs.numdaemons++;
- gs.numdown++;
- dmn->fd = -1;
- dmn->t_wakeup = NULL;
- thread_add_timer_msec(master, wakeup_init, dmn,
- 100 + (random() % 900),
- &dmn->t_wakeup);
- dmn->restart.interval = gs.min_restart_interval;
- if (tail)
- tail->next = dmn;
- else
- gs.daemons = dmn;
- tail = dmn;
-
- if (!strcmp(dmn->name, special))
- gs.special = dmn;
- }
- }
- if (!gs.daemons) {
- flog_err(EC_WATCHFRR_UNEXPECTED_DAEMONS,
- "Must specify one or more daemons to monitor.");
- frr_help_exit(1);
- }
- if (!watch_only && !gs.special) {
- flog_err(EC_WATCHFRR_UNEXPECTED_DAEMONS,
- "\"%s\" daemon must be in daemon lists", special);
- frr_help_exit(1);
- }
-
- /* Make sure we're not already running. */
- pid_output(pidfile);
-
- /* Announce which daemons are being monitored. */
- {
- struct daemon *dmn;
- size_t len = 0;
-
- for (dmn = gs.daemons; dmn; dmn = dmn->next)
- len += strlen(dmn->name) + 1;
-
- {
- char buf[len + 1];
- char *p = buf;
-
- for (dmn = gs.daemons; dmn; dmn = dmn->next) {
- if (p != buf)
- *p++ = ' ';
- strcpy(p, dmn->name);
- p += strlen(p);
- }
- zlog_notice("%s %s watching [%s]%s", progname,
- FRR_VERSION, buf,
- watch_only ? ", monitor mode" : "");
- }
- }
-
- {
- struct thread thread;
-
- while (thread_fetch(master, &thread))
- thread_call(&thread);
- }
+ frr_run(master);
systemd_send_stopping();
/* Not reached. */
diff --git a/watchfrr/watchfrr.h b/watchfrr/watchfrr.h
index 1a1c19056..ee16846a1 100644
--- a/watchfrr/watchfrr.h
+++ b/watchfrr/watchfrr.h
@@ -21,6 +21,10 @@
#ifndef FRR_WATCHFRR_H
#define FRR_WATCHFRR_H
+#include "lib/memory.h"
+
+DECLARE_MGROUP(WATCHFRR)
+
extern void watchfrr_vty_init(void);
extern pid_t integrated_write_pid;