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