diff --git a/NEWS.adoc b/NEWS.adoc index 9c3f60f73a..dcab7063f8 100644 --- a/NEWS.adoc +++ b/NEWS.adoc @@ -161,6 +161,13 @@ https://github.com/networkupstools/nut/milestone/12 of the existing mappings. Suggest how user can help improve the driver if too few data points were seen. [#3082, #3095] + - `upsd` data server updates: + * Sometimes "Data for UPS [X] is stale" and "UPS [X] data is no longer + stale" messages were logged in the same second, especially no busy + systems. Now we allow one more second on top of `MAXAGE` setting to + declare the device dead, just in case fractional/whole second rounding + comes into play and breaks things. [issue #661] + - `upsdrvctl` tool updates: * Make use of `setproctag()` and `getproctag()` to report parent/child process names. [#3084] diff --git a/server/sstate.c b/server/sstate.c index e49eaac2cf..9bae0cd397 100644 --- a/server/sstate.c +++ b/server/sstate.c @@ -478,12 +478,24 @@ int sstate_dead(upstype_t *ups, int arg_maxage) if ((elapsed > (arg_maxage / 3)) && (difftime(now, ups->last_ping) > (arg_maxage / 3))) sendping(ups); - if (elapsed > arg_maxage) { + if (elapsed > arg_maxage + 1) { upsdebugx(3, "%s: didn't hear from driver for UPS [%s] for %g seconds (max %d)", __func__, ups->name, elapsed, arg_maxage); return 1; /* dead */ } + if (elapsed > arg_maxage) { + /* Per https://github.com/networkupstools/nut/issues/661 we do + * often see "is stale" and "is alive" messages in the same + * second, especially on busy systems that can not dedicate + * every scheduled time slot to NUT daemons and data pipes. + * So data exchange frequency settings may almost race... + */ + upsdebugx(3, "%s: didn't hear from driver for UPS [%s] for %g seconds (max %d); will declare it dead next second (delaying just in case of whole-second rounding issues)", + __func__, ups->name, elapsed, arg_maxage); + return 0; /* probably dead */ + } + /* ignore DATAOK/DATASTALE unless the dump is done */ if ((ups->dumpdone) && (!ups->data_ok)) { upsdebugx(3, "%s: driver for UPS [%s] says data is stale", __func__, ups->name);