Sorry for Google Groups formatting. Trying again as html.
--
You received this message because you are subscribed to the Google Groups "Tornado Web Server" group.
To unsubscribe from this group and stop receiving emails from it, send an email to python-tornad...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/python-tornado/ecd62bfd80922512a36aecb7fa68ed1e%40mail.gmail.com.
Thank you, Python 3 does resolve this pipe problem, but I suspect that pull request is unrelated. Running the example below on Python 3 with Tornado 5 does not show the problem (and neither does the equivalent translation for Tornado 6): If I read the Tornado code correctly, I think the differences is that Tornado 5 uses the asyncio event loop when available and BaseAsyncIOLoop.add_handler() ignores IOLoop.ERROR. So updating to Python 3 does fix the problem (and begs the question of what happens to epoll error events in asyncio, which I haven’t looked into).
To view this discussion on the web visit https://groups.google.com/d/msgid/python-tornado/CAFkYKJ4patKC%2BKzg5O1DEUByg0Ko%3D2CEKF2vgSQSGBR5KjNXSg%40mail.gmail.com.
For anyone else still migrating apps off Python 2, the workaround I posted earlier in this thread is incomplete and potentially causes the reading side of PipeIOStream on Python 2 to hang. To correct this, translate EPOLLHUP to EPOLLIN instead of ignoring it:
class CompleteReadPipeIOStream(PipeIOStream):
def get_fd_error(self):
# The default implementation returns None, which makes errors undetectable
return IOError('Unknown error in pipe')
def write(self, *args, **kwargs):
raise NotImplementedError('This implementation untested for writes')
def _handle_events(self, fd, events):
if events & select.EPOLLHUP:
# Do not pass along EPOLLHUP because super treats it as an error
# and marks this side of the pipe closed when actually it just
# means that the write side of the pipe closed. This side might
# still need to read data, so closing on hup can result in
# incomplete reads.
#
# Translate to read because there's a window between when the
# writer writes the last data and when it writes EOF during which
# super might try a read. That read returns None, meaning EAGAIN
# or EWOULDBLOCK, so super waits for an EPOLLIN message before it
# will satisfy the next read future, but the EPOLLIN never arrives
# because closing the writer sets EPOLLHUP instead.
events = (events | select.EPOLLIN) & ~select.EPOLLHUP
super(CompleteReadPipeIOStream, self)._handle_events(fd, events)
Switching to Python 3 with Tornado 5+, using asyncio, that is, obviates this. Because asyncio uses the selectors module, it translates hup to read or write already - from the discussion starting on https://github.com/python/cpython/issues/61057#issuecomment-1093604398
there's no SELECT_ERR anymore: error conditions (POLLNVAL|POLLERR and also POLLHUP) are reported as SELECT_IN|SELECT_OUT, depending on the input event mask: I don't think that a separate error flag is needed, because the error will be reported when the FD will be read/written (and in the context where the error can be handled appropriately
From: Josiah Ulfers <josiah...@nltgis.com>
Sent: Monday, December 12, 2022 9:27 AM
To: 'python-...@googlegroups.com' <python-...@googlegroups.com>
Subject: RE: [tornado] RE: Incomplete reads from PipeIOStream
Thank you, Python 3 does resolve this pipe problem, but I suspect that pull request is unrelated. Running the example below on Python 3 with Tornado 5 does not show the problem (and neither does the equivalent translation for Tornado 6): If I read the Tornado code correctly, I think the differences is that Tornado 5 uses the asyncio event loop when available and BaseAsyncIOLoop.add_handler() ignores IOLoop.ERROR. So updating to Python 3 does fix the problem (and begs the question of what happens to epoll error events in asyncio, which I haven’t looked into).
From: python-...@googlegroups.com <python-...@googlegroups.com> On Behalf Of Ben Darnell
Sent: Friday, December 9, 2022 11:45 AM
To: python-...@googlegroups.com
Subject: Re: [tornado] RE: Incomplete reads from PipeIOStream
I'm not certain it's the same thing, but Tornado 6.1 fixed some bugs related to reading from IOStreams which the other side closed after sending data (https://github.com/tornadoweb/tornado/pull/2805). This was with sockets and not pipes, so there's a chance that pipes have their own issue, but first I'd try upgrading and see if that fixes the problem.
-Ben
To view this discussion on the web visit https://groups.google.com/d/msgid/python-tornado/CAFkYKJ4patKC%2BKzg5O1DEUByg0Ko%3D2CEKF2vgSQSGBR5KjNXSg%40mail.gmail.com.