Calling a sd_notify(0, "WATCHDOG=1") in a service
Asked Answered
W

3

8

I have a sys d service. I want to implement a watch dog for that. It's something like,

[Unit]
Description=Watchdog example service

[Service]
Type=notify
Environment=NOTIFY_SOCKET=/run/%p.sock
ExecStartPre=-/usr/bin/docker kill %p
ExecStartPre=-/usr/bin/docker rm %p
ExecStart=/usr/libexec/sdnotify-proxy /run/%p.sock /usr/bin/docker run \
    --env=NOTIFY_SOCKET=/run/%p.sock \
    --name %p pranav93/test_watchdogged python hello.py
ExecStop=/usr/bin/docker stop %p

Restart=on-success
WatchdogSec=30s
RestartSec=30s


[Install]
WantedBy=multi-user.target

According to docs I've to call sd_notify("watchdog=1") every half of the interval specified (In this case it's 15s). But I've no idea how to call that function in a service. Help would be highly appreciated.

Worsley answered 5/10, 2015 at 11:33 Comment(0)
M
9

sd_notify(0,"WATCHDOG=1") is a API for notifying systemd that your process is working fine.

As Type=notify has been used, sd_notify(0,"WATCHDOG=1") should be called in your application not in service and this must be called at regular interval(before 30 sec as WatchdogSec=30s is mentioned in your service file) so that systemd get notified else,

systemd will think of this as failed service and hence systemd will kill your service and restart it.

Mistranslate answered 8/10, 2015 at 3:48 Comment(0)
S
13

I had to install systemd lib:

sudo apt-get install libsystemd-dev

And compile the program passing it to linker:

gcc testWatchDogProcess.c -o testWatchDogProcess -lsystemd

I´ve made some changes in @rameshrgtvl code to make it run directly without any warning or errors.

#include <systemd/sd-daemon.h>
#include <fcntl.h>
#include <time.h>
/* This should be sent once you are done with your initialization */
/* Until you call this systemd will keep your service as activating status */
/* Once you called, systemd will change the status of ur service to active */

#define true  1

int main ()
{
        sd_notify (0, "READY=1");

        /* Way to get the WatchdogSec value from service file */
        char * env;
        int interval=0;
        int isRun = true;
        env = getenv("WATCHDOG_USEC");
        if (env)
        {
                interval = atoi(env)/(2*1000000);
        }
        /* Ping systsemd once you are done with Init */
        sd_notify (0, "WATCHDOG=1");

        /* Now go for periodic notification */
        while(isRun == true)
        {
                sleep(interval);
            /* Way to ping systemd */
                sd_notify (0, "WATCHDOG=1");
        }
        return 0;
}
Sepaloid answered 26/2, 2016 at 13:47 Comment(1)
Now I see that was you sharing the code, @rameshrgtvl . Thanks!Sepaloid
M
9

sd_notify(0,"WATCHDOG=1") is a API for notifying systemd that your process is working fine.

As Type=notify has been used, sd_notify(0,"WATCHDOG=1") should be called in your application not in service and this must be called at regular interval(before 30 sec as WatchdogSec=30s is mentioned in your service file) so that systemd get notified else,

systemd will think of this as failed service and hence systemd will kill your service and restart it.

Mistranslate answered 8/10, 2015 at 3:48 Comment(0)
M
8

Sample Service File

[Unit]
Description=Test watchdog Demo process
DefaultDependencies=false
Requires=basic.target

[Service]
Type=notify
WatchdogSec=10s
ExecStart=/usr/bin/TestWatchDogProcess
StartLimitInterval=5min
StartLimitBurst=5
StartLimitAction=reboot
Restart=always

Sample Code For testWatchDogProcess.c:

#include "systemd/sd-daemon.h"
#include <fcntl.h>
#include <time.h>

/* This should be sent once you are done with your initialization */
/* Until you call this systemd will keep your service as activating status */
/* Once you called, systemd will change the status of ur service to active */

sd_notify (0, "READY=1");

/* Way to get the WatchdogSec value from service file */
env = getenv("WATCHDOG_USEC");
if(env != NULL)
int interval = atoi(env)/(2*1000000);

/* Ping systsemd once you are done with Init */
sd_notify (0, "WATCHDOG=1");

/* Now go for periodic notification */
while(isRun == true)
{
    sleep(interval);
    /* Way to ping systemd */
    sd_notify (0, "WATCHDOG=1");
}

    return 0;

}

Note: Based on your systemd version please take care to include proper header and library during compilation.

Metronome answered 11/12, 2015 at 5:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.