Thanks for your help so far, I really appreciate it.

A manual backoff seems the best solution for this weird behavior for now, 
since reliable udp heavily depends on timing this is not such a bad thing 
anyway.

Meanwhile I try to figure out the cause for this issue.


Am Montag, 24. Februar 2014 00:31:24 UTC+1 schrieb Guido van Rossum:
>
> I still can't repro it with your code. But that doesn't mean it's not a 
> real condition. It sounds like the kind of odd corner of entirely 
> legitimate UDP behavior that is hard to provoke but which a robust app 
> should handle.
>
> Note that the default behavior in Tulip appears to be to ignore OSError 
> coming out of sendto() -- the transport calls protocol.error_received(), 
> which by default does nothing. Since there are many other cases where a 
> packet may silently be dropped on the floor, this behavior is technically 
> correct -- the question is whether it is the best default behavior we can 
> imagine.
>
> Unfortunately turning it into a pause_protocol() call in your 
> error_received() handler is a little tricky -- the transport remembers 
> whether it has paused the protocol or not, but this state is not public. So 
> you shouldn't call your own pause_writing(), since you'd never receive a 
> resume_writing() call from the transport. Perhaps you can set a flag 
> internal to your protocol that just causes you to back off for a brief 
> period of time? The optimal back-off time should be tuned experimentally.
>
> --Guido
>
> On Sun, Feb 23, 2014 at 2:45 PM, Christopher Probst <
> foxnet.d...@googlemail.com <javascript:>> wrote:
>
>> I made a simpler test, without using tulip, just using plain 
>> sockets<http://stackoverflow.com/questions/21973661/os-x-udp-send-error-55-no-buffer-space-available/21973705?noredirect=1#comment33297277_21973705>
>> .
>>
>> from socket import *
>>
>> udp = socket(AF_INET, SOCK_DGRAM)
>> udp.setsockopt(SOL_SOCKET, SO_REUSEADDR, True)
>>
>> udp.bind(('0.0.0.0', 1337))
>> udp.setblocking(False)
>> udp.setsockopt(SOL_IP, IP_TTL, 4)
>> udp.connect(('8.8.8.8', 12345))
>>
>> buf = b'x' * 400for _ in range(1024 * 1024 * 10):
>>     udp.send(buf)
>>
>> In this test I'm just writing a lot of udp packets to 8.8.8.8, which gets 
>> dropped after 4 hops (it's just for testing anyway). But this code actually 
>> causes the same error (so it has nothing to do with tulip, though 
>> flow-control might be affected).
>>
>> The weird thing is, that the following code although causes the same 
>> error:
>>
>> from socket import *
>>
>> udp = socket(AF_INET, SOCK_DGRAM)
>> udp.connect(('8.8.8.8', 12345))
>>
>> buf = b'x' * 400for _ in range(1024 * 1024 * 10):
>>     udp.send(buf)
>>
>> In other words: The "blocking" mode is not so blocking apparently on my 
>> machine. If you cannot reproduce this error(which is good!), than this 
>> might be an issue on my local machine. But in any case it's not a tulip bug.
>>
>> I'm just curious what this can be...
>>   
>>
>> Am Sonntag, 23. Februar 2014 23:34:39 UTC+1 schrieb Guido van Rossum:
>>>
>>> I haven't been able to repro this using the test you attached to issue 
>>> 153. But I don't have another machine available, I've only tried localhost 
>>> on OSX (10.9) and from that same box to a local virtual machine running 
>>> Ubunu. The receiving end just throws away the data -- is that your test 
>>> setup too? I used "while 1: s.recv(10000); n += 1" in an interactive Python 
>>> shell.
>>>
>>> I do see packet loss (just counting packets received and packets sent) 
>>> but no exceptions nor does pause_writing() ever get called. From putting 
>>> some print()s in the code it looks like the sendto() operation always 
>>> immediately succeeds.
>>>
>>> The errno has a name: errno.ENOBUFS -- it's 55 on OSX, but 105 on Ubuntu.
>>>
>>> Perhaps you can elaborate on your test setup?
>>>
>>>
>>> On Sun, Feb 23, 2014 at 11:29 AM, Christopher Probst <
>>> foxnet.d...@googlemail.com> wrote:
>>>
>>>> Ok, I tried it now with 180 bytes packet and it does not occur, I guess 
>>>> that my lan connection(gigabit) is too fast that those packets get queued 
>>>> up. Or OSX decide whether or not to queue those packets based on the size. 
>>>> But this seems to be heavily os dependent .
>>>>
>>>> Am Sonntag, 23. Februar 2014 20:12:46 UTC+1 schrieb Guido van Rossum:
>>>>>
>>>>> Have you tried reducing the write buffer size?
>>>>> On Feb 23, 2014 10:41 AM, "Christopher Probst" <
>>>>> foxnet.d...@googlemail.com> wrote:
>>>>>
>>>>>> I saw this in the official 3.4rc1 doc.
>>>>>>
>>>>>> The doc says, that flow-control callbacks are valid for Protocols and 
>>>>>> SubprocessProtocols, but DatagramProtocol is not specified.
>>>>>>
>>>>>> Though I'm happy that Datagram control flow is officially supported I 
>>>>>> have now an other problem which is directly connected with this issue.
>>>>>> Using OSX10.9.1 and python 3.3 sending a lot of udp packets actually 
>>>>>> does not cause the flow-control to be activated but throws an OSError(55 
>>>>>> *No 
>>>>>> buffer space available)* .
>>>>>>
>>>>>> After googling around for hours I found out that this is a 
>>>>>> BSD(probably OS X only) thing. On linux the control-flow works as 
>>>>>> expected. 
>>>>>>
>>>>>> I listed an issue for this in your tulip repo:
>>>>>> Issue 153 <https://code.google.com/p/tulip/issues/detail?id=153>
>>>>>>
>>>>>> I think that this is really not a python bug, but the way BSD/OSX 
>>>>>> handles too much udp packets (the socket sdnbuf option is kind of 
>>>>>> ignored 
>>>>>> by OSX). I've read that windows actually handles udp overload in a 
>>>>>> similiar 
>>>>>> way as BSD does. Though i don't have a windows machine this should 
>>>>>> probably 
>>>>>> be tested to confirm or disprove this issue.
>>>>>>
>>>>>> PS:
>>>>>> 18.5.3.2.5. Flow control 
>>>>>> callbacks<http://docs.python.org/3.4/library/asyncio-protocol.html#flow-control-callbacks>
>>>>>>  
>>>>>>
>>>>>> These callbacks may be called on 
>>>>>> Protocol<http://docs.python.org/3.4/library/asyncio-protocol.html#asyncio.Protocol>
>>>>>>  and 
>>>>>> SubprocessProtocol<http://docs.python.org/3.4/library/asyncio-protocol.html#asyncio.SubprocessProtocol>
>>>>>>  instances:
>>>>>> BaseProtocol.pause_writing()<http://docs.python.org/3.4/library/asyncio-protocol.html#asyncio.BaseProtocol.pause_writing>
>>>>>>  
>>>>>>
>>>>>> Called when the transport’s buffer goes over the high-water mark.
>>>>>> BaseProtocol.resume_writing()<http://docs.python.org/3.4/library/asyncio-protocol.html#asyncio.BaseProtocol.resume_writing>
>>>>>>  
>>>>>>
>>>>>> Called when the transport’s buffer drains below the low-water mark.
>>>>>>
>>>>>>
>>>>>>
>>>>>>
>>>>>> Am Sonntag, 23. Februar 2014 18:56:42 UTC+1 schrieb Guido van Rossum:
>>>>>>>
>>>>>>> This looks like a bug in the docs; the intention is that datagram 
>>>>>>> protocols also support flow control. Where does it say so in the docs? 
>>>>>>> Is 
>>>>>>> it the PEP or the CPython Doc tree?
>>>>>>>
>>>>>>>
>>>>>>> On Sat, Feb 22, 2014 at 5:12 PM, Christopher Probst <
>>>>>>> foxnet.d...@googlemail.com> wrote:
>>>>>>>
>>>>>>>> Hi,
>>>>>>>>
>>>>>>>> after looking into the implementation I saw that, for instance, _
>>>>>>>> SelectorDatagramTransport calls _maybe_pause_protocol and it's 
>>>>>>>> counterpart, but the doc says that only Protocol and 
>>>>>>>> SubprocessProtocol has 
>>>>>>>> flow-control support and DatagramProtocol does not.
>>>>>>>>
>>>>>>>> I know that udp flow-control is not the same as tcp flow-control, 
>>>>>>>> but I'm concerned about filling up the internal buffer when writing a 
>>>>>>>> lot 
>>>>>>>> of datagrams. If this is not supported, I would argue that the udp 
>>>>>>>> support is pretty much broken for data intense application because how 
>>>>>>>> would the writer know when the internal buffer (and/or kernel level 
>>>>>>>> buffer) 
>>>>>>>> are full ?
>>>>>>>>
>>>>>>>> So, is the doc just not up-to-date or is it an implementation 
>>>>>>>> detail of tulip ?
>>>>>>>>
>>>>>>>>  And other question that came up: Are there any plans for 
>>>>>>>> coroutine methods for udp (like StreamWriter/Reader for TCP) ? 
>>>>>>>>
>>>>>>>> Also, are there any "dirty" corners somebody heavily working with 
>>>>>>>> udp have to know ? I'm implementing reliable udp and I would like to 
>>>>>>>> use 
>>>>>>>> the coroutine style instead of callbacks.
>>>>>>>>
>>>>>>>>
>>>>>>>> Regards,
>>>>>>>> Chris
>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> -- 
>>>>>>> --Guido van Rossum (python.org/~guido) 
>>>>>>>
>>>>>>
>>>
>>>
>>> -- 
>>> --Guido van Rossum (python.org/~guido) 
>>>
>>
>
>
> -- 
> --Guido van Rossum (python.org/~guido) 
>

Reply via email to