pnv
pnv

Reputation: 3135

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

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.

Upvotes: 8

Views: 16741

Answers (3)

Saturn
Saturn

Reputation: 976

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.

Upvotes: 9

fabatera
fabatera

Reputation: 379

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;
}

Upvotes: 13

rameshrgtvl
rameshrgtvl

Reputation: 343

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.

Upvotes: 8

Related Questions