]> git.ipfire.org Git - thirdparty/knot-resolver.git/commitdiff
modules/sd_watchdog: deinit correctness
authorVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 24 Jun 2019 12:44:26 +0000 (14:44 +0200)
committerVladimír Čunát <vladimir.cunat@nic.cz>
Mon, 24 Jun 2019 14:04:35 +0000 (16:04 +0200)
and slightly better error reporting.

lib/utils.c
lib/utils.h
modules/sd_watchdog/sd_watchdog.c

index 780805ea831b0d0eb21f8bcbf79c018d0727c06c..0200b144c74b0228a029777ca52a76488df234a0 100644 (file)
@@ -963,6 +963,11 @@ uint64_t kr_now()
        return uv_now(uv_default_loop());
 }
 
+void kr_uv_free_cb(uv_handle_t* handle)
+{
+       free(handle->data);
+}
+
 const char *kr_strptime_diff(const char *format, const char *time1_str,
                             const char *time0_str, double *diff) {
        assert(format != NULL);
index 5b376c6e81c08779736fe8a4eee6df8a6639e9c0..7b8079c75429c46484b49ae528563c6e4fa8819a 100644 (file)
@@ -30,6 +30,7 @@
 #include <libknot/packet/pkt.h>
 #include <libknot/rrset.h>
 #include <libknot/rrtype/rrsig.h>
+#include <uv.h>
 
 #include "kresconfig.h"
 #include "lib/generic/array.h"
@@ -478,6 +479,9 @@ static inline uint16_t kr_rrset_type_maysig(const knot_rrset_t *rr)
 KR_EXPORT
 uint64_t kr_now();
 
+/** Call free(handle->data); it's useful e.g. as a callback in uv_close(). */
+KR_EXPORT void kr_uv_free_cb(uv_handle_t* handle);
+
 /** Convert name from lookup format to wire.  See knot_dname_lf
  *
  * \note len bytes are read and len+1 are written with *normal* LF,
index bdf6f51f44ea03c93766ebbb3805340855d17a0c..76f0a96dfb02946730c113fc1e5fe6c7310840dd 100644 (file)
@@ -17,6 +17,7 @@ struct watchdog_config {
 static void keepalive_ping(uv_timer_t *timer)
 {
        // NOTE: in the future, some sanity checks could be used here
+       // It is generally recommended to ignore the return value of this call.
        sd_notify(0, "WATCHDOG=1");
 }
 
@@ -51,7 +52,9 @@ int sd_watchdog_init(struct kr_module *module)
        uv_timer_init(loop, &conf->timer);
        ret = uv_timer_start(&conf->timer, keepalive_ping, delay_ms, delay_ms);
        if (ret != 0) {
-               kr_log_error("[sd_watchdog] error: failed to start uv_timer!\n");
+               kr_log_error("[sd_watchdog] error: failed to start uv_timer: %s\n",
+                               uv_strerror(ret));
+               conf->timer.loop = NULL;
                return kr_error(ret);
        }
 
@@ -64,8 +67,19 @@ int sd_watchdog_init(struct kr_module *module)
 KR_EXPORT
 int sd_watchdog_deinit(struct kr_module *module)
 {
-       struct stat_data *conf = module->data;
-       if (conf) {
+       struct watchdog_config *conf = module->data;
+       if (conf && conf->timer.loop == uv_default_loop()) { /* normal state */
+               int ret = uv_timer_stop(&conf->timer);
+               if (ret != 0) {
+                       kr_log_error("[sd_watchdog] error: failed to stop uv_timer: %s\n",
+                                       uv_strerror(ret));
+               }
+               /* We have a problem: UV timer can't be closed immediately,
+                * but as soon as we return from _deinit(), we get dlclose()
+                * so no function from this module may be usable anymore. */
+               conf->timer.data = conf;
+               uv_close((uv_handle_t *)&conf->timer, kr_uv_free_cb);
+       } else { /* watchdog might be just disabled */
                free(conf);
        }
        return kr_ok();