Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
e364d51
drivers/main.{c,h}, docs/man/ups.conf.txt, conf/ups.conf.sample, NEWS…
jimklimov Jul 23, 2026
cf8f210
drivers/main.c: set_exit_flag(): log debug traces based on new value,…
jimklimov Jul 24, 2026
6f3a67f
drivers/main.c: set_exit_flag(): use common EF_EXIT_FAILURE and EF_EX…
jimklimov Jul 24, 2026
ac4faf1
drivers/main.c, drivers/dstate.c: use set_exit_flag() and symbolic EF…
jimklimov Jul 24, 2026
0e4f2da
drivers/nhs_ser.c: use set_exit_flag() with symbolic EF_EXIT_* values…
jimklimov Jul 24, 2026
7655e5d
drivers/main.{c,h}: accept reconnect_trying(2) to consistently proces…
jimklimov Jul 24, 2026
b8e92ae
drivers/main.{c,h}: reconnect_trying(): refactor to use reconnect_sta…
jimklimov Jul 24, 2026
ec4c3f7
drivers/main.c: reconnect_trying(): fix syslog facility usage [#3541]
jimklimov Jul 24, 2026
ae6a7b2
drivers/*.c, NEWS.adoc: update drivers to use reconnect_trying() with…
jimklimov Jul 24, 2026
d092311
drivers/belkin.c, NEWS.adoc: retry failed connections [#3541]
jimklimov Jul 27, 2026
668abe1
NEWS.adoc: fix indentation style
jimklimov Jul 27, 2026
fa64ce7
drivers/bestfortress.c, NEWS.adoc: retry failed connections [#3541]
jimklimov Jul 27, 2026
e188720
drivers/belkin.c: handle valid/invalid upsfd like in bestfortress.c […
jimklimov Jul 27, 2026
7e9e875
drivers/genericups.c, NEWS.adoc: retry failed connections [#3541]
jimklimov Jul 27, 2026
2039b4b
drivers/genericups.c: handle valid/invalid upsfd like in bestfortress…
jimklimov Jul 27, 2026
9f0e089
drivers/powerpanel.c, NEWS.adoc: retry failed connections [#3541]
jimklimov Jul 27, 2026
ff81bbd
drivers/powervar_cx_usb.c, UPGRADING.adoc: remove old bespoke reconne…
jimklimov Jul 27, 2026
5011dc8
NEWS.adoc: list drivers impacted by `reconnect_max_tries` in one plac…
jimklimov Jul 27, 2026
5bd86ef
drivers/tripplite.c, NEWS.adoc: retry failed connections [#3541]
jimklimov Jul 27, 2026
25e936a
drivers/tripplite_usb.c, UPGRADING.adoc: remove old bespoke reconnect…
jimklimov Jul 27, 2026
0ee8833
drivers/main.c, conf/ups.conf.sample, docs/man/ups.conf.txt: Introduc…
jimklimov Jul 27, 2026
fd5bf65
drivers/main.{c,h}: introduce may_log_reconnect_trying() for drivers …
jimklimov Jul 27, 2026
ea8370b
drivers/apcsmart.c: revise tracking of serial port file descriptor [#…
jimklimov Jul 27, 2026
9e94a53
drivers/*.c: remove useless custom logging, hide useful messages behi…
jimklimov Jul 27, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions NEWS.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -58,10 +58,11 @@ https://github.com/networkupstools/nut/milestone/13
attempts on timeout errors, simplifying error recovery. [PR #3414]
* Increased default TCP response timeout to 2000 ms. [PR #3418]


- `dummy-ups` driver updates:
* Added `authconf` driver parameter for repeater mode to control
authentication configuration discovery. It accepts `default`, `none`,
or a specific authconf file path. [issue #3329]
* Added `authconf` driver parameter for repeater mode to control
authentication configuration discovery. It accepts `default`, `none`,
or a specific authconf file path. [issue #3329]

- `nhs_ser` driver updates:
* Modernized serial communication and added validated settings for baud
Expand Down Expand Up @@ -171,6 +172,22 @@ https://github.com/networkupstools/nut/milestone/13
chunks populated only partially with bytes we intended. These buffers are
now more diligently pre-zeroed as their siblings were in other code paths,
to avoid sending host stack garbage to a device. [#3529]
* Introduced a `reconnect_max_tries` setting for NUT drivers, so they can
be configured to exit after the specified number of reconnection attempts
(so that the OS service management facility can completely recycle the
driver program). Multiple drivers were updated to use the new facility
to consistently report `reconnect_trying()` states instead of what they
did before, including: `adelsystem_cbi`, `apc_modbus`, `apcsmart`,
`bcmxcp_usb`, `blazer_usb`, `generic_modbus`, `nhs_ser`, `nutdrv_qx`,
`powerman-pdu`, `powervar_cx_usb`, `richcomm_usb`, `riello_usb`,
`tripplite_usb`, `usbhid-ups` (it is possible that for now some of them
would log the situation twice, with old methods and the new, and that
some would abort the program if reconnection attempt fails). [PR #3541]
* `belkin`, `bestfortress`, `genericups`, `powerpanel`, `tripplite` drivers
introduced attempts to reconnect in case of failure, instead of just
exiting right away or remaining in data stale mode indefinitely, also
using `reconnect_trying()` for consistent reporting. They now track
serial port file descriptor validity a bit more diligently. [PR #3541]

- NUT client libraries:
* Complete support for actions documented in `docs/net-protocol.txt`
Expand Down
5 changes: 5 additions & 0 deletions UPGRADING.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,11 @@ The new `-A filename` option defaults to trying to use a `nutauth.conf` file
reading one ('none' as the legacy default). See the updated manual pages
for more details. [issues #3329, #3411]

- The `powervar_cx_usb`, `tripplite_usb` drivers used a built-in limit on
reconnection attempts after which they exited ('60' and '10' respectively).
This was revised to follow the new common setting `reconnect_max_tries`,
which defaults to trying indefinitely now. [#3541]

Changes from 2.8.4 to 2.8.5
---------------------------

Expand Down
19 changes: 19 additions & 0 deletions conf/ups.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,25 @@ maxretry = 3
#
# The default is 75 seconds.
#
# reconnect_max_tries: OPTIONAL. This can be set as a global variable above
# your first UPS definition and it can also be set in a
# UPS section. If a driver loses connection to the device,
# try reconnecting for the specified number of iterations and
# exit (so some OS service management facility or an alerted
# sysadmin can restart the driver program "from scratch").
# A zero value (unreasonable but possible) means to exit as
# soon as the device connection was lost.
# A negative value (default) means to try reconnecting
# indefinitely (e.g. data cable fell out, or the data path
# to a networked UPS was lost for a significant time).
#
# reconnect_report_freq: OPTIONAL. This can be set as a global variable
# above your first UPS definition and it can also be set in a
# UPS section, and used in conjunction with reconnect_max_tries
# to report progress (and on-going lack of success) every N
# attempts, to avoid flooding the logs. A non-positive value
# disables such updates completely (default).
#
# debug_min: OPTIONAL. Specify a minimum debug level for all driver daemons
# and for the upsdrvctl tool (when specified at global level),
# or for this driver daemon (when specified in a driver section),
Expand Down
31 changes: 31 additions & 0 deletions docs/man/ups.conf.txt
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,27 @@ its own in `upsd.conf`.
+
Environment variable `NUT_STATEPATH` set by caller can override this setting.

*reconnect_max_tries*::

Optional. If a driver loses connection to the device, try reconnecting for
the specified number of iterations and exit (so some OS service management
facility or an alerted sysadmin can restart the driver program "from scratch").
+
A zero value (unreasonable but possible) means to exit as soon as the device
connection was lost.
+
A negative value (default) means to try reconnecting indefinitely (e.g. data
cable fell out, or the data path to a networked UPS was lost for a significant
time).

*reconnect_report_freq*::

Optional. This can be used in conjunction with `reconnect_max_tries` to
report progress (and on-going lack of success) every `N` attempts, to avoid
flooding the logs.
+
A non-positive value disables such updates completely (default).

*maxstartdelay*::

Optional. Same as the UPS field of the same name, but this is the
Expand Down Expand Up @@ -340,6 +361,16 @@ They would not be actively killed by `upsdrvctl` after this timeout expires.
+
The default is 75 seconds.

*reconnect_max_tries*::
Optional. This can be set as a global variable above your first UPS
definition and it can also be set in a UPS section. See explanation
above, in the global section.

*reconnect_report_freq*::
Optional. This can be set as a global variable above your first UPS
definition and it can also be set in a UPS section. See explanation
above, in the global section.

*maxretry*::
Optional. This can be set as a global variable above your first UPS
definition and it can also be set in a UPS section. See explanation
Expand Down
6 changes: 3 additions & 3 deletions drivers/adelsystem_cbi.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
#endif

#define DRIVER_NAME "NUT ADELSYSTEM DC-UPS CB/CBI driver (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")"
#define DRIVER_VERSION "0.08"
#define DRIVER_VERSION "0.09"

/* variables */
static modbus_t *mbctx = NULL; /* modbus memory context */
Expand Down Expand Up @@ -1330,7 +1330,7 @@ void modbus_reconnect(void)
int rval;

upsdebugx(1, "modbus_reconnect, trying to reconnect to modbus server");
dstate_setinfo("driver.state", "reconnect.trying");
reconnect_trying(RECONNECT_TRYING);

/* clear current modbus context */
modbus_close(mbctx);
Expand Down Expand Up @@ -1391,5 +1391,5 @@ void modbus_reconnect(void)
/* #elif (defined NUT_MODBUS_TIMEOUT_ARG_timeval) // some un-castable type in fields */
#endif /* NUT_MODBUS_TIMEOUT_ARG_* */

dstate_setinfo("driver.state", "quiet");
reconnect_trying(RECONNECT_SUCCESS);
}
9 changes: 5 additions & 4 deletions drivers/apc_modbus.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
#endif

