Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BufferError: Existing exports of data: object cannot be re-sized #2700

Open
rahultaing opened this issue Jul 4, 2019 · 2 comments
Open

BufferError: Existing exports of data: object cannot be re-sized #2700

rahultaing opened this issue Jul 4, 2019 · 2 comments
Labels

Comments

@rahultaing
Copy link

rahultaing commented Jul 4, 2019

We have a single threaded application using tornado 4.5.3. The application calls stream.write to flush data downstream. We wrote a UT in which we mock the write_to_fd to return 0 bytes. We are trying to replicate a scenario in which the self._write_buffer would continually grow if no bound has been specified.

This test results in a BufferError every time the self._write_buffer is being updated either in write method self._write_buffer += data or in _handle_write method del self._write_buffer[:self._write_buffer_pos]

Let me know if there is other information we can share to help root cause this issue.

@bdarnell
Copy link
Member

bdarnell commented Jul 4, 2019

Can you post this unit test? Does it reproduce with newer versions of Tornado?

@rahultaing
Copy link
Author

rahultaing commented Jul 4, 2019

Here's what the test looks like. AsyncStatsite is our statsite client that is using tornado tcpclient to connect to statsrelay and flush data periodically or when the buffer gets full.

@pytest.mark.gen_test
def test_stream_write_buffer_error(io_loop):
    statsite = AsyncStatsite("127.0.0.1", 8125, io_loop)

    def log_statsite():
        with patch.object(tornado.iostream.IOStream, 'write_to_fd', return_value=0):
            statsite.log(["123" for x in xrange(MESSAGES_TO_BUFFER+1)])

    def stop_ioloop():
        tornado.ioloop.IOLoop.current().stop()

    PeriodicCallback(log_statsite, 1, io_loop).start()
    io_loop.call_later(15, stop_ioloop)

    io_loop.start()

In the AsyncStatsite __init__ we just connect using TCPClient:

 client = tornado.tcpclient.TCPClient()
 self.connect = functools.partial(client.connect, host, port)
 self.stream = self._ioloop.run_sync(self.connect)

And we flush using the write method:
yield self.stream.write(buffer_data)

It doesn't repro on higher versions because that line of code (del self._write_buffer[:self._write_buffer_pos]) has been updated and buffer implementation isn't the same as in version 4.5.3

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants