asynchat sends data on async_chat.push and .push_with_producer

ludvig.ericson at gmail.com ludvig.ericson at gmail.com
Tue May 13 07:43:02 EDT 2008


Hello,

My question concerns asynchat in particular. With the following half-
pseudo code in mind:

    class Example(asynchat.async_chat):
        def readable(self):
            if foo:
                self.push_with_producer(ProducerA())
            return asynchat.async_chat.readable(self)

Now, asyncore will call the readable function just before a select(),
and it is meant to determine whether or not to include that asyncore
dispatcher in the select map for reading.

The problem with this code is that it has the unexpected side-effect
of _immediately_ trying to send, disregarding if the async_chat object
is indeed writable or not.

The asynchat.push_with_producer (and .push as well)
call .initiate_send(), which in turn calls .send if there's data
buffered. While this might seem logical, it isn't at all.

Insinuate that when Example.readable is called, the socket has already
been closed. There are two possible scenarios where it could be
closed. a) The remote endpoint closed the connection, and b) the
producer ProducerA somehow closed the connection (my case).

Obviously, calling send on a socket that has been closed will result
in an error - EBADF, "Bad file descriptor".

So, my question is: Why does asynchat.push* call self.initiate_send?
Nothing in the name "push" suggests that it'll transmit immediately,
disregarding potential "closedness". Removing the two calls
to .initiate_send() in the two push functions would still mean data is
sent, but only when data can be sent - which is, IMO, what should be
done.

Thankful for insights,
Ludvig.



More information about the Python-list mailing list