#define DRIVER_NAME "NUT APC Modbus driver " DRIVER_NAME_NUT_MODBUS_HAS_USB_WITH_STR " USB support (libmodbus link type: " NUT_MODBUS_LINKTYPE_STR ")"
#define DRIVER_VERSION "0.20"
#define DRIVER_VERSION "0.21"

#if defined NUT_MODBUS_HAS_USB

Expand Down Expand Up @@ -955,7 +955,7 @@ static void _apc_modbus_create_reopen_matcher(void)

static int _apc_modbus_reopen(void)
{
dstate_setinfo("driver.state", "reconnect.trying");
reconnect_trying(RECONNECT_TRYING);

if (modbus_connect(modbus_ctx) < 0) {
upslogx(LOG_ERR, "%s: Unable to connect Modbus: %s", __func__, modbus_strerror(errno));
Expand All @@ -975,9 +975,10 @@ static int _apc_modbus_reopen(void)

is_open = 1;

dstate_setinfo("driver.state", "reconnect.updateinfo");
reconnect_trying(RECONNECT_UPDATEINFO);
_apc_modbus_read_inventory();
dstate_setinfo("driver.state", "quiet");

reconnect_trying(RECONNECT_SUCCESS);

return 1;
}
Expand Down
31 changes: 23 additions & 8 deletions drivers/apcsmart.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
#include "apcsmart_tabs.h"

#define DRIVER_NAME "APC Smart protocol driver"
#define DRIVER_VERSION "3.39"
#define DRIVER_VERSION "3.40"

#ifdef WIN32
# ifndef ECANCELED
Expand Down Expand Up @@ -477,7 +477,7 @@ static ssize_t apc_read_i(char *buf, size_t buflen, int flags, const char *fn, u
fatalx (EXIT_FAILURE, "Error: apc_read_i called with buflen too large");
}

if (INVALID_FD(upsfd))
if (INVALID_FD_SER(upsfd))
return 0;

if (flags & SER_D0) {
Expand Down Expand Up @@ -605,7 +605,7 @@ static ssize_t apc_write_i(unsigned char code, const char *fn, unsigned int ln)
ssize_t ret;
errno = 0;

if (INVALID_FD(upsfd))
if (INVALID_FD_SER(upsfd))
return 0;

ret = ser_send_char(upsfd, code);
Expand Down Expand Up @@ -2301,6 +2301,13 @@ void upsdrv_initups(void)
}

upsfd = extrafd = ser_open(device_path);

if (INVALID_FD_SER(upsfd)) {
upslogx(LOG_WARNING, "%s: failed to open %s",
__func__, device_path);
/* \todo: Deal with the failure */
}

apc_ser_set();

/* fill length values */
Expand All @@ -2312,14 +2319,15 @@ void upsdrv_cleanup(void)
{
char temp[APC_LBUF];

if (INVALID_FD(upsfd))
if (INVALID_FD_SER(upsfd))
return;

apc_flush(0);
/* try to bring the UPS out of smart mode */
apc_write(APC_GODUMB);
apc_read(temp, sizeof(temp), SER_TO);
ser_close(upsfd, device_path);
upsfd = ERROR_FD_SER;
}

void upsdrv_initinfo(void)
Expand Down Expand Up @@ -2394,8 +2402,9 @@ void upsdrv_updateinfo(void)

/* become aggressive after a few tries */
if (!(last_worked % 60)) {
upslogx(LOG_WARNING, "Trying to reconnect to the UPS");
dstate_setinfo("driver.state", "reconnect.trying");
upsdebugx(1, "%s: Trying to reconnect to the UPS", __func__);

reconnect_trying(RECONNECT_TRYING);

upsdebugx(1, "%s: call upsdrv_cleanup", __func__);
/* dstate_setinfo("driver.state", "cleanup.upsdrv"); */
Expand All @@ -2412,12 +2421,18 @@ void upsdrv_updateinfo(void)
/* dstate_setinfo("driver.state", "init.info"); */
upsdrv_initinfo();

if (INVALID_FD_SER(upsfd)) {
upsdebugx(1, "%s: upsfd remains invalid", __func__);
dstate_datastale();
return;
}

reconnect_trying(RECONNECT_UPDATEINFO);
upsdebugx(1, "%s: call upsdrv_updateinfo", __func__);
dstate_setinfo("driver.state", "reconnect.updateinfo");
/* dstate_setinfo("driver.state", "init.updateinfo"); */
upsdrv_updateinfo();

dstate_setinfo("driver.state", "init.quiet");
reconnect_trying(RECONNECT_SUCCESS);
}

upsdebugx(1, "%s: nudging UPS with 'Y', iteration #%d ...",
Expand Down
11 changes: 8 additions & 3 deletions drivers/bcmxcp_usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include <unistd.h>

#define SUBDRIVER_NAME "USB communication subdriver"
#define SUBDRIVER_VERSION "0.28"
#define SUBDRIVER_VERSION "0.29"

/* communication driver description structure */
upsdrv_info_t comm_upsdrv_info = {
Expand Down Expand Up @@ -385,7 +385,7 @@ void upsdrv_cleanup(void)

void upsdrv_reconnect(void)
{
dstate_setinfo("driver.state", "reconnect.trying");
reconnect_trying(RECONNECT_TRYING);

upsdebugx(4, "==================================================");
upsdebugx(4, "= device has been disconnected, try to reconnect =");
Expand All @@ -396,7 +396,12 @@ void upsdrv_reconnect(void)

upsdrv_initups();

dstate_setinfo("driver.state", "quiet");
if (upsdev) {
reconnect_trying(RECONNECT_SUCCESS);
/* dstate_dataok() is called in bcmxcp.c::upsdrv_updateinfo() */
} else {
dstate_datastale();
}
}

/* USB functions */
Expand Down
Loading
Loading