[Toybox] [PATCH] Introducing toys/pending/watchdog.c
enh
enh at google.com
Sat Aug 22 13:05:25 PDT 2020
On Sat, Aug 22, 2020 at 11:22 AM Chris Sarra via Toybox <
toybox at lists.landley.net> wrote:
> This patch introduces a simple watchdog implementation for toybox. We
> send the appropriate ioctls to set the relevant timeouts, and intercept
> signals to safely shut down if required.
> ---
> toys/pending/watchdog.c | 128 ++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 128 insertions(+)
> create mode 100644 toys/pending/watchdog.c
>
> diff --git a/toys/pending/watchdog.c b/toys/pending/watchdog.c
> new file mode 100644
> index 00000000..0813fe69
> --- /dev/null
> +++ b/toys/pending/watchdog.c
> @@ -0,0 +1,128 @@
> +/* watchdog - start a watchdog timer with configurable kick frequencies
> +
> + Author: Chris Sarra, chrissarra at google.com
not sure why we're both working on a Saturday, but...
>
> + Date: 25 July 2019
> + Ref: kernel.org/doc/Documentation/watchdog/watchdog-api.txt
>
use the " * " indent from the other source files?
also mention that there's precedent in a busybox "watchdog", which this is
command-line compatible with?
> +USE_WATCHDOG(NEWTOY(watchdog, "Ft#T#", TOYFLAG_NEEDROOT|TOYFLAG_BIN))
>
huh. i didn't realize that USE_ worked _inside_ the comment! probably best
to move it below the comment as is the convention though.
> +config WATCHDOG
> + bool "watchdog"
> + default y
> + help
> + usage: watchdog [-F] [-t SW_TIMER_S] [-T HW_TIMER_S] DEV
> +
> + Start the watchdog timer at DEV with optional timeout parameters.
>
(blank line here.)
> + -F run in the foreground (do not daemonize)
> + -t software timer (in seconds)
> + -T hardware timer (in seconds)
>
say what the defaults are?
the busybox help implies that it's possible to use more precision than
seconds? afaik from the kernel source and kernel docs, though, that's a lie?
i think it would help to explain that -T is what you set the hardware
watchdog to, and -t is how often you kick it. i didn't get that from either
your --help or the busybox --help.
so something like:
-T N Set hardware watchdog to N seconds (default 60).
-t N Kick watchdog every N seconds (default 30).
? (note that it should be a tab between the "-T N" part and the "Set ..."
part.)
> +*/
> +#define FOR_watchdog
> +#include "toys.h"
> +#include "linux/watchdog.h"
> +
> +// Make sure no DEBUG variable is set; change this if you need debug
> prints!
> +#undef WATCHDOG_DEBUG
>
delete this or turn it into a -v flag, depending on whether it's still
useful now the toy has been written, or was just useful during development?
(rtcwake, for example, has this kind of thing in -v, but sleep doesn't.)
> +// Default timeout values in seconds.
> +#define WATCHDOG_SW_TIMER_S_DEFAULT (4)
> +#define WATCHDOG_HW_TIMER_S_DEFAULT (60)
>
is there a reason these are different from busybox's defaults, which seem
to be 30 and 60?
also, you can declare defaults in the USE_ line with =30 or =60, letting
you remove this and the corresponding code.
> +GLOBALS(
> + long hw_timer_s;
> + long sw_timer_s;
> + int fd;
> +)
> +
> +static int intercept_signals(void (*fn)(int)) {
> + int rc = 0;
> + struct sigaction sigact;
> + memset(&sigact, 0, sizeof(sigact));
> + sigact.sa_handler = fn;
> +
> + rc = sigaction(SIGTERM, &sigact, NULL);
> +#if defined(WATCHDOG_DEBUG)
> + if ( rc ) {
> + printf("failed to create new sigaction for SIGTERM: %d\n", rc);
> + }
> +#endif
> + return rc;
> +}
>
(this is already written. see call site below.)
> +void safe_shutdown(int __attribute__((unused))ignored) {
> + write(TT.fd, "V", 1);
> + close(TT.fd);
> + TT.fd = -1;
> + error_exit("safely exited watchdog.");
> +}
> +
> +void watchdog_main(void) {
> + int rc = 0;
> + long hw_timer_sec = 0;
> + char *watchdog_dev = NULL;
> +
> + if ( toys.optc > 0 ) {
> + watchdog_dev = toys.optargs[0];
> +#if defined(WATCHDOG_DEBUG)
> + printf("using dev @ '%s'\n", watchdog_dev);
> +#endif
> + } else {
> + error_exit("watchdog dev required");
> + }
>
you can replace all this with <1 at the start of the USE_TOY string. (see
sleep.c for an example.)
> + // Set default values for timeouts if no flags
> + if (!(toys.optflags & FLAG_t)) {
>
FLAG(t), but you can just put this in the USE_TOY as explained above.
> + TT.sw_timer_s = WATCHDOG_SW_TIMER_S_DEFAULT;
> +#if defined(WATCHDOG_DEBUG)
> + printf("using default sw_timer_s.\n");
> +#endif
> + }
> +
> + if (!(toys.optflags & FLAG_T)) {
> + TT.hw_timer_s = WATCHDOG_HW_TIMER_S_DEFAULT;
> +#if defined(WATCHDOG_DEBUG)
> + printf("using default hw_timer_s.\n");
> +#endif
> + }
> +
> +#if defined(WATCHDOG_DEBUG)
> + printf("hw timer: %ld seconds\n", TT.hw_timer_s);
> + printf("sw timer: %ld seconds\n", TT.sw_timer_s);
> +#endif
> +
> + if (!(toys.optflags & FLAG_F)) {
> +#if defined(WATCHDOG_DEBUG)
> + printf("daemonizing. so long, foreground!\n");
> +#endif
> + // Attempt to daemonize
> + rc = daemon(1, 1);
> + if ( rc ) {
> + perror_exit("failed to daemonize: %d", rc);
>
rc will always be -1 on failure, so all this can just be `if (!FLAG(F) &&
daemon(1, 1)) perror_exit("daemon failed");`.
> + }
> + }
> +
> + // Intercept terminating signals so we can call our shutdown routine
> first.
> + if ( intercept_signals(safe_shutdown) ) {
> + perror_exit("failed to intercept desired signals: %d", rc);
> + }
> +#if defined(WATCHDOG_DEBUG)
> + printf("Successfully intercepted signals.\n");
> +#endif
>
sigatexit()
> + TT.fd = open(watchdog_dev, O_WRONLY);
> + if ( TT.fd == -1 ) {
> + perror_exit("failed to open '%s'", watchdog_dev);
> + }
>
xopen()
> +#if defined(WDIOC_SETTIMEOUT)
>
as far as i can tell, this has existed since 2.6 kernels, so you don't need
the #if?
> + // SETTIMEOUT takes time value in seconds: s = ms / (1000 ms/s)
> + hw_timer_sec = TT.hw_timer_s;
> + xioctl(TT.fd, WDIOC_SETTIMEOUT, (void *)&hw_timer_sec);
>
(no need for this local if you let USE_TOY do the default for you. even
when you can't, you can just assign to TT.whatever.)
> +#endif // WDIOC_SETTIMEOUT
> +
> + // Now that we've got the watchdog device open, kick it periodically.
> + while (1) {
> + write(TT.fd, "\0", 1);
>
xwrite?
> + usleep(TT.sw_timer_s * 1000 * 1000);
>
isn't this just sleep(TT.sw_timer_s)?
> + }
> +}
> --
> 2.28.0.297.g1956fa8f8d-goog
>
> _______________________________________________
> Toybox mailing list
> Toybox at lists.landley.net
> http://lists.landley.net/listinfo.cgi/toybox-landley.net
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.landley.net/pipermail/toybox-landley.net/attachments/20200822/6287f017/attachment-0001.htm>
More information about the Toybox
mailing list