Skip to content

Commit 512aba6

Browse files
authored
Merge pull request #1 from jimklimov/issue-nut-2609
Fix (RTU USB) failure to `select()` an invalid file descriptor
2 parents 584fbda + cf058fb commit 512aba6

3 files changed

Lines changed: 60 additions & 3 deletions

File tree

configure.ac

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,23 @@ if test "x$with_libusb" != "xno"; then
157157
LIBUSB_LIBS="-lusb-1.0"
158158
AC_DEFINE(HAVE_LIBUSB, 1, [defined if libusb is available])
159159
have_libusb=yes
160+
161+
AC_MSG_CHECKING([for libusb pollfd accessibility])
162+
AC_LANG_PUSH([C])
163+
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([
164+
#include <libusb-1.0/libusb.h>
165+
],[
166+
libusb_context *ctx = NULL;
167+
const struct libusb_pollfd** list = libusb_get_pollfds(ctx);
168+
/* Do not care about actual return value in this test,
169+
* normally check for non-zero meaning to look in errno */
170+
]
171+
)],
172+
[AC_DEFINE(HAVE_LIBUSB_POLLFD, 1, [defined if libusb pollfd is available])
173+
AC_MSG_RESULT([ok])
174+
],
175+
[AC_MSG_RESULT([no])]
176+
)
160177
], [
161178
AC_MSG_ERROR(["libusb-1.0 not found. Please install libusb-1.0."])
162179
])

src/modbus-rtu-usb.c

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,35 @@ static int _modbus_rtu_usb_connect(modbus_t *ctx)
546546
}
547547

548548
ctx_rtu_usb->device_handle = dev_handle;
549-
549+
#if defined HAVE_LIBUSB_POLLFD && HAVE_LIBUSB_POLLFD
550+
if (usb_ctx) {
551+
const struct libusb_pollfd** pollfds = libusb_get_pollfds(usb_ctx);
552+
if (pollfds) {
553+
unsigned j;
554+
for (j=0; pollfds[j] != NULL; j++) {}
555+
if (ctx->debug) {
556+
printf("Got a list of %u libusb file descriptors to poll\n", j);
557+
}
558+
/* FIXME: We might get more than one FD here.
559+
* Some research is needed to check if they
560+
* all should be polled. In that case maybe
561+
* libmodbus should move from single ctx->s
562+
* to an array of file descriptors/sockets.
563+
*/
564+
if (j == 1) {
565+
ctx->s = pollfds[0]->fd;
566+
}
567+
} else if (ctx->debug) {
568+
printf("Got no list of libusb file descriptors to poll\n");
569+
}
570+
} else if (ctx->debug) {
571+
printf("Got no libusb context to query for file descriptors to poll\n");
572+
}
573+
#else
574+
if (ctx->debug) {
575+
printf("Can not get a list of libusb file descriptors to poll from this libusb version\n");
576+
}
577+
#endif /* HAVE_LIBUSB_POLLFD */
550578
break;
551579
}
552580

src/modbus.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,14 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
377377

378378
/* Add a file descriptor to the set */
379379
FD_ZERO(&rset);
380-
FD_SET(ctx->s, &rset);
380+
if (ctx->s < 0) {
381+
if (ctx->debug) {
382+
/* we may not have an FD with e.g. libusb usage */
383+
fprintf(stderr, "Using a backend without a file descriptor, will not select() on it.\n");
384+
}
385+
} else {
386+
FD_SET(ctx->s, &rset);
387+
}
381388

382389
/* We need to analyse the message step by step. At the first step, we want
383390
* to reach the function code because all packets contain this
@@ -430,7 +437,12 @@ int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type)
430437
errno = saved_errno;
431438
#endif
432439
}
433-
return -1;
440+
if (ctx->s >= 0) {
441+
return -1;
442+
}
443+
// else: We have at most tried some default FD's but not
444+
// the (lacking) one for the backend, so fall through for
445+
// its recv method anyway (e.g. query libusb directly).
434446
}
435447

436448
rc = ctx->backend->recv(ctx, msg + msg_length, length_to_read);

0 commit comments

Comments
 (0)