From 244006169fe6e4501f2d4fea9b4b0f04a5927f06 Mon Sep 17 00:00:00 2001 From: zhangyi Date: Sat, 1 Jan 2022 09:17:05 +0800 Subject: [PATCH] feat(modbus): use poll() for *nix --- src/modbus-rtu.c | 13 ++++++++++--- src/modbus-tcp.c | 36 +++++++++++++++++++----------------- src/modbus.c | 5 +++-- 3 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/modbus-rtu.c b/src/modbus-rtu.c index 01e703d46..e318f6c9e 100644 --- a/src/modbus-rtu.c +++ b/src/modbus-rtu.c @@ -11,6 +11,7 @@ #include #ifndef _MSC_VER #include +#include #endif #include @@ -1167,14 +1168,20 @@ static int _modbus_rtu_select(modbus_t *ctx, fd_set *rset, return -1; } #else - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) { + struct pollfd fds[1]; + fds[0].fd = ctx->s; + fds[0].events = POLLIN; + fds[0].revents = 0; + int timeout_ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + while ((s_rc = poll(fds, 1, timeout_ms)) == -1) { if (errno == EINTR) { if (ctx->debug) { fprintf(stderr, "A non blocked signal was caught\n"); } /* Necessary after an error */ - FD_ZERO(rset); - FD_SET(ctx->s, rset); + fds[0].fd = ctx->s; + fds[0].events = POLLIN; + fds[0].revents = 0; } else { return -1; } diff --git a/src/modbus-tcp.c b/src/modbus-tcp.c index 516427370..cdcc58c22 100644 --- a/src/modbus-tcp.c +++ b/src/modbus-tcp.c @@ -4,6 +4,7 @@ * SPDX-License-Identifier: LGPL-2.1-or-later */ +#include #if defined(_WIN32) # define OS_WIN32 /* ws2_32.dll has getaddrinfo and freeaddrinfo on Windows XP and later. @@ -19,6 +20,7 @@ #include #ifndef _MSC_VER #include +#include #endif #include #include @@ -273,15 +275,13 @@ static int _connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen, #else if (rc == -1 && errno == EINPROGRESS) { #endif - fd_set wset; int optval; socklen_t optlen = sizeof(optval); - struct timeval tv = *ro_tv; - /* Wait to be available in writing */ - FD_ZERO(&wset); - FD_SET(sockfd, &wset); - rc = select(sockfd + 1, NULL, &wset, NULL, &tv); + struct pollfd fds[1]; + fds[0].fd = sockfd; + fds[0].events = POLLOUT; + rc = poll(fds, 1, ro_tv->tv_sec * 1000 + ro_tv->tv_usec / 1000); if (rc <= 0) { /* Timeout or fail */ return -1; @@ -451,14 +451,10 @@ static int _modbus_tcp_flush(modbus_t *ctx) rc = recv(ctx->s, devnull, MODBUS_TCP_MAX_ADU_LENGTH, MSG_DONTWAIT); #else /* On Win32, it's a bit more complicated to not wait */ - fd_set rset; - struct timeval tv; - - tv.tv_sec = 0; - tv.tv_usec = 0; - FD_ZERO(&rset); - FD_SET(ctx->s, &rset); - rc = select(ctx->s+1, &rset, NULL, NULL, &tv); + struct pollfd fds[1]; + fds[0].fd = ctx->s; + fds[0].events = POLLIN; + rc = poll(fds, 1, 0); if (rc == -1) { return -1; } @@ -718,14 +714,20 @@ int modbus_tcp_pi_accept(modbus_t *ctx, int *s) static int _modbus_tcp_select(modbus_t *ctx, fd_set *rset, struct timeval *tv, int length_to_read) { int s_rc; - while ((s_rc = select(ctx->s+1, rset, NULL, NULL, tv)) == -1) { + struct pollfd fds[1]; + fds[0].fd = ctx->s; + fds[0].events = POLLIN; + fds[0].revents = 0; + int timeout_ms = tv->tv_sec * 1000 + tv->tv_usec / 1000; + while ((s_rc = poll(fds, 1, timeout_ms)) == -1) { if (errno == EINTR) { if (ctx->debug) { fprintf(stderr, "A non blocked signal was caught\n"); } /* Necessary after an error */ - FD_ZERO(rset); - FD_SET(ctx->s, rset); + fds[0].fd = ctx->s; + fds[0].events = POLLIN; + fds[0].revents = 0; } else { return -1; } diff --git a/src/modbus.c b/src/modbus.c index 43e8a3592..2189950c2 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -357,8 +357,9 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) /* Add a file descriptor to the set */ FD_ZERO(&rset); - FD_SET(ctx->s, &rset); - + if (ctx->s < 1024) { + FD_SET(ctx->s, &rset); + } /* We need to analyse the message step by step. At the first step, we want * to reach the function code because all packets contain this * information. */