Do nonblocking socket read before select for packet receive #104
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.
I've periodically run into some cases where the
receive_packet
method hangs indefinitely on anIO.select
even though the underlying network socket has actually received some bytes from the network for incoming MQTT packets. I've only been able to consistently reproduce this when running with JRuby 9k for some reason but I believe the underlying condition affects MRI Ruby as well.Specifically, I believe the condition that I'm running into is the same as the buffering issue documented for
OpenSSL::SSL::SSLSocket
andIO.select
calls at http://ruby-doc.org/core-2.2.0/IO.html#method-c-select.I experimented with changing the logic in
receive_packet
to use a combination of aread_nonblock
call (reading only a single byte at most) followed by anIO.select
call in the event that no data is available to be read and anIO.WaitReadable
-derived exception is thrown. This PR shows the approach that I used. It does make the logic a bit more messy in that for cases that the first byte in the packet is read beforeMQTT:Packet.read()
is called, it passes along the byte so that thePacket.read()
method can use it.With the approach on this PR, I'm no longer able to reproduce the indefinite
IO.select()
hangs, on MRI Ruby or JRuby. The read throughput also seems like it might be a bit better with a heavy amount of publish packets coming into the socket since available data seems to be received much more quickly.Thanks for your consideration for this PR and thanks much for all of the great work that you've put into this library!