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

Python 3.7: RuntimeError: read() called while another coroutine is already waiting for incoming data #169

Open
klairetan opened this issue Mar 20, 2021 · 1 comment

Comments

@klairetan
Copy link

I'm running into basically the same issue as encode/httpx#527. When running client requests concurrently, the request ends up throwing with a stack trace like below

packages/thriftpy2/contrib/aio/client.py", line 42, in _req return (yield from self._recv(_api))
File "/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/client.py", line 56, in _recv fname, mtype, rseqid = yield from self._iprot.read_message_begin()
File "/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/protocol/binary.py", line 251, in read_message_begin api, ttype, seqid = yield from read_message_begin( 
  File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/protocol/binary.py", line 28, in read_message_begin sz = unpack_i32((yield from inbuf.read(4))) 
   File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/base.py", line 47, in read return (yield from readall(self._read, sz)) 
    File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/base.py", line 15, in readall chunk = yield from read_fn(sz - have) 
     File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/buffered.py", line 40, in _read buf = yield from self._trans.read(max(rest_len, self._buf_size)) 
      File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/framed.py", line 41, in read yield from self.read_frame() 
       File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/framed.py", line 46, in read_frame buff = yield from readall(self._trans.read, 4) 
        File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/transport/base.py", line 15, in readall chunk = yield from read_fn(sz - have) 
         File"/var/lib/conda/envs/ktan/lib/python3.8/site-packages/thriftpy2/contrib/aio/socket.py", line 169, in read buff = yield from asyncio.wait_for( 
          File"/var/lib/conda/envs/ktan/lib/python3.8/asyncio/tasks.py", line 483, in wait_for return fut.result() 
           File"/var/lib/conda/envs/ktan/lib/python3.8/asyncio/streams.py", line 684, in read await self._wait_for_data('read') 
            File"/var/lib/conda/envs/ktan/lib/python3.8/asyncio/streams.py", line 503, in _wait_for_data raise RuntimeError( RuntimeError: read() called while another coroutine is already waiting for incoming data

This tends to happen when I run two client methods concurrently. For example, when I run the following snippet 1000 times, it would throw the above error around 40% of the time.

bar, foo, zed = await asyncio.gather(
   thrift_client.get_bar(...),
   thrift_client.get_foo(...),
   thrift_client.get_zed(...)
)

Since all requests share the same StreamReader, I wonder if when we make requests concurrently, it's possible we end up calling self._wait_for_data('read') from a second request that also tries to run another read coroutine? Has anyone run into this before? The folks working on httpx got around it by adding a lock around trying to read from the stream.

@ethe
Copy link
Member

ethe commented Mar 22, 2021

There is not a reporting before, I will try to reproduce your case, thank you

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

No branches or pull requests

2 participants