[Python-modules-team] Bug#949974: More details

Enrico Zini enrico at enricozini.org
Mon Jan 27 20:46:35 GMT 2020


Hello,

I tracked the issue: in http1connection.py, the write method does:

    self._pending_write = self.stream.write(fchunk)
    self._pending_write.add_done_callback(self._on_write_complete)   

The Future[1] documentation says:

    Callbacks registered with add_done_callback() are always called via
    the event loop’s call_soon_threadsafe().

So although self._pending_write in that case is already in a 'done'
state, self._on_write_complete is only called the next time we'll
reenter the event loop.

Meanwhile, before returning to the event loop, the flow of the code
continues and RequestHandler.finish calls:

    self.request.connection.finish()

It detects correctly that there is still a pending write, and calls:

    future_add_done_callback(self._pending_write, self._finish_request)

However, future_add_done_callback does not schedule self._finish_request
for the next ioloop iteration like Future.add_done_callback does:

    # concurrent.py:
    def future_add_done_callback(future, callback):
        # …
        if future.done():
            callback(future)
        else:
            future.add_done_callback(callback)

Compare with:

    # In concurrent.py, class Future:
    def add_done_callback(self, fn):
        # …
        if self._done:
            from tornado.ioloop import IOLoop
            IOLoop.current().add_callback(fn, self)
        else:
            self._callbacks.append(fn)

So self._finish_request is called before self._on_write_complete,
_clear_callbacks() is called, which resets self._write_callbacks.

When control returns to the event loop, _on_write_complete is finally,
called, which finds self._write_future set to None, and won't trigger
the future that will permit RequestHandler.flush() to continue.

If there is still data to write, self._pending_write is not done when
future_add_done_callback is called, and RequestHandler.flush() won't get
stuck.


Enrico


[1] https://www.tornadoweb.org/en/stable/concurrent.html#tornado.concurrent.Future.add_done_callback

-- 
GPG key: 4096R/634F4BD1E7AD5568 2009-05-08 Enrico Zini <enrico at enricozini.org>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://alioth-lists.debian.net/pipermail/python-modules-team/attachments/20200127/c0a5cbe4/attachment-0001.sig>


More information about the Python-modules-team mailing list