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
AsyncIO Race Condition Fix #2641
Conversation
Codecov ReportPatch coverage:
Additional details and impacted files@@ Coverage Diff @@
## master #2641 +/- ##
===========================================
- Coverage 92.28% 78.22% -14.06%
===========================================
Files 115 115
Lines 29751 29787 +36
===========================================
- Hits 27455 23301 -4154
- Misses 2296 6486 +4190
... and 38 files with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here.
|
@chayim I think this only fixed the pipeline, while the race condition still exists in the redis-py/redis/asyncio/client.py Line 514 in 66a4d6b
I can still reproduce #2624 using the latest redis-py Keep in mind that you need slow enough Redis connection to reproduce this, otherwise the cancellation does not happen simply because the entire RESP exchange with Redis happens before there is a chance to cancel the task. Also, are you sure that shielding from cancellation is the right approach? For example, this means that there would be no way to cancel a blocking BLPOP. |
I found the same problem. Just install the Redis service locally and run the following code and it will definitely reproduce: import asyncio
from redis.asyncio import Redis
async def main():
async with Redis(single_connection_client=True) as r:
await r.set('foo', 'foo')
await r.set('bar', 'bar')
t = asyncio.create_task(r.get('foo'))
await asyncio.sleep(0) # <--- must 0
t.cancel()
try:
await t
print('try again, we did not cancel the task in time')
except asyncio.CancelledError as e:
print('managed to cancel the task, connection is left open with unread response')
print('bar:', await r.get('bar'))
print('ping:', await r.ping())
print('foo:', await r.get('foo'))
if __name__ == '__main__':
asyncio.run(main()) |
closes #2624
closes #2579