Fix (RTU USB) failure to select()
an invalid file descriptor
#1
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Implementation of new libusb-based USB RTU for libmodbus, as proposed by @EchterAgo as part of networkupstools/nut#2063 solution, involves direct libusb API communications in the new backend. As such, there is normally no file descriptor to
select()
for incoming data, as is the case with serial port or a network socket (TCP RTU).After investigation done in networkupstools/nut#2609 and related tickets (networkupstools/nut#2289, networkupstools/nut#2732) I am convinced that the technical issue is in this backend never initializing
ctx->s
so it remains-1
from common allocation. The (generally platform-defined) implementations ofFD_SET
et al expect non-negative integers as file descriptor numbers:While some platforms used for initial development apparently were lax about this for whatever reason, on others later on this use of
-1
misfired visibly; I suspect they were made more secure about checking for memory errors (and here we could have had an array underflow, depending onFD_XXX
implementation as e.g. macros).This PR proposes a couple of changes:
ctx->s == -1
in the FD set forselect()
(just in case, do pass that logical code path - e.g. if the system imposes some default file descriptors to consider anyway), and do notreturn
from that code path if it failed and we hadctx->s == -1
.ctx->s
.These changes were tested in networkupstools/nut#2609 (comment) which collected the device data and did not crash like before.
NOTE: The test
Got a list of 3 libusb file descriptors to poll
and so did not assign any toctx->s
; this may need more exploration - what those FDs are and if each should be polled. Maybe change the singlectx->s
to an array (or to keep code of other RTU's largely unmodified, add the array to backend or even common ctx structure, and use it forselect()
if e.g.ctx->s==-2
)?