Weird problem with UDP and gevent

R

Roy Smith

I'm running:

Ubuntu Precise
Python 2.7.3
django 1.4.5
gunicorn 0.17.4
gevent 1.0dev (rc3)

I haven't been able to pin this down exactly, but it looks like if I
do (inside of a custom logging.Handler subclass):

# Paraphrased from the actual code
remote_addr = ("localhost", 9700)
self.socket = socket.socket(type=socket.SOCK_DGRAM)
payload = "..."
self.socket.connect(remote_addr)
self.socket.send(payload)

I get intermittant hangs in the connect() call. If I rewrite this as:

remote_addr = ("localhost", 9700)
self.socket = socket.socket(type=socket.SOCK_DGRAM)
payload = "..."
self.socket.sendto(payload, remote_addr)

everything works fine. Has anybody seen anything like this? I'm
guessing this is some kind of gevent bug.

My apologies if this is the wrong forum. The gevent mailing list
appears to be broken (no activity in 3 weeks, no response to
subscription request, post via google groups disappeared into the
void), so I'm trying here.
 
J

James Harris

Roy Smith said:
I'm running:

Ubuntu Precise
Python 2.7.3
django 1.4.5
gunicorn 0.17.4
gevent 1.0dev (rc3)

I haven't been able to pin this down exactly, but it looks like if I
do (inside of a custom logging.Handler subclass):

# Paraphrased from the actual code
remote_addr = ("localhost", 9700)
self.socket = socket.socket(type=socket.SOCK_DGRAM)
payload = "..."
self.socket.connect(remote_addr)
self.socket.send(payload)

I get intermittant hangs in the connect() call. If I rewrite this as:

remote_addr = ("localhost", 9700)
self.socket = socket.socket(type=socket.SOCK_DGRAM)
payload = "..."
self.socket.sendto(payload, remote_addr)

everything works fine. Has anybody seen anything like this? I'm
guessing this is some kind of gevent bug.

Those are two different things. You would normally use connect() on a
SOCK_STREAM socket. It requires that the remote endpoint, in this case
localhost:9700, has an open socket listening for connections. sendto() is
the right thing to use with SOCK_DGRAM.

James
 
R

Roy Smith

Those are two different things. You would normally use connect() on a
SOCK_STREAM socket. It requires that the remote endpoint, in this case
localhost:9700, has an open socket listening for connections. sendto() is
the right thing to use with SOCK_DGRAM.

You are supposed to be able to call connect() on a UDP socket. All it does is store the remote address in the kernel socket structure. Doing connect() followed by a series of send()s is nominally more efficient than doing a series of sendto()s.

I forgot to mention that the connect()/send() code works just fine if I switch my gunicorn config from gevent to sync workers.
 
G

Grant Edwards

Those are two different things.

Yes. They differ in the addresses _from_which_ packets can be
received. In the "connect" example, you will only be able to receive
packets from ("localhost",9700). In the second example you can
receive packets from any address. Since the snippets only send
packets not receive packets, they should both behave identically.
You would normally use connect() on a SOCK_STREAM socket. It requires
that the remote endpoint, in this case localhost:9700, has an open
socket listening for connections. sendto() is the right thing to use
with SOCK_DGRAM.

Either will work. You can use connect() with a SOCK_DGRAM. What it
does is

1) save the destination address and use it when you call send()

2) limit the addresses from which packets will be received.

From the Linux connect(2) man page:

If the socket sockfd is of type SOCK_DGRAM then addr is the address
to which datagrams are sent by default, and the only address from
which datagrams are received.
 

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top