From 6b94461bf616c2edbd0b312ab988a18ba800bee1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Jan 2025 22:33:37 +0100 Subject: [PATCH 1/5] src/modbus.c: _modbus_receive_msg(): avoid select() on invalid file descriptor Signed-off-by: Jim Klimov --- src/modbus.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/modbus.c b/src/modbus.c index 0360d5ccd..d2b6324e0 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -377,7 +377,14 @@ 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 < 0) { + if (ctx->debug) { + /* we may not have an FD with e.g. libusb usage */ + fprintf(stderr, "Using a backend without a file descriptor, will not select() on it.\n"); + } + } else { + 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 From e7ac328a94065701ba6c66ccd0c220fba4248b74 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sat, 11 Jan 2025 22:55:36 +0100 Subject: [PATCH 2/5] configure.ac, src/modbus-rtu-usb.c: try to use libusb_get_pollfds() if available Signed-off-by: Jim Klimov --- configure.ac | 17 +++++++++++++++++ src/modbus-rtu-usb.c | 24 +++++++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 016f8fa0f..b3d1a0af5 100644 --- a/configure.ac +++ b/configure.ac @@ -157,6 +157,23 @@ if test "x$with_libusb" != "xno"; then LIBUSB_LIBS="-lusb-1.0" AC_DEFINE(HAVE_LIBUSB, 1, [defined if libusb is available]) have_libusb=yes + + AC_MSG_CHECKING([for libusb pollfd accessibility]) + AC_LANG_PUSH([C]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([ +#include +],[ +libusb_context *ctx = NULL; +const struct libusb_pollfd** list = libusb_get_pollfds(ctx); +/* Do not care about actual return value in this test, + * normally check for non-zero meaning to look in errno */ +] + )], + [AC_DEFINE(HAVE_LIBUSB_POLLFD, 1, [defined if libusb pollfd is available]) + AC_MSG_RESULT([ok]) + ], + [AC_MSG_RESULT([no])] + ) ], [ AC_MSG_ERROR(["libusb-1.0 not found. Please install libusb-1.0."]) ]) diff --git a/src/modbus-rtu-usb.c b/src/modbus-rtu-usb.c index 5413176a3..f1a5b4788 100644 --- a/src/modbus-rtu-usb.c +++ b/src/modbus-rtu-usb.c @@ -546,7 +546,29 @@ static int _modbus_rtu_usb_connect(modbus_t *ctx) } ctx_rtu_usb->device_handle = dev_handle; - +#if defined HAVE_LIBUSB_POLLFD && HAVE_LIBUSB_POLLFD + if (usb_ctx) { + const struct libusb_pollfd** pollfds = libusb_get_pollfds(usb_ctx); + if (pollfds) { + unsigned j; + for (j=0; pollfds[j] != NULL; j++) {} + if (ctx->debug) { + printf("Got a list of %u libusb file descriptors to poll", j); + } + if (j == 1) { + ctx->s = pollfds[0]->fd; + } + } else if (ctx->debug) { + printf("Got no list of libusb file descriptors to poll"); + } + } else if (ctx->debug) { + printf("Got no libusb context to query for file descriptors to poll"); + } +#else + if (ctx->debug) { + printf("Can not get a list of libusb file descriptors to poll from this libusb version"); + } +#endif /* HAVE_LIBUSB_POLLFD */ break; } From d483010810c59bdace2a105512b4a4490351968f Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Sun, 12 Jan 2025 13:14:39 +0100 Subject: [PATCH 3/5] src/modbus.c: _modbus_receive_msg(): do not return after failed select() if this backend had no valid FD Signed-off-by: Jim Klimov --- src/modbus.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/modbus.c b/src/modbus.c index d2b6324e0..a350d37f8 100644 --- a/src/modbus.c +++ b/src/modbus.c @@ -437,7 +437,12 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) errno = saved_errno; #endif } - return -1; + if (ctx->s >= 0) { + return -1; + } + // else: We have at most tried some default FD's but not + // the (lacking) one for the backend, so fall through for + // its recv method anyway (e.g. query libusb directly). } rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read); From 3f5ddecbecf68c272ce1a7c238419b4c450dbede Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 14 Jan 2025 11:08:21 +0100 Subject: [PATCH 4/5] src/modbus-rtu-usb.c: _modbus_rtu_usb_connect(): fix debug printouts (add EOL) Signed-off-by: Jim Klimov --- src/modbus-rtu-usb.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modbus-rtu-usb.c b/src/modbus-rtu-usb.c index f1a5b4788..c32be6749 100644 --- a/src/modbus-rtu-usb.c +++ b/src/modbus-rtu-usb.c @@ -553,20 +553,20 @@ static int _modbus_rtu_usb_connect(modbus_t *ctx) unsigned j; for (j=0; pollfds[j] != NULL; j++) {} if (ctx->debug) { - printf("Got a list of %u libusb file descriptors to poll", j); + printf("Got a list of %u libusb file descriptors to poll\n", j); } if (j == 1) { ctx->s = pollfds[0]->fd; } } else if (ctx->debug) { - printf("Got no list of libusb file descriptors to poll"); + printf("Got no list of libusb file descriptors to poll\n"); } } else if (ctx->debug) { - printf("Got no libusb context to query for file descriptors to poll"); + printf("Got no libusb context to query for file descriptors to poll\n"); } #else if (ctx->debug) { - printf("Can not get a list of libusb file descriptors to poll from this libusb version"); + printf("Can not get a list of libusb file descriptors to poll from this libusb version\n"); } #endif /* HAVE_LIBUSB_POLLFD */ break; From cf058fb42b783d2cfc2b57575e534bb7e797570a Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 14 Jan 2025 11:08:40 +0100 Subject: [PATCH 5/5] src/modbus-rtu-usb.c: _modbus_rtu_usb_connect(): comment about getting multiple FDs to poll Signed-off-by: Jim Klimov --- src/modbus-rtu-usb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modbus-rtu-usb.c b/src/modbus-rtu-usb.c index c32be6749..6e861767f 100644 --- a/src/modbus-rtu-usb.c +++ b/src/modbus-rtu-usb.c @@ -555,6 +555,12 @@ static int _modbus_rtu_usb_connect(modbus_t *ctx) if (ctx->debug) { printf("Got a list of %u libusb file descriptors to poll\n", j); } + /* FIXME: We might get more than one FD here. + * Some research is needed to check if they + * all should be polled. In that case maybe + * libmodbus should move from single ctx->s + * to an array of file descriptors/sockets. + */ if (j == 1) { ctx->s = pollfds[0]->fd; }