]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
watchdog: implemented systemd-style watchdog support
authorErkki Seppälä <flux@modeemi.fi>
Wed, 29 Nov 2017 20:21:38 +0000 (22:21 +0200)
committerJaroslav Kysela <perex@perex.cz>
Fri, 5 Jan 2018 10:34:37 +0000 (11:34 +0100)
debian/tvheadend.service has a commented example on enabling it.

Makefile
debian/tvheadend.service
src/main.c
src/watchdog.c [new file with mode: 0644]
src/watchdog.h [new file with mode: 0644]

index 9eb1db8b3eaab28e1b8d32612652fabfc1b40b7b..5e5bf118576977b62c958bbcb2805b3e1d290553 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -261,6 +261,7 @@ SRCS-1 = \
        src/string_list.c \
        src/wizard.c \
        src/memoryinfo.c
+
 SRCS = $(SRCS-1)
 I18N-C = $(SRCS-1)
 
@@ -622,6 +623,9 @@ SRCS-${CONFIG_SSL} += src/descrambler/algo/libdesdec.c
 # DBUS
 SRCS-${CONFIG_DBUS_1}  += src/dbus.c
 
+# Watchdog
+SRCS-${CONFIG_LIBSYSTEMD_DAEMON} += src/watchdog.c
+
 # File bundles
 SRCS-${CONFIG_BUNDLE}     += bundle.c
 BUNDLES-yes               += src/webui/static
index 63e424354ebf77d9d34c29259531fe5eb4297bba..a9374a3d6e97d9033e293d8ea75be30929fd747d 100644 (file)
@@ -10,5 +10,12 @@ Type=forking
 Restart=on-failure
 RestartSec=54s
 
+# To enable watchdog functionality, uncomment these, remove Type=forking
+# and compile with --enable-libsystemd_daemon
+#Type=notify
+#WatchdogSec=1m
+#TimeoutStartSec=5m
+#TimeoutStopSec=20
+
 [Install]
 WantedBy=multi-user.target
index e617ca88c9de6f18cc361463c4f13fcea8f3baa6..84b8ea1b24010217c50ff331dc0717b983aa2675 100644 (file)
@@ -75,6 +75,7 @@
 #include "packet.h"
 #include "streaming.h"
 #include "memoryinfo.h"
+#include "watchdog.h"
 #if CONFIG_LINUXDVB_CA
 #include "input/mpegts/en50221/en50221.h"
 #endif
@@ -1256,6 +1257,8 @@ main(int argc, char **argv)
 
   pthread_mutex_unlock(&global_lock);
 
+  tvhftrace(LS_MAIN, watchdog_init);
+
   /**
    * Wait for SIGTERM / SIGINT, but only in this thread
    */
@@ -1382,6 +1385,8 @@ main(int argc, char **argv)
 #endif
   tvh_gettext_done();
   free((char *)tvheadend_webroot);
+
+  tvhftrace(LS_MAIN, watchdog_done);
   return 0;
 }
 
diff --git a/src/watchdog.c b/src/watchdog.c
new file mode 100644 (file)
index 0000000..f51ad46
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ *  tvheadend, systemd watchdog support
+ *  Copyright (C) 2017-2018 Erkki Seppälä
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "watchdog.h"
+#include "tvheadend.h"
+
+#include <systemd/sd-daemon.h>
+
+static pthread_t watchdog_tid;
+static pthread_mutex_t watchdog_exiting_mutex;
+static tvh_cond_t watchdog_exiting_cond;
+static int watchdog_exiting;    /* 1 if exit has been requested */
+static int watchdog_enabled;    /* 1 if watchdog was enabled for the systemd unit */
+static uint64_t watchdog_interval_usec; /* value from .service divided by 2 */
+
+static void* watchdog_thread(void* aux)
+{
+  int exiting = 0;
+  (void) aux; /* ignore */
+  sd_notify(0, "READY=1");
+  pthread_mutex_lock(&watchdog_exiting_mutex);
+  while (!exiting) {
+    if (!watchdog_exiting) {
+      /*
+       * Just keep ticking regardless the return value; its intention is
+       * to pace the loop down, and let us exit fast when the time comes
+       */
+      tvh_cond_timedwait(&watchdog_exiting_cond, &watchdog_exiting_mutex, mclk() + watchdog_interval_usec);
+      if (!watchdog_exiting) {
+        pthread_mutex_lock(&global_lock);
+        pthread_mutex_unlock(&global_lock);
+        sd_notify(0, "WATCHDOG=1");
+      }
+    }
+    exiting = watchdog_exiting;
+  }
+  pthread_mutex_unlock(&watchdog_exiting_mutex);
+
+  return NULL;
+}
+
+void watchdog_init(void)
+{
+  /*
+   * I doubt MONOCLOCK_RESOLUTION is going to change, but if it does,
+   * let's break this
+   */
+#if MONOCLOCK_RESOLUTION != 1000000LL
+#error "Watchdog assumes MONOCLOCK_RESOLUTION == 1000000LL"
+#endif
+
+  watchdog_enabled = sd_watchdog_enabled(0, &watchdog_interval_usec) > 0;
+  if (watchdog_enabled) {
+     /* suggested by sd_watchdog_enabled documentation: */
+    watchdog_interval_usec /= 2;
+
+    watchdog_exiting = 0;
+    tvh_cond_init(&watchdog_exiting_cond);
+    pthread_mutex_init(&watchdog_exiting_mutex, NULL);
+
+    tvhthread_create(&watchdog_tid, NULL, watchdog_thread, NULL, "systemd watchdog");
+  }
+}
+
+void watchdog_done(void)
+{
+  if (watchdog_enabled) {
+    pthread_mutex_lock(&watchdog_exiting_mutex);
+    watchdog_exiting = 1;
+    tvh_cond_signal(&watchdog_exiting_cond, 0);
+    pthread_mutex_unlock(&watchdog_exiting_mutex);
+
+    pthread_join(watchdog_tid, NULL);
+
+    tvh_cond_destroy(&watchdog_exiting_cond);
+    pthread_mutex_destroy(&watchdog_exiting_mutex);
+  }
+}
diff --git a/src/watchdog.h b/src/watchdog.h
new file mode 100644 (file)
index 0000000..68af828
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *  tvheadend, systemd watchdog support
+ *  Copyright (C) 2017-2018 Erkki Seppälä
+ *
+ *  This program is free software: you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation, either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef WATCHDOG_H_
+#define WATCHDOG_H_
+
+#include "config.h"
+
+#if ENABLE_LIBSYSTEMD_DAEMON
+
+void watchdog_init(void);
+void watchdog_done(void);
+
+#else /* #if ENABLE_LIBSYSTEMD_DAEMON */
+
+static inline void watchdog_init(void) { }
+static inline void watchdog_done(void) { }
+
+#endif /* #if else ENABLE_LIBSYSTEMD_DAEMON */
+
+
+#endif /* WATCHDOG_H_ */