stephane / libmodbus

A Modbus library for Linux, Mac OS, FreeBSD and Windows
http://libmodbus.org
GNU Lesser General Public License v2.1
3.3k stars 1.71k forks source link

LibModbus hangs in endless loop if tcp-error occurs and MODBUS_ERROR_RECOVERY_LINK was set #618

Open dadidag opened 2 years ago

dadidag commented 2 years ago

Using modbus-tcp in Windows.

If I set error-handling to MODBUS_ERROR_RECOVERY_LINK and a tcp-error occurs (e.g. Modbus-slave has died) the send_msg method hangs in an endless loop due to using errno insted of WSAGetLastError() (in Windows the send() API does not set errno, WSAGetLastError has o be used).

static int send_msg(modbus_t ctx, uint8_t msg, int msg_length) { int rc; int i;

msg_length = ctx->backend->send_msg_pre(msg, msg_length);

if (ctx->debug) {
    for (i = 0; i < msg_length; i++)
        printf("[%.2X]", msg[i]);
    printf("\n");
}

/* In recovery mode, the write command will be issued until to be
   successful! Disabled by default. */
do {
    rc = ctx->backend->send(ctx, msg, msg_length);
    if (rc == -1) {
        _error_print(ctx, NULL);
        if (ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) {
            int saved_errno = errno;

            if ((errno == EBADF || errno == ECONNRESET || errno == EPIPE)) {
                modbus_close(ctx);
                _sleep_response_timeout(ctx);
                modbus_connect(ctx);
            } else {
                _sleep_response_timeout(ctx);
                modbus_flush(ctx);
            }
            errno = saved_errno;
        }
    }
} while ((ctx->error_recovery & MODBUS_ERROR_RECOVERY_LINK) &&
         rc == -1);
stephane commented 1 year ago

It is fixed by https://github.com/stephane/libmodbus/commit/db1cbc593501590eef16bbf9e0746290ac9116b9?