I have an update:

I switched now to WLAN, the problem is gone. This is really weird but I 
think I know what happens here:

OSX is probably "too" clever: I talked this morning to an osx expert and he 
said, that OSX does a few magic things when connected to gigabit. For 
instance: blocking functions MAY no block if thread scheduled is considered 
more expensive (thats why I get those errors when using packets over a few 
hundred bytes, but no errors when using very small packets) than sending, 
that explains my "nonblocking" behavior even though the socket was put into 
blocking mode. 

Further: OSX seems to buffer packets for gigabit on a different buffer 
which could raise ENOBUFS error instead of just block for a given time.

Funny enough, I got this morning my hands on a BSD system (FreeBSD) and it 
indeed caused identical problems when connected to gigabit. Linux does not 
have problems with gigabit though, which is nice. 

I think this issue is kind of solved for me, because the application should 
run in internet environments instead of high speed local lans where tcp 
should be used anyway.

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