Commit db1cbc593501590eef16bbf9e0746290ac9116b9

Authored by Mohamed Amine Mzoughi
Committed by Stéphane Raimbault
1 parent 06dc37ff

Fixed MODBUS_ERROR_RECOVERY_LINK not working on Windows.

Showing 1 changed file with 44 additions and 2 deletions
src/modbus.c
@@ -182,7 +182,21 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) @@ -182,7 +182,21 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
182 rc = ctx->backend->send(ctx, msg, msg_length); 182 rc = ctx->backend->send(ctx, msg, msg_length);
183 if (rc == -1) { 183 if (rc == -1) {
184 _error_print(ctx, NULL); 184 _error_print(ctx, NULL);
185 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { 185 + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK &&
  186 + ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) {
  187 +#ifdef _WIN32
  188 + const int wsa_err = WSAGetLastError();
  189 + if (wsa_err == WSAENETRESET || wsa_err == WSAENOTCONN || wsa_err == WSAENOTSOCK ||
  190 + wsa_err == WSAESHUTDOWN || wsa_err == WSAEHOSTUNREACH || wsa_err == WSAECONNABORTED ||
  191 + wsa_err == WSAECONNRESET || wsa_err == WSAETIMEDOUT) {
  192 + modbus_close(ctx);
  193 + _sleep_response_timeout(ctx);
  194 + modbus_connect(ctx);
  195 + } else {
  196 + _sleep_response_timeout(ctx);
  197 + modbus_flush(ctx);
  198 + }
  199 +#else
186 int saved_errno = errno; 200 int saved_errno = errno;
187 201
188 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) { 202 if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
@@ -194,6 +208,7 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) @@ -194,6 +208,7 @@ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length)
194 modbus_flush(ctx); 208 modbus_flush(ctx);
195 } 209 }
196 errno = saved_errno; 210 errno = saved_errno;
  211 +#endif
197 } 212 }
198 } 213 }
199 } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && 214 } while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
@@ -345,6 +360,9 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -345,6 +360,9 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
345 int length_to_read; 360 int length_to_read;
346 int msg_length = 0; 361 int msg_length = 0;
347 _step_t step; 362 _step_t step;
  363 +#ifdef _WIN32
  364 + int wsa_err;
  365 +#endif
348 366
349 if (ctx->debug) { 367 if (ctx->debug) {
350 if (msg_type == MSG_INDICATION) { 368 if (msg_type == MSG_INDICATION) {
@@ -386,7 +404,17 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -386,7 +404,17 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
386 rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read); 404 rc = ctx->backend->select(ctx, &rset, p_tv, length_to_read);
387 if (rc == -1) { 405 if (rc == -1) {
388 _error_print(ctx, "select"); 406 _error_print(ctx, "select");
389 - if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) { 407 + if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK &&
  408 + ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) {
  409 +#ifdef _WIN32
  410 + wsa_err = WSAGetLastError();
  411 +
  412 + // no equivalent to ETIMEDOUT when select fails on Windows
  413 + if (wsa_err == WSAENETDOWN || wsa_err == WSAENOTSOCK) {
  414 + modbus_close(ctx);
  415 + modbus_connect(ctx);
  416 + }
  417 +#else
390 int saved_errno = errno; 418 int saved_errno = errno;
391 419
392 if (errno == ETIMEDOUT) { 420 if (errno == ETIMEDOUT) {
@@ -397,6 +425,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -397,6 +425,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
397 modbus_connect(ctx); 425 modbus_connect(ctx);
398 } 426 }
399 errno = saved_errno; 427 errno = saved_errno;
  428 +#endif
400 } 429 }
401 return -1; 430 return -1;
402 } 431 }
@@ -409,7 +438,19 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -409,7 +438,19 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
409 438
410 if (rc == -1) { 439 if (rc == -1) {
411 _error_print(ctx, "read"); 440 _error_print(ctx, "read");
  441 +#ifdef _WIN32
  442 + wsa_err = WSAGetLastError();
412 if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) && 443 if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
  444 + (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
  445 + (wsa_err == WSAENOTCONN || wsa_err == WSAENETRESET || wsa_err == WSAENOTSOCK ||
  446 + wsa_err == WSAESHUTDOWN || wsa_err == WSAECONNABORTED || wsa_err == WSAETIMEDOUT ||
  447 + wsa_err == WSAECONNRESET)) {
  448 + modbus_close(ctx);
  449 + modbus_connect(ctx);
  450 + }
  451 +#else
  452 + if ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
  453 + (ctx->backend->backend_type == _MODBUS_BACKEND_TYPE_TCP) &&
413 (errno == ECONNRESET || errno == ECONNREFUSED || 454 (errno == ECONNRESET || errno == ECONNREFUSED ||
414 errno == EBADF)) { 455 errno == EBADF)) {
415 int saved_errno = errno; 456 int saved_errno = errno;
@@ -418,6 +459,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) @@ -418,6 +459,7 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
418 /* Could be removed by previous calls */ 459 /* Could be removed by previous calls */
419 errno = saved_errno; 460 errno = saved_errno;
420 } 461 }
  462 +#endif
421 return -1; 463 return -1;
422 } 464 }
423 465