@@ -101,7 +101,8 @@ vartab_t *vartab_h = NULL;
101101 */
102102time_t poll_interval = 2 ;
103103static char * chroot_path = NULL , * user = NULL , * group = NULL ;
104- static int user_from_cmdline = 0 , group_from_cmdline = 0 ;
104+ static int user_from_cmdline = 0 , group_from_cmdline = 0 ,
105+ reconnect_max_tries = -1 , reconnect_count = 0 ;
105106
106107/* signal handling */
107108int exit_flag = 0 ;
@@ -1397,6 +1398,18 @@ static int main_arg(char *var, char *val)
13971398 return 1 ; /* handled */
13981399 }
13991400
1401+ /* Allow per-driver overrides of the global setting
1402+ * and allow to reload this, why not. */
1403+ if (!strcmp (var , "reconnect_max_tries" )) {
1404+ int intval = -1 ;
1405+ if ( str_to_int (val , & intval , 10 ) ) {
1406+ reconnect_max_tries = intval ;
1407+ reconnect_count = 0 ;
1408+ } else {
1409+ upslogx (LOG_INFO , "WARNING : Invalid reconnect_max_tries value found in ups.conf global settings" );
1410+ }
1411+ }
1412+
14001413 /* only for upsdrvctl - ignored here */
14011414 if (!strcmp (var , "sdorder" ))
14021415 return 1 ; /* handled */
@@ -1571,6 +1584,18 @@ static void do_global_args(const char *var, const char *val)
15711584 return ;
15721585 }
15731586
1587+ if (!strcmp (var , "reconnect_max_tries" )) {
1588+ int intval = -1 ;
1589+ if ( str_to_int (val , & intval , 10 ) ) {
1590+ reconnect_max_tries = intval ;
1591+ reconnect_count = 0 ;
1592+ } else {
1593+ upslogx (LOG_INFO , "WARNING : Invalid reconnect_max_tries value found in ups.conf global settings" );
1594+ }
1595+
1596+ return ;
1597+ }
1598+
15741599 /* Allow to specify its minimal debugging level for all drivers -
15751600 * admins can set more with command-line args, but can't set
15761601 * less without changing config. Should help debug of services.
@@ -2169,6 +2194,77 @@ void setup_signals(void)
21692194}
21702195#endif /* !WIN32*/
21712196
2197+ /* Called by a driver to enter/continue a reconnection loop (trying=1,
2198+ * with certain configuration can activate exit_flag) or to end it (0).
2199+ * Sets the driver.state to "reconnect.trying" or "quiet" respectively.
2200+ * Returns how many attempts remain before driver exits (-1 if it won't).
2201+ */
2202+ int reconnect_trying (int trying )
2203+ {
2204+ if (!trying ) {
2205+ if (reconnect_count > 0 )
2206+ upslogx (LOG_INFO , "Driver reconnected "
2207+ "to the device [%s] after %d attempts" ,
2208+ upsname , reconnect_count );
2209+ reconnect_count = 0 ;
2210+ dstate_setinfo ("driver.state" , "quiet" );
2211+ return -1 ;
2212+ }
2213+
2214+ if (reconnect_max_tries == 0 ) {
2215+ upslogx (LOG_WARNING , "Driver lost connection "
2216+ "to the device [%s] and will exit immediately" ,
2217+ upsname );
2218+ exit_flag = 1 ;
2219+ return 0 ;
2220+ }
2221+
2222+ dstate_setinfo ("driver.state" , "reconnect.trying" );
2223+
2224+ if (reconnect_count == 0 ) {
2225+ if (reconnect_max_tries < 0 ) {
2226+ upslogx (LOG_INFO , "Driver reconnecting "
2227+ "to the device [%s], will try "
2228+ "indefinitely" ,
2229+ upsname );
2230+ } else {
2231+ upslogx (LOG_INFO , "Driver reconnecting "
2232+ "to the device [%s], will try for "
2233+ "max %d attempts, then will exit" ,
2234+ upsname , reconnect_max_tries );
2235+ }
2236+ }
2237+
2238+ if (reconnect_count < INT_MAX ) {
2239+ reconnect_count ++ ;
2240+ } else {
2241+ upsdebugx (1 , "%s: reconnect counter overflowed" , __func__ );
2242+ if (reconnect_max_tries > 0 ) {
2243+ upslogx (LOG_WARNING , "Driver lost connection "
2244+ "to the device [%s] and reconnect "
2245+ "counter overflowed, will exit immediately" ,
2246+ upsname );
2247+ exit_flag = 1 ;
2248+ return 0 ;
2249+ }
2250+ }
2251+
2252+ if (reconnect_max_tries > 0 ) {
2253+ if (reconnect_max_tries < reconnect_count ) {
2254+ upslogx (LOG_WARNING , "Driver lost connection "
2255+ "to the device [%s] and tried to "
2256+ "reconnect for %d times, "
2257+ "now will exit as configured" ,
2258+ upsname , reconnect_count );
2259+ exit_flag = 1 ;
2260+ return 0 ;
2261+ }
2262+ return reconnect_max_tries - reconnect_count + 1 ;
2263+ }
2264+
2265+ return -1 ;
2266+ }
2267+
21722268/* This source file is used in some unit tests to mock realistic driver
21732269 * behavior - using a production driver skeleton, but their own main().
21742270 * It is called from main-stub.c in shared-mode builds.
@@ -3301,6 +3397,11 @@ int main(int argc, char **argv)
33013397 gettimeofday (& timeout , NULL );
33023398 timeout .tv_sec += poll_interval ;
33033399
3400+ if (reconnect_count > 0 ) {
3401+ dstate_setinfo ("driver.reconnect_count" , "%d" , reconnect_count );
3402+ dstate_setinfo ("driver.reconnect_max_tries" , "%d" , reconnect_max_tries );
3403+ }
3404+
33043405 /* Drivers can now choose to track changes of current battery
33053406 * charge vs. its previous value to e.g. report "CHRG" status.
33063407 * TODO: Eventually provide a common `runtimecal` fallback to all?
0 commit comments