[Twisted-Python] linux kernel 2.6.11-rc broke twisted process pipes

James Y Knight foom at fuhm.net
Mon Feb 28 22:40:00 EST 2005


On Feb 28, 2005, at 7:37 PM, Andrea Arcangeli wrote:
> It's never the inverse since pollin was always forced to be set, both
> for readers and writers, so a write fd was always returned as readable
> unconditionally.

I'm glad we all agree as to what the new behavior should be, but you're 
incorrect about the extent of the old brokenness. Simple tests prove 
that POLLIN was not forced to be true always:

On a debian 2.6.9-1-k7 kernel:

====
import os,select
r,w=os.pipe()
p=select.poll()
p.register(w, select.POLLIN|select.POLLOUT)

print select.select([w],[w],[w],0)
print p.poll(0)

os.write(w, "asdf")
print select.select([w],[w],[w],0)
print p.poll(0)

os.close(r)
print select.select([w],[w],[w],0)
print p.poll(0)
====

outputs:
([], [4], [])
[(4, 4)] (aka POLLOUT)
([4], [], [])
[(4, 1)] (aka POLLIN)
([4], [4], [])
[(4, 9)] (aka POLLIN|POLLERR)

> It's POLLERR not POLLHUP. POLLHUP is set only when the "writer" side
> disconnected and you're listening to a reader fd. POLLERR is instead
> returned when the "reader" disconnected and you're listening to a
> writer fd.

Right. Twisted treats all of POLLERR/HUP/NVAL the same, anyways.

> 671         if (events & (POLLIN | POLLRDNORM)) {
> 672                 if ((rpipe->pipe_buffer.cnt > 0) ||
> 673                     (rpipe->pipe_state & PIPE_EOF))
> 674                         revents |= events & (POLLIN | POLLRDNORM);
> 675         }
> The way I read it, even openbsd will report the fd as readable
> regardless if the channel is disconnected, if the buffer has something
> into it.

Nope -- Notice that rpipe and wpipe are backwards for the read and 
write fds. "rpipe" on the write fd won't ever have any data in it. 
(Except of course that pipes in BSD are bidirectional!). In BSD, 
everything is symmetric, so it'd be very difficult for a stupid bug 
like reporting the same status for both ends to occur.

> Are you reall sure it can't be called with pollreactor?
>
> Sorry for asking again but I really want to be sure select won't screw
> things up with >1024 fds open ;)

Yes, it will get called, because linux returns (returned?) 
POLLERR|POLLIN when the other side is closed. pollreactor doesn't 
assume the connection was lost immediately when POLLERR/etc is set, if 
POLLIN is also set, because POLLIN|POLLHUP means there is more data 
available to be read from the kernel buffer that was sent before the 
connection closed. And, since normal transport implementations of 
doRead actually do try to read, if it was lying about POLLIN, that's 
okay: the read syscall will fail, and CONNECTION_LOST will be returned 
from doRead.

James





More information about the Twisted-Python mailing list