Commit a06255be5ca65545221b099ee8607c8c1bbc800f

Authored by Stéphane Raimbault
1 parent ef81a69e

Sleep for delay of response timeout before reconnect (closes #77)

Thanks to Karl Palsson.
doc/modbus_set_error_recovery.txt
@@ -23,19 +23,20 @@ By default there is no error recovery ('MODBUS_ERROR_RECOVERY_NONE') so the @@ -23,19 +23,20 @@ By default there is no error recovery ('MODBUS_ERROR_RECOVERY_NONE') so the
23 application is responsible for controlling the error values returned by 23 application is responsible for controlling the error values returned by
24 libmodbus functions and for handling them if necessary. 24 libmodbus functions and for handling them if necessary.
25 25
26 -When 'MODBUS_ERROR_RECOVERY_LINK' is set, the library will attempt an immediate  
27 -reconnection (which may hang for several seconds if the network to the remote  
28 -target unit is down). This mode will try a infinite close/connect loop until  
29 -success on send call and will just try one time to retablish the connection on  
30 -select/read calls (if the connecton was down, the values to read are certainly  
31 -not available anymore after reconnection, except for slave/server). This mode  
32 -will also run flush requests after a delay based on the current response timeout  
33 -in some situations (eg. timeout of select call). 26 +When 'MODBUS_ERROR_RECOVERY_LINK' is set, the library will attempt an
  27 +reconnection after a delay defined by response timeout of the libmodbus context.
  28 +This mode will try a infinite close/connect loop until success on send call and
  29 +will just try one time to retablish the connection on select/read calls (if the
  30 +connecton was down, the values to read are certainly not available anymore after
  31 +reconnection, except for slave/server). This mode will also run flush requests
  32 +after a delay based on the current response timeout in some situations (eg.
  33 +timeout of select call). The reconnection attempt can hang for several seconds
  34 +if the network to the remote target unit is down.
34 35
35 When 'MODBUS_ERROR_RECOVERY_PROTOCOL' is set, a sleep and flush sequence will be 36 When 'MODBUS_ERROR_RECOVERY_PROTOCOL' is set, a sleep and flush sequence will be
36 used to cleanup the ongoing communication, this can occurs when the message 37 used to cleanup the ongoing communication, this can occurs when the message
37 length is invalid, the TID is wrong or the received function code is not the 38 length is invalid, the TID is wrong or the received function code is not the
38 -expected one. 39 +expected one. The response timeout delay will be used to sleep.
39 40
40 The modes are mask values and so they are complementary. 41 The modes are mask values and so they are complementary.
41 42
src/modbus.c
@@ -102,7 +102,7 @@ void _error_print(modbus_t *ctx, const char *context) @@ -102,7 +102,7 @@ void _error_print(modbus_t *ctx, const char *context)
102 } 102 }
103 } 103 }
104 104
105 -static int _sleep_and_flush(modbus_t *ctx) 105 +static void _sleep_response_timeout(modbus_t *ctx)
106 { 106 {
107 #ifdef _WIN32 107 #ifdef _WIN32
108 /* usleep doesn't exist on Windows */ 108 /* usleep doesn't exist on Windows */
@@ -117,7 +117,6 @@ static int _sleep_and_flush(modbus_t *ctx) @@ -117,7 +117,6 @@ static int _sleep_and_flush(modbus_t *ctx)
117 while (nanosleep(&request, &remaining) == -1 && errno == EINTR) 117 while (nanosleep(&request, &remaining) == -1 && errno == EINTR)
118 request = remaining; 118 request = remaining;
119 #endif 119 #endif
120 - return modbus_flush(ctx);  
121 } 120 }
122 121
123 int modbus_flush(modbus_t *ctx) 122 int modbus_flush(modbus_t *ctx)
@@ -192,9 +191,11 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) @@ -192,9 +191,11 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
192 191
193 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) { 192 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
194 modbus_close(ctx); 193 modbus_close(ctx);
  194 + _sleep_response_timeout(ctx);
195 modbus_connect(ctx); 195 modbus_connect(ctx);
196 } else { 196 } else {
197 - _sleep_and_flush(ctx); 197 + _sleep_response_timeout(ctx);
  198 + modbus_flush(ctx);
198 } 199 }
199 errno = saved_errno; 200 errno = saved_errno;
200 } 201 }
@@ -379,7 +380,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -379,7 +380,8 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
379 int saved_errno = errno; 380 int saved_errno = errno;
380 381
381 if (errno == ETIMEDOUT) { 382 if (errno == ETIMEDOUT) {
382 - _sleep_and_flush(ctx); 383 + _sleep_response_timeout(ctx);
  384 + modbus_flush(ctx);
383 } else if (errno == EBADF) { 385 } else if (errno == EBADF) {
384 modbus_close(ctx); 386 modbus_close(ctx);
385 modbus_connect(ctx); 387 modbus_connect(ctx);
@@ -494,7 +496,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, @@ -494,7 +496,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
494 rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length); 496 rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length);
495 if (rc == -1) { 497 if (rc == -1) {
496 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { 498 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
497 - _sleep_and_flush(ctx); 499 + _sleep_response_timeout(ctx);
  500 + modbus_flush(ctx);
498 } 501 }
499 return -1; 502 return -1;
500 } 503 }
@@ -538,7 +541,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, @@ -538,7 +541,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
538 function, req[offset]); 541 function, req[offset]);
539 } 542 }
540 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { 543 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
541 - _sleep_and_flush(ctx); 544 + _sleep_response_timeout(ctx);
  545 + modbus_flush(ctx);
542 } 546 }
543 errno = EMBBADDATA; 547 errno = EMBBADDATA;
544 return -1; 548 return -1;
@@ -587,7 +591,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, @@ -587,7 +591,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
587 } 591 }
588 592
589 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { 593 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
590 - _sleep_and_flush(ctx); 594 + _sleep_response_timeout(ctx);
  595 + modbus_flush(ctx);
591 } 596 }
592 597
593 errno = EMBBADDATA; 598 errno = EMBBADDATA;
@@ -600,7 +605,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req, @@ -600,7 +605,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
600 rsp_length, rsp_length_computed); 605 rsp_length, rsp_length_computed);
601 } 606 }
602 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) { 607 if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_PROTOCOL) {
603 - _sleep_and_flush(ctx); 608 + _sleep_response_timeout(ctx);
  609 + modbus_flush(ctx);
604 } 610 }
605 errno = EMBBADDATA; 611 errno = EMBBADDATA;
606 rc = -1; 612 rc = -1;