Skip to content

Commit

Permalink
watchdog: implemented systemd-style watchdog support
Browse files Browse the repository at this point in the history
debian/tvheadend.service has a commented example on enabling it.
  • Loading branch information
Erkki Seppälä authored and perexg committed Jan 5, 2018
1 parent d61d200 commit 35d3bd8
Show file tree
Hide file tree
Showing 5 changed files with 146 additions and 0 deletions.
4 changes: 4 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,7 @@ SRCS-1 = \
src/string_list.c \
src/wizard.c \
src/memoryinfo.c

SRCS = $(SRCS-1)
I18N-C = $(SRCS-1)

Expand Down Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions debian/tvheadend.service
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 5 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
*/
Expand Down Expand Up @@ -1382,6 +1385,8 @@ main(int argc, char **argv)
#endif
tvh_gettext_done();
free((char *)tvheadend_webroot);

tvhftrace(LS_MAIN, watchdog_done);
return 0;
}

Expand Down
93 changes: 93 additions & 0 deletions src/watchdog.c
Original file line number Diff line number Diff line change
@@ -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);
}
}
37 changes: 37 additions & 0 deletions src/watchdog.h
Original file line number Diff line number Diff line change
@@ -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_ */

0 comments on commit 35d3bd8

Please sign in to comment.