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 23 application is responsible for controlling the error values returned by
24 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 36 When 'MODBUS_ERROR_RECOVERY_PROTOCOL' is set, a sleep and flush sequence will be
36 37 used to cleanup the ongoing communication, this can occurs when the message
37 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 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 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 107 #ifdef _WIN32
108 108 /* usleep doesn't exist on Windows */
... ... @@ -117,7 +117,6 @@ static int _sleep_and_flush(modbus_t *ctx)
117 117 while (nanosleep(&request, &remaining) == -1 && errno == EINTR)
118 118 request = remaining;
119 119 #endif
120   - return modbus_flush(ctx);
121 120 }
122 121  
123 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 191  
193 192 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
194 193 modbus_close(ctx);
  194 + _sleep_response_timeout(ctx);
195 195 modbus_connect(ctx);
196 196 } else {
197   - _sleep_and_flush(ctx);
  197 + _sleep_response_timeout(ctx);
  198 + modbus_flush(ctx);
198 199 }
199 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 380 int saved_errno = errno;
380 381  
381 382 if (errno == ETIMEDOUT) {
382   - _sleep_and_flush(ctx);
  383 + _sleep_response_timeout(ctx);
  384 + modbus_flush(ctx);
383 385 } else if (errno == EBADF) {
384 386 modbus_close(ctx);
385 387 modbus_connect(ctx);
... ... @@ -494,7 +496,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
494 496 rc = ctx->backend->pre_check_confirmation(ctx, req, rsp, rsp_length);
495 497 if (rc == -1) {
496 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 502 return -1;
500 503 }
... ... @@ -538,7 +541,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
538 541 function, req[offset]);
539 542 }
540 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 547 errno = EMBBADDATA;
544 548 return -1;
... ... @@ -587,7 +591,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
587 591 }
588 592  
589 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 598 errno = EMBBADDATA;
... ... @@ -600,7 +605,8 @@ static int check_confirmation(modbus_t *ctx, uint8_t *req,
600 605 rsp_length, rsp_length_computed);
601 606 }
602 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 611 errno = EMBBADDATA;
606 612 rc = -1;
... ...