BIND 10 #312: python msgq timeouts differ from c++ ones
BIND 10 Development
do-not-reply at isc.org
Fri Sep 10 20:56:31 UTC 2010
#312: python msgq timeouts differ from c++ ones
-------------------------+--------------------------------------------------
Reporter: jelte | Owner: jelte
Type: defect | Status: reviewing
Priority: major | Milestone: y2 6 month milestone
Component: msgq | Resolution:
Keywords: | Sensitive: 0
Estimatedhours: 0.0 | Hours: 0
Billable: 1 | Totalhours: 0
Internal: 0 |
-------------------------+--------------------------------------------------
Changes (by vorner):
* owner: vorner => jelte
Comment:
I think it is correct, when it is in blocking mode. However, in
nonblocking, I still think there might be a problem. If I'm wrong, please
tell me, why this can not happen:
I'm assuming that if None is returned, it means „I do not have any
messages from the bus right now, ask later“.
So, asume someone sent a message like this:
|length|........data.........|
But because the network is slow, we got only this, and the rest is
somewhere on the way, when we ask if there is something and we do not
block:
|length|........da
So, now we read length, which returs whole 4 bytes. Then we read part of
the data until the „a“. Because we still do not have enough, we loop again
(in the _receive_bytes) and try to get more, but because the socket is
nonblocking, it throws socket.error with EAGAIN (meaning no more data
now). It is caught in _receive_full_buffer, which then returns None (no
message right now), discarding the „length“ and „........da“ we already
read.
So someone asks for a message a moment later, so it goes to read the
length. The „ta.........“ is on the socket now, so we take part of it as a
length, which is wrong. Similar thing would happen, if we asked at the
time when we had only part of the length on the socket (which can happen
when the two messages were sent together/there was long send buffer and it
was in the same packet with preciding message).
I think we need to keep the data we already read and reuse it next time in
case of EAGAIN. May I suggest a wrapper around recv that keeps a buffer of
read data and when we get the whole message we clean it, when we get
EAGAIN, we put position at the front and try getting data from the buffer
next time before we start reading from the socket again? Or, if I'm not
clear in what I mean, should I write the code and give the review to
someone else instead?
There's other thing that seems little bit odd:
if len(new_data) == 0: # server closed connection
if nonblock:
return None
else:
raise ProtocolError("Read of 0 bytes: connection closed")
Why, when the server closes a connection, it is an error when we have
blocking read and is „No message right now, ask later“ when we are
nonblocking? (recv returns 0 bytes only when the connection is closed, if
there are 0 bytes waiting and we are nonblocking, it throws EAGAIN).
--
Ticket URL: <http://bind10.isc.org/ticket/312#comment:6>
BIND 10 Development <http://bind10.isc.org>
BIND 10 Development
More information about the bind10-tickets
mailing list