Skip to content

Commit

Permalink
Add watchdog_interval method and tests
Browse files Browse the repository at this point in the history
This adds a `watchdog_interval` method as well as tests for it and for `watchdog?` (which previously had no tests). I also took the liberty of revising the docs for `watchdog?` to (I hope) be a little clearer.

Fixes agis#6.
  • Loading branch information
Mr0grog committed Jun 26, 2024
1 parent 98eaf64 commit ef7c0be
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 14 deletions.
38 changes: 24 additions & 14 deletions lib/sd_notify.rb
Original file line number Diff line number Diff line change
Expand Up @@ -59,33 +59,43 @@ def self.fdstore(unset_env=false)
notify(FDSTORE, unset_env)
end

# If the $WATCHDOG_USEC environment variable is set,
# and the $WATCHDOG_PID variable is unset or set to the PID of the current
# process
# Determine whether the systemd's watchdog is enabled for your program. If
# enabled, systemd will restart (or take some configured action) on your
# service when it goes N seconds without receiving a `WATCHDOG` notification
# from your program.
#
# See #watchdog for sending notifications and #watchdog_interval for how
# frequently to send them.
#
# @return [Boolean] true if the service manager expects watchdog keep-alive
# notification messages to be sent from this process.
#
# @note Unlike sd_watchdog_enabled(3), this method does not mutate the
# environment.
def self.watchdog?
wd_usec = ENV["WATCHDOG_USEC"]
wd_pid = ENV["WATCHDOG_PID"]

return false if !wd_usec

begin
wd_usec = Integer(wd_usec)
rescue
return false
end
return false if watchdog_interval == 0.0

return false if wd_usec <= 0
wd_pid = ENV["WATCHDOG_PID"]
return true if !wd_pid || wd_pid == $$.to_s

false
end

# Get the expected number of seconds between watchdog notifications. If
# systemd's watchdog manager is enabled, it will take action if it does not
# receive notifications at least this often from your program.
#
# @return [Float] the frequency (in seconds) at which the service manager
# expects watchdog keep-alive notification messages from this process.
#
# @note Unlike sd_watchdog_enabled(3), this returns seconds, not microseconds.
def self.watchdog_interval
wd_usec = Integer(ENV["WATCHDOG_USEC"])
wd_usec.positive? ? wd_usec / 1e6 : 0.0
rescue StandardError
0.0
end

# Notify systemd with the provided state, via the notification socket, if
# any.
#
Expand Down
39 changes: 39 additions & 0 deletions test/sd_notify_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,50 @@ def test_sd_notify_ready_unset
assert_nil(ENV["NOTIFY_SOCKET"])
end

def test_sd_notify_watchdog_disabled
setup_socket

assert_equal(false, SdNotify.watchdog?)
end

def test_sd_notify_watchdog_enabled
ENV["WATCHDOG_USEC"] = "5_000_000"
ENV["WATCHDOG_PID"] = $$.to_s
setup_socket

assert_equal(true, SdNotify.watchdog?)
end

def test_sd_notify_watchdog_enabled_for_a_different_process
ENV["WATCHDOG_USEC"] = "5_000_000"
ENV["WATCHDOG_PID"] = ($$ + 1).to_s
setup_socket

assert_equal(false, SdNotify.watchdog?)
end

def test_sd_notify_watchdog_interval_disabled
setup_socket

assert_equal(0.0, SdNotify.watchdog_interval)
end

def test_sd_notify_watchdog_interval_enabled
ENV["WATCHDOG_USEC"] = "5_000_000"
ENV["WATCHDOG_PID"] = $$.to_s
setup_socket

assert_equal(5.0, SdNotify.watchdog_interval)
end

def teardown
@socket.close if @socket
File.unlink(@sockaddr) if @sockaddr
@socket = nil
@sockaddr = nil
ENV.delete("NOTIFY_SOCKET")
ENV.delete("WATCHDOG_USEC")
ENV.delete("WATCHDOG_PID")
end

private
Expand Down

0 comments on commit ef7c0be

Please sign in to comment.