Search code examples
rustsystemd

How do I make my Rust program communicate to systemd's WatchDog?


I've followed this tutorial: https://www.linode.com/docs/guides/start-service-at-boot/ and set everything up.

Since my problem is exactly this: https://unix.stackexchange.com/questions/298027/restart-systemd-service-when-output-is-no-longer-generated I've also followed the answers here.

The problem with the solution: after 7 hours of runtime, the program stuck. No output generated, systemd didn't restart it.

in my_service.service are both suggested mandatory entries everything else is correct

WatchdogSec=30
Restart=on-watchdog

Can I manually make my Rust program communicate with systemd? And if yes - how? I'd love to make it notify systemd at particular lines periodically.

The docs couldn't be more minimal: https://docs.rs/systemd/latest/systemd/daemon/constant.STATE_WATCHDOG.html I don't understand a single thing..

Another example crate libsystemd, there's 3 search results for WatchDog and this one is the most relevant I guess. https://docs.rs/libsystemd/latest/libsystemd/daemon/enum.NotifyState.html#variant.Watchdog

IDK how I am able to accomplish anything here. Do I just paste this line anywhere in the program that I want?

libsystemd::daemon::NotifyState

how will it know the PID?

In any case: each of those packages has multiple methods, and my program hangs after anywhere from 1-24 hours, trial and error might take weeks.

How can I make my Rust program communicate to the systemd from inside threads, or if impossible - just manually set it up and ensure the WatchDog receives the signal as I want it? What's the line of code for sending a single notification from Rust program to systemd?

As mentioned above the go-to logic is simple: if no print output, restart the program.


Solution

  • You have to send the message somehow. By looking for functions that use the NotifyState I found both systemd::daemon::notify and libsystemd::daemon::notify either of which will do.

    For example:

    use systemd::daemon::{notify, STATE_WATCHDOG};
    notify(false, [(STATE_WATCHDOG, "1")].iter()).unwrap();