From dc7039b8d8c6a406f90a94543bf4416960238f5e Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 18 Mar 2018 11:49:27 +0100 Subject: [PATCH 01/10] Fix #100: Adjust path to COND_RECONF /var/run symlink may be missing On systems with the new /run hierarchy the compat symlink from /var/run may be missing, or not yet be set up by bootmisc.so. This patch adds a layer of safety to the condition layer, both set and get cond ops now perform an adjustmed of the condition path if needed. Signed-off-by: Joachim Nilsson --- src/cond-w.c | 8 ++++++-- src/cond.c | 8 ++++++-- src/pid.h | 15 ++++++++++++++- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/cond-w.c b/src/cond-w.c index 2c44dbb1..afe69a63 100644 --- a/src/cond-w.c +++ b/src/cond-w.c @@ -31,12 +31,16 @@ #include "pid.h" #include "service.h" -static int cond_set_gen(const char *path, unsigned int gen) +static int cond_set_gen(const char *file, unsigned int gen) { + char *ptr, path[256]; FILE *fp; int ret; - fp = fopen(path, "w"); + /* /var/run --> /run symlink may not exist (yet) */ + ptr = pid_runpath(file, path, sizeof(path)); + + fp = fopen(ptr, "w"); if (!fp) return -1; diff --git a/src/cond.c b/src/cond.c index 15a02088..9698b963 100644 --- a/src/cond.c +++ b/src/cond.c @@ -51,13 +51,17 @@ const char *cond_path(const char *name) return pid_runpath(tmp, file, sizeof(file)); } -unsigned int cond_get_gen(const char *path) +unsigned int cond_get_gen(const char *file) { + char *ptr, path[256]; unsigned int gen; FILE *fp; int ret; - fp = fopen(path, "r"); + /* /var/run --> /run symlink may not exist (yet) */ + ptr = pid_runpath(file, path, sizeof(path)); + + fp = fopen(ptr, "r"); if (!fp) return 0; diff --git a/src/pid.h b/src/pid.h index d01558a2..9eaec3d6 100644 --- a/src/pid.h +++ b/src/pid.h @@ -34,7 +34,17 @@ char *pid_file (svc_t *svc); int pid_file_create (svc_t *svc); int pid_file_parse (svc_t *svc, char *arg); -static inline char *pid_runpath(char *file, char *path, size_t len) +/** + * pid_runpath - Adjust /var/run --> /run path depending on system + * @file: Path to file in /run/path or /var/run/path + * @path: Pointer to buffer to write correct path + * @len: Length, in bytes, of @path buffer + * + * Returns: + * Always returns a valid pointer, which can be either @path with a /run + * or /var/run prefix to @file, or it may be @file if the prefix is OK. + */ +static inline char *pid_runpath(const char *file, char *path, size_t len) { static int unknown = 1; static char *prefix = "/var/run"; @@ -45,6 +55,9 @@ static inline char *pid_runpath(char *file, char *path, size_t len) unknown = 0; } + if (!strncmp(file, prefix, strlen(prefix))) + return (char *)file; + if (!strncmp(file, "/var/run/", 9)) file += 9; else if (!strncmp(file, "/run/", 5)) From 406339e75552e3677970a11f831f7f07430cc845 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 18 Mar 2018 17:25:02 +0100 Subject: [PATCH 02/10] Refactor, unify finit_tty_t + tty_node_t --> struct tty Signed-off-by: Joachim Nilsson --- plugins/tty.c | 10 ++--- src/tty.c | 100 +++++++++++++++++++++++++------------------------- src/tty.h | 30 ++++++--------- 3 files changed, 67 insertions(+), 73 deletions(-) diff --git a/plugins/tty.c b/plugins/tty.c index d0c9bfaa..93d10a79 100644 --- a/plugins/tty.c +++ b/plugins/tty.c @@ -57,7 +57,7 @@ static void watcher(void *arg, int fd, int events) { int len = 0; char buf[EVENT_SIZE], name[42]; - tty_node_t *entry; + struct tty *entry; struct inotify_event *notified = (struct inotify_event *)buf; while ((len = read(fd, buf, sizeof(buf)))) { @@ -72,11 +72,11 @@ static void watcher(void *arg, int fd, int events) snprintf(name, sizeof(name), "/dev/%s", notified->name); entry = tty_find(name); - if (entry && tty_enabled(&entry->data)) { + if (entry && tty_enabled(entry)) { if (notified->mask & IN_CREATE) - tty_start(&entry->data); - else if (entry->data.pid) - tty_stop(&entry->data); + tty_start(entry); + else if (entry->pid) + tty_stop(entry); } } } diff --git a/src/tty.c b/src/tty.c index 2314311e..9f60cc1a 100644 --- a/src/tty.c +++ b/src/tty.c @@ -41,7 +41,7 @@ #ifdef FALLBACK_SHELL static pid_t fallback = 0; #endif -static LIST_HEAD(, tty_node) tty_list = LIST_HEAD_INITIALIZER(); +static LIST_HEAD(, tty) tty_list = LIST_HEAD_INITIALIZER(); static char *canonicalize(char *tty) { @@ -88,7 +88,7 @@ static char *canonicalize(char *tty) void tty_mark(void) { - tty_node_t *tty; + struct tty *tty; LIST_FOREACH(tty, &tty_list, link) tty->dirty = -1; @@ -96,17 +96,17 @@ void tty_mark(void) void tty_sweep(void) { - tty_node_t *tty, *tmp; + struct tty *tty, *tmp; LIST_FOREACH_SAFE(tty, &tty_list, link, tmp) { if (!tty->dirty) continue; - _d("TTY %s dirty, stopping ...", tty->data.name); - tty_stop(&tty->data); + _d("TTY %s dirty, stopping ...", tty->name); + tty_stop(tty); if (tty->dirty == -1) { - _d("TTY %s removed, cleaning up.", tty->data.name); + _d("TTY %s removed, cleaning up.", tty->name); tty_unregister(tty); } } @@ -136,7 +136,7 @@ void tty_sweep(void) */ int tty_register(char *line, struct rlimit rlimit[], char *file) { - tty_node_t *entry; + struct tty *entry; int insert = 0, noclear = 0, nowait = 0, nologin = 0; size_t i, num = 0; char *tok, *cmd = NULL, *args[TTY_MAX_ARGS]; @@ -238,13 +238,13 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) } } - entry->data.name = dev; - entry->data.baud = baud ? strdup(baud) : NULL; - entry->data.term = term ? strdup(term) : NULL; - entry->data.noclear = noclear; - entry->data.nowait = nowait; - entry->data.nologin = nologin; - entry->data.runlevels = conf_parse_runlevels(runlevels); + entry->name = dev; + entry->baud = baud ? strdup(baud) : NULL; + entry->term = term ? strdup(term) : NULL; + entry->noclear = noclear; + entry->nowait = nowait; + entry->nologin = nologin; + entry->runlevels = conf_parse_runlevels(runlevels); /* External getty */ if (cmd) { @@ -255,12 +255,12 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) tok = cmd; else tok++; - entry->data.cmd = cmd; + entry->cmd = cmd; args[1] = strdup(tok); for (i = 1; i < num; i++) - entry->data.args[j++] = strdup(args[i]); - entry->data.args[++j] = NULL; + entry->args[j++] = strdup(args[i]); + entry->args[++j] = NULL; } _d("Registering %s getty on TTY %s at %s baud with term %s on runlevels %s", @@ -270,7 +270,7 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) LIST_INSERT_HEAD(&tty_list, entry, link); /* Register configured limits */ - memcpy(entry->data.rlimit, rlimit, sizeof(entry->data.rlimit)); + memcpy(entry->rlimit, rlimit, sizeof(entry->rlimit)); if (file && conf_changed(file)) entry->dirty = 1; /* Modified, restart */ @@ -281,7 +281,7 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) return 0; } -int tty_unregister(tty_node_t *tty) +int tty_unregister(struct tty *tty) { if (!tty) { _e("Missing argument"); @@ -290,20 +290,20 @@ int tty_unregister(tty_node_t *tty) LIST_REMOVE(tty, link); - if (tty->data.name) - free(tty->data.name); - if (tty->data.baud) - free(tty->data.baud); - if (tty->data.term) - free(tty->data.term); - if (tty->data.cmd) { + if (tty->name) + free(tty->name); + if (tty->baud) + free(tty->baud); + if (tty->term) + free(tty->term); + if (tty->cmd) { int i; - free(tty->data.cmd); + free(tty->cmd); for (i = 0; i < TTY_MAX_ARGS; i++) { - if (tty->data.args[i]) - free(tty->data.args[i]); - tty->data.args[i] = NULL; + if (tty->args[i]) + free(tty->args[i]); + tty->args[i] = NULL; } } free(tty); @@ -311,12 +311,12 @@ int tty_unregister(tty_node_t *tty) return 0; } -tty_node_t *tty_find(char *dev) +struct tty *tty_find(char *dev) { - tty_node_t *entry; + struct tty *entry; LIST_FOREACH(entry, &tty_list, link) { - if (!strcmp(dev, entry->data.name)) + if (!strcmp(dev, entry->name)) return entry; } @@ -326,7 +326,7 @@ tty_node_t *tty_find(char *dev) size_t tty_num(void) { size_t num = 0; - tty_node_t *entry; + struct tty *entry; LIST_FOREACH(entry, &tty_list, link) num++; @@ -337,22 +337,22 @@ size_t tty_num(void) size_t tty_num_active(void) { size_t num = 0; - tty_node_t *entry; + struct tty *entry; LIST_FOREACH(entry, &tty_list, link) { - if (entry->data.pid) + if (entry->pid) num++; } return num; } -tty_node_t *tty_find_by_pid(pid_t pid) +struct tty *tty_find_by_pid(pid_t pid) { - tty_node_t *entry; + struct tty *entry; LIST_FOREACH(entry, &tty_list, link) { - if (entry->data.pid == pid) + if (entry->pid == pid) return entry; } @@ -375,7 +375,7 @@ static int tty_exist(char *dev) return result; } -void tty_start(finit_tty_t *tty) +void tty_start(struct tty *tty) { char *dev; @@ -408,7 +408,7 @@ void tty_start(finit_tty_t *tty) tty->pid = run_getty2(dev, tty->cmd, tty->args, tty->noclear, tty->nowait, tty->rlimit); } -void tty_stop(finit_tty_t *tty) +void tty_stop(struct tty *tty) { if (!tty->pid) return; @@ -425,7 +425,7 @@ void tty_stop(finit_tty_t *tty) tty->pid = 0; } -int tty_enabled(finit_tty_t *tty) +int tty_enabled(struct tty *tty) { if (!tty) return 0; @@ -473,12 +473,12 @@ int tty_fallback(pid_t lost) return 0; } -static void tty_action(tty_node_t *tty) +static void tty_action(struct tty *tty) { - if (!tty_enabled(&tty->data)) - tty_stop(&tty->data); + if (!tty_enabled(tty)) + tty_stop(tty); else - tty_start(&tty->data); + tty_start(tty); } /* @@ -486,7 +486,7 @@ static void tty_action(tty_node_t *tty) */ int tty_respawn(pid_t pid) { - tty_node_t *tty = tty_find_by_pid(pid); + struct tty *tty = tty_find_by_pid(pid); if (!tty) return tty_fallback(pid); @@ -495,7 +495,7 @@ int tty_respawn(pid_t pid) utmp_set_dead(pid); /* Clear PID to be able to respawn it. */ - tty->data.pid = 0; + tty->pid = 0; tty_action(tty); return 1; @@ -506,7 +506,7 @@ int tty_respawn(pid_t pid) */ void tty_reload(char *dev) { - tty_node_t *tty; + struct tty *tty; if (dev) { tty = tty_find(dev); @@ -531,7 +531,7 @@ void tty_reload(char *dev) /* Start all TTYs that exist in the system and are allowed at this runlevel */ void tty_runlevel(void) { - tty_node_t *tty; + struct tty *tty; LIST_FOREACH(tty, &tty_list, link) tty_action(tty); diff --git a/src/tty.h b/src/tty.h index 1ed5d50b..40c00cb4 100644 --- a/src/tty.h +++ b/src/tty.h @@ -32,7 +32,9 @@ #define TTY_MAX_ARGS 16 #define EVENT_SIZE ((sizeof(struct inotify_event) + NAME_MAX + 1)) -typedef struct { +struct tty { + LIST_ENTRY(tty) link; + char *name; char *baud; char *term; @@ -48,32 +50,24 @@ typedef struct { /* Limits and scoping */ struct rlimit rlimit[RLIMIT_NLIMITS]; -} finit_tty_t; -typedef struct tty_node { - LIST_ENTRY(tty_node) link; - finit_tty_t data; - - /* XXX: Yes, TTYs should be refactored into a separate SVC type. */ - int dirty; /* Set if old mtime != new mtime => reloaded, - * or -1 when marked for removal */ -} tty_node_t; - -//extern LIST_HEAD(, tty_node) tty_list; + /* Set if modified => reloaded, or -1 when marked for removal */ + int dirty; +}; void tty_mark (void); void tty_sweep (void); int tty_register (char *line, struct rlimit rlimit[], char *file); -int tty_unregister (tty_node_t *tty); +int tty_unregister (struct tty *tty); -tty_node_t *tty_find (char *dev); +struct tty *tty_find (char *dev); size_t tty_num (void); size_t tty_num_active (void); -tty_node_t *tty_find_by_pid (pid_t pid); -void tty_start (finit_tty_t *tty); -void tty_stop (finit_tty_t *tty); -int tty_enabled (finit_tty_t *tty); +struct tty *tty_find_by_pid (pid_t pid); +void tty_start (struct tty *tty); +void tty_stop (struct tty *tty); +int tty_enabled (struct tty *tty); int tty_respawn (pid_t pid); void tty_reload (char *dev); void tty_runlevel (void); From e9670b87b334f0db604b2ef60ed58394f5fc922c Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 18 Mar 2018 18:58:19 +0100 Subject: [PATCH 03/10] Refactor, convert struct tty members to static strings Signed-off-by: Joachim Nilsson --- src/exec.c | 2 +- src/getty.c | 2 +- src/tty.c | 12 +++--------- src/tty.h | 6 +++--- 4 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/exec.c b/src/exec.c index c4c69061..842181e1 100644 --- a/src/exec.c +++ b/src/exec.c @@ -363,7 +363,7 @@ pid_t run_getty(char *tty, char *baud, char *term, int noclear, int nowait, stru if (!pid) { speed_t speed = B38400; - if (baud) { + if (baud && baud[0]) { speed = stty_parse_speed(baud); if (B0 == speed) logit(LOG_CRIT, "TTY %s: Invalid speed %s", tty, baud); diff --git a/src/getty.c b/src/getty.c index 8852488f..58b95a1f 100644 --- a/src/getty.c +++ b/src/getty.c @@ -237,7 +237,7 @@ int getty(char *tty, speed_t speed, char *term, char *user) stty(fd, speed); close(fd); - if (term) + if (term && term[0]) setenv("TERM", term, 1); return do_login(name); diff --git a/src/tty.c b/src/tty.c index 9f60cc1a..2d63996a 100644 --- a/src/tty.c +++ b/src/tty.c @@ -238,9 +238,9 @@ int tty_register(char *line, struct rlimit rlimit[], char *file) } } - entry->name = dev; - entry->baud = baud ? strdup(baud) : NULL; - entry->term = term ? strdup(term) : NULL; + strlcpy(entry->name, dev, sizeof(entry->name)); + strlcpy(entry->baud, baud ? baud : "", sizeof(entry->baud)); + strlcpy(entry->term, term ? term : "", sizeof(entry->term)); entry->noclear = noclear; entry->nowait = nowait; entry->nologin = nologin; @@ -290,12 +290,6 @@ int tty_unregister(struct tty *tty) LIST_REMOVE(tty, link); - if (tty->name) - free(tty->name); - if (tty->baud) - free(tty->baud); - if (tty->term) - free(tty->term); if (tty->cmd) { int i; diff --git a/src/tty.h b/src/tty.h index 40c00cb4..b623917d 100644 --- a/src/tty.h +++ b/src/tty.h @@ -35,9 +35,9 @@ struct tty { LIST_ENTRY(tty) link; - char *name; - char *baud; - char *term; + char name[42]; + char baud[10]; + char term[10]; int noclear; int nowait; int nologin; From 7fe9f3c4b69c64834115a284b5a437d9697db851 Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Thu, 22 Mar 2018 08:06:57 +0100 Subject: [PATCH 04/10] Travis-CI: Disable CLANG build temporarily for Coverity Scan Signed-off-by: Joachim Nilsson --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e388a394..324c40eb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,9 +9,9 @@ sudo: false #sudo: true # Test build with both GCC and Clang (LLVM) +# - clang compiler: - gcc - - clang env: global: From 65ccc407fa3e0cd1c065351ae4ff9701f03bf86f Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Thu, 22 Mar 2018 08:08:48 +0100 Subject: [PATCH 05/10] Follow-up #100: Remove buggy "optimization", caught by Coverity Scan We cannot allow pid_runpath() to return its 'file' argument because that may be a stack variable in a helper function. Signed-off-by: Joachim Nilsson --- src/pid.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/pid.h b/src/pid.h index 9eaec3d6..f204858f 100644 --- a/src/pid.h +++ b/src/pid.h @@ -55,9 +55,6 @@ static inline char *pid_runpath(const char *file, char *path, size_t len) unknown = 0; } - if (!strncmp(file, prefix, strlen(prefix))) - return (char *)file; - if (!strncmp(file, "/var/run/", 9)) file += 9; else if (!strncmp(file, "/run/", 5)) From 3b2f2690e7b1f009c8edcad591cbccefeb8354fb Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 18 Jun 2018 18:33:13 +0200 Subject: [PATCH 06/10] initctl: start and restart should behave the same if svc has crashed MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by Mattias Walström, Westermo. Signed-off-by: Joachim Nilsson --- src/api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/api.c b/src/api.c index 55958ab6..5289cfd8 100644 --- a/src/api.c +++ b/src/api.c @@ -78,6 +78,9 @@ static int service_restart(svc_t *svc) if (!svc) return 1; + if (svc_is_blocked(svc)) + svc_start(svc); + svc_mark_dirty(svc); service_step(svc); From 43942ab513891629c3f457aaa060a6cbfacd7ddf Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 8 Jul 2018 19:20:56 +0200 Subject: [PATCH 07/10] watchdog.c: Update copyright years and reflow license header Signed-off-by: Joachim Nilsson --- src/watchdog.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/watchdog.c b/src/watchdog.c index fde0ebba..2c1e4ff1 100644 --- a/src/watchdog.c +++ b/src/watchdog.c @@ -1,6 +1,6 @@ /* Built-in watchdog daemon * - * Copyright (c) 2016 Joachim Nilsson + * Copyright (c) 2016-2018 Joachim Nilsson * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -9,16 +9,16 @@ * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. */ #include From 3a1ad67e920e594968029c79668e930ff02bd6dd Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Sun, 8 Jul 2018 19:21:49 +0200 Subject: [PATCH 08/10] Convert built-in watchdog to a standalone mini watchdogd Signed-off-by: Joachim Nilsson --- configure.ac | 8 ++++--- src/Makefile.am | 12 +++++++--- src/finit.c | 12 +++++++--- src/watchdog.c | 59 +++++++++++++++++++++++++++---------------------- 4 files changed, 55 insertions(+), 36 deletions(-) diff --git a/configure.ac b/configure.ac index 8a2fc124..0e4ecf3a 100644 --- a/configure.ac +++ b/configure.ac @@ -218,9 +218,11 @@ AM_CONDITIONAL(INETD, [test "x$enable_inetd" = "xyes"]) AM_CONDITIONAL(WATCHDOGD, [test "x$enable_watchdog" = "xyes"]) # Override default libdir, used for plugins and rescue.conf -#pkglibdir=$libdir/finit -#AC_SUBST(pkglibdir) -#AC_EXPAND_DIR(pkglibdir, "$libdir/finit") +pkglibdir=$libdir/finit +AC_SUBST(pkglibexecdir) +AC_EXPAND_DIR(pkglibexecdir, "$libexecdir/finit") +AC_DEFINE_UNQUOTED(FINIT_LIBPATH_, "$pkglibexecdir", [Finit libexec path]) + AC_EXPAND_DIR(plugin_path, "$libdir/finit/plugins") AC_SUBST(plugin_path) AC_DEFINE_UNQUOTED(PLUGIN_PATH, "$plugin_path", [Finit plugin path]) diff --git a/src/Makefile.am b/src/Makefile.am index 0d947efc..7880cc63 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -10,6 +10,9 @@ endif bin_PROGRAMS = logit sbin_PROGRAMS = finit initctl reboot +if WATCHDOGD +pkglibexec_PROGRAMS = watchdogd +endif logit_SOURCES = logit.c logit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99 @@ -36,9 +39,6 @@ pkginclude_HEADERS = cond.h finit.h helpers.h inetd.h log.h plugin.h svc.h if INETD finit_SOURCES += inetd.c inetd.h endif -if WATCHDOGD -finit_SOURCES += watchdog.c watchdog.h -endif finit_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99 finit_CFLAGS += $(lite_CFLAGS) $(uev_CFLAGS) @@ -63,6 +63,12 @@ reboot_LDADD = $(lite_LIBS) INIT_LNKS = telinit init REBOOT_LNKS = shutdown halt poweroff suspend +if WATCHDOGD +watchdogd_SOURCES = watchdog.c watchdog.h +watchdogd_CFLAGS = -W -Wall -Wextra -Wno-unused-parameter -std=gnu99 +#log.c log.h +endif + # Hook in install to add finit and reboot symlink(s) install-exec-hook: @$(INSTALL_DATA) $(srcdir)/rescue.conf $(DESTDIR)$(pkglibdir) diff --git a/src/finit.c b/src/finit.c index e62bcb8d..5ab8891f 100644 --- a/src/finit.c +++ b/src/finit.c @@ -47,7 +47,6 @@ #include "tty.h" #include "util.h" #include "utmp-api.h" -#include "watchdog.h" int wdogpid = 0; /* No watchdog by default */ int runlevel = 0; /* Bootstrap 'S' */ @@ -214,12 +213,18 @@ static void emergency_shell(void) */ static void finalize(void) { + svc_t *svc; + /* * Run startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) run_parts(runparts, NULL); + svc = svc_find(FINIT_LIBPATH_ "watchdogd", 1); + if (svc && !wdogpid) + wdogpid = svc->pid; + /* * Start all tasks/services in the configured runlevel */ @@ -412,9 +417,10 @@ int main(int argc, char* argv[]) } /* - * Start built-in watchdog as soon as possible, if enabled + * Start bundled watchdogd as soon as possible, if enabled */ - wdogpid = watchdog(argv[0]); + if (which(FINIT_LIBPATH_ "/watchdogd")) + service_register(SVC_TYPE_SERVICE, FINIT_LIBPATH_ "/watchdogd", global_rlimit, NULL); /* * Mount filesystems diff --git a/src/watchdog.c b/src/watchdog.c index 2c1e4ff1..54145e70 100644 --- a/src/watchdog.c +++ b/src/watchdog.c @@ -21,12 +21,18 @@ * SOFTWARE. */ +#include +#include +#include +#include +#include +#include +#include #include +#include #include #include -#include "finit.h" -#include "log.h" #include "watchdog.h" int running = 1; @@ -51,6 +57,9 @@ static int init(char *progname, char *devnode) signal(SIGTERM, sighandler); signal(SIGPWR, sighandler); + openlog(&progname[1], LOG_CONS | LOG_PID, LOG_DAEMON); + syslog(LOG_INFO, "Finit v%s basic watchdogd starting ...", VERSION); + fd = open(devnode, O_WRONLY); if (fd == -1) return -1; @@ -78,6 +87,7 @@ static int loop(int fd, int timeout) /* External watchdogd wants to take over ... */ if (handover) { + syslog(LOG_INFO, "Handing over %s and exiting ...", WDT_DEVNODE); ioctl(fd, WDIOC_KEEPALIVE, &dummy); return !write(fd, "V", 1); } @@ -85,35 +95,30 @@ static int loop(int fd, int timeout) return 0; } -int watchdog(char *progname) +int main(int argc, char *argv[]) { - int pid; + int fd, ret; - pid = fork(); - if (pid == 0) { - int fd, ret; - - fd = init(progname, WDT_DEVNODE); - if (fd == -1) { - if (ENOENT != errno) - _pe("Failed connecting to watchdog %s", WDT_DEVNODE); - _exit(1); - } - - ret = loop(fd, WDT_TIMEOUT); - while (!handover) { - /* Waiting for SIGTERM ... */ - sleep(1); - - /* Set lowest possible timeout on SIGTERM */ - ioctl(fd, WDIOC_SETTIMEOUT, &shutdown); - } - close(fd); - - _exit(ret); + fd = init(argv[0], WDT_DEVNODE); + if (fd == -1) { + if (ENOENT != errno) + syslog(LOG_CRIT, "Failed connecting to watchdog %s", WDT_DEVNODE); + return 1; } - return pid; + ret = loop(fd, WDT_TIMEOUT); + while (!handover) { + syslog(LOG_ALERT, "System going down ..."); + + /* Waiting for SIGTERM ... */ + sleep(1); + + /* Set lowest possible timeout on SIGTERM */ + ioctl(fd, WDIOC_SETTIMEOUT, &shutdown); + } + close(fd); + + return ret; } /** From 40db4f4f58c0920a18e4023377cae49d00bca83a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 9 Jul 2018 22:13:30 +0200 Subject: [PATCH 09/10] Minor, refactor to avoid namespace confusion with service.c API Signed-off-by: Joachim Nilsson --- src/api.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/api.c b/src/api.c index 5289cfd8..c6ac7254 100644 --- a/src/api.c +++ b/src/api.c @@ -51,7 +51,7 @@ static int call(int (*action)(svc_t *), char *buf, size_t len) return svc_parse_jobstr(buf, len, action, NULL); } -static int service_stop(svc_t *svc) +static int stop(svc_t *svc) { if (!svc) return 1; @@ -62,7 +62,7 @@ static int service_stop(svc_t *svc) return 0; } -static int service_start(svc_t *svc) +static int start(svc_t *svc) { if (!svc) return 1; @@ -73,7 +73,7 @@ static int service_start(svc_t *svc) return 0; } -static int service_restart(svc_t *svc) +static int restart(svc_t *svc) { if (!svc) return 1; @@ -87,9 +87,9 @@ static int service_restart(svc_t *svc) return 0; } -static int do_start (char *buf, size_t len) { return call(service_start, buf, len); } -static int do_stop (char *buf, size_t len) { return call(service_stop, buf, len); } -static int do_restart(char *buf, size_t len) { return call(service_restart, buf, len); } +static int do_start (char *buf, size_t len) { return call(start, buf, len); } +static int do_stop (char *buf, size_t len) { return call(stop, buf, len); } +static int do_restart(char *buf, size_t len) { return call(restart, buf, len); } static char query_buf[368]; static int missing(char *job, int id) From a487a308140f5e249cba47642739146a312b105a Mon Sep 17 00:00:00 2001 From: Joachim Nilsson Date: Mon, 9 Jul 2018 22:26:35 +0200 Subject: [PATCH 10/10] Refactor wdog tracking and hand-over to use svc_t instead of PID Signed-off-by: Joachim Nilsson --- src/api.c | 23 +++++++++++++++++------ src/finit.c | 13 ++++++++----- src/finit.h | 1 - src/sig.c | 10 ++++++---- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/src/api.c b/src/api.c index c6ac7254..bd6b5a34 100644 --- a/src/api.c +++ b/src/api.c @@ -44,6 +44,7 @@ #include "service.h" #include "util.h" +extern svc_t *wdog; static uev_t api_watcher; static int call(int (*action)(svc_t *), char *buf, size_t len) @@ -340,13 +341,23 @@ static void api_cb(uev_t *w, void *arg, int events) break; } - if (wdogpid > 0 && wdogpid != rq.runlevel) { - _d("Sending SIGTERM to %d", wdogpid); - kill(wdogpid, SIGTERM); - do_sleep(1); + _e("Request to hand-over wdog ... to PID %d", rq.runlevel); + svc = svc_find_by_pid(rq.runlevel); + if (!svc) { + logit(LOG_ERR, "Cannot find PID %d, not registered.", rq.runlevel); + break; } - _d("wdog was %d, now %d is in charge", wdogpid, rq.runlevel); - wdogpid = rq.runlevel; + + /* Disable and allow Finit to collect bundled watchdog */ + if (wdog) { + logit(LOG_NOTICE, "Stopping and removing %s (PID:%d)", wdog->cmd, wdog->pid); + stop(wdog); + if (wdog->protected) { + wdog->protected = 0; + wdog->runlevels = 0; + } + } + wdog = svc; break; case INIT_CMD_SVC_ITER: diff --git a/src/finit.c b/src/finit.c index 5ab8891f..2d02b369 100644 --- a/src/finit.c +++ b/src/finit.c @@ -48,7 +48,6 @@ #include "util.h" #include "utmp-api.h" -int wdogpid = 0; /* No watchdog by default */ int runlevel = 0; /* Bootstrap 'S' */ int cfglevel = RUNLEVEL; /* Fallback if no configured runlevel */ int prevlevel = -1; @@ -62,6 +61,7 @@ char *rcsd = FINIT_RCSD; char *runparts = NULL; uev_ctx_t *ctx = NULL; /* Main loop context */ +svc_t *wdog = NULL; /* No watchdog by default */ /* * Show user configured banner before service bootstrap progress @@ -215,16 +215,19 @@ static void finalize(void) { svc_t *svc; + /* + * Track bundled watchdogd in case a better one turns up + */ + svc = svc_find(FINIT_LIBPATH_ "/watchdogd", 1); + if (svc) + wdog = svc; + /* * Run startup scripts in the runparts directory, if any. */ if (runparts && fisdir(runparts) && !rescue) run_parts(runparts, NULL); - svc = svc_find(FINIT_LIBPATH_ "watchdogd", 1); - if (svc && !wdogpid) - wdogpid = svc->pid; - /* * Start all tasks/services in the configured runlevel */ diff --git a/src/finit.h b/src/finit.h index 95b02493..57b34c4b 100644 --- a/src/finit.h +++ b/src/finit.h @@ -92,7 +92,6 @@ struct init_request { char data[368]; }; -extern int wdogpid; extern int runlevel; extern int cfglevel; extern int prevlevel; diff --git a/src/sig.c b/src/sig.c index d0d279e8..96a67ba5 100644 --- a/src/sig.c +++ b/src/sig.c @@ -83,6 +83,8 @@ #include "util.h" #include "utmp-api.h" +extern svc_t *wdog; + /* * Old-style SysV shutdown sends a setenv cmd INIT_HALT with "=HALT", * "=POWERDOWN", or "" to cancel shutdown, before requesting change to @@ -185,8 +187,8 @@ void do_shutdown(shutop_t op) return; } - if (wdogpid) { - print(kill(wdogpid, SIGPWR) == 1, "Advising watchdog, system going down"); + if (wdog) { + print(kill(wdog->pid, SIGPWR) == 1, "Advising watchdog, system going down"); do_sleep(2); } @@ -208,11 +210,11 @@ void do_shutdown(shutop_t op) /* Reboot via watchdog or kernel, or shutdown? */ if (op == SHUT_REBOOT) { - if (wdogpid) { + if (wdog) { int timeout = 10; /* Wait here until the WDT reboots, or timeout with fallback */ - print(kill(wdogpid, SIGTERM) == 1, "Pending watchdog reboot"); + print(kill(wdog->pid, SIGTERM) == 1, "Pending watchdog reboot"); while (timeout--) do_sleep(1); }