socket.recv won't block?

1,721 views
Skip to first unread message

Justin Patrin

unread,
Jul 22, 2011, 3:00:02 PM7/22/11
to gevent: coroutine-based Python network library
I'm just implementing a new service with gevent and I'm a bit
surprised that I can't get the gevent sockets to "block" within a
greenlet. I'm using the StreamServer with a handling function which
calls socket.recv(). I've tried socket.setblocking(1) and
socket.settimeout(None) but neither makes any difference. My read loop
just keeps looping over and over and won't even give up control to
another greenlet.

I've added calls to gevent.socket.wait_read() and this causes the
greenlet to give up control and allow other greenlets to run but it
also does not block. My read loop is still running constantly, causing
high CPU usage even though no data is received. Am I missing
something? I looked into how socket.recv is supposed to work and
looked at the gevent.socket.socket.recv call which appears as if it
should block with wait_read() if EWOULDBLOCK is raised, but if I step
into that code it never gets past the return. sock.recv(*args) is
always just returning an empty string.

Here's a simplified test case:


import gevent.socket
from gevent.server import StreamServer
from gevent.pool import Pool

def handle(socket, address):
socket.setblocking(1)
i = 0
while True:
gevent.socket.wait_read(socket.fileno())
data = socket.recv(10)
print "[%i] data: %r" % (i, data)
i += 1

def start_server():
server = StreamServer(('0.0.0.0', 8787), handle)
server.serve_forever()

def main():
start_server()

if __name__ == '__main__':
main()

I have tested with:
echo "hello" | nc localhost 8787

Denis Bilenko

unread,
Jul 22, 2011, 3:07:02 PM7/22/11
to gev...@googlegroups.com
On Sat, Jul 23, 2011 at 2:00 AM, Justin Patrin <jpa...@lolapps.com> wrote:
> I've added calls to gevent.socket.wait_read() and this causes the
> greenlet to give up control and allow other greenlets to run but it
> also does not block. My read loop is still running constantly, causing
> high CPU usage even though no data is received. Am I missing
> something? I looked into how socket.recv is supposed to work and
> looked at the gevent.socket.socket.recv call which appears as if it
> should block with wait_read() if EWOULDBLOCK is raised, but if I step
> into that code it never gets past the return. sock.recv(*args) is
> always just returning an empty string.

recv() returning empty string means the connection was closed by the
remote side.
At this point you're supposed to stop calling recv().

def handle(socket, address):
while True:
data = socket.recv(10)
if not data:
break

Justin Patrin

unread,
Jul 22, 2011, 3:52:57 PM7/22/11
to gevent: coroutine-based Python network library
On Jul 22, 12:07 pm, Denis Bilenko <denis.bile...@gmail.com> wrote:
Thanks, that makes some sense....although it's interesting that if I
add a socket.send() in the loop, nc still gets those messages back
even though recv() is returning an empty string.

Damjan

unread,
Jul 27, 2011, 3:54:37 PM7/27/11
to gevent: coroutine-based Python network library
> Thanks, that makes some sense....although it's interesting that if I
> add a socket.send() in the loop, nc still gets those messages back
> even though recv() is returning an empty string.

That's because sockets can be closed separetelly in both directions.
See man 3 shutdown
Reply all
Reply to author
Forward
0 new messages