-
-
Notifications
You must be signed in to change notification settings - Fork 8.3k
extmod/asyncio: Fix Stream.wait_closed
.
#13533
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
base: master
Are you sure you want to change the base?
Conversation
Code size report:
|
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## master #13533 +/- ##
=======================================
Coverage 98.36% 98.36%
=======================================
Files 159 159
Lines 21090 21090
=======================================
Hits 20745 20745
Misses 345 345 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Leaving pending bytes at server side will cause the socket to be closed promptly when `Stream.wait_closed` is called which raises `ECONNRESET` at client side. The fix is to make sure there is no pending data and then close the socket. Signed-off-by: Carlos Gil <carlosgilglez@gmail.com>
c9dea4d
to
e793718
Compare
Thanks for the patch. As per #13478 (comment), this will need a minimal example to show the problem. |
Yes the example is the test (see the comments) async def handle_connection(reader, writer):
# Test that peername exists (but don't check its value, it changes)
writer.get_extra_info("peername")
data = await reader.read(11) # leaving bytes unread triggers the error
# data = await reader.read(13) # reading everything
print("echo:", data.replace(b"\r\n", b""))
writer.write(data)
await writer.drain()
print("close")
writer.close()
await writer.wait_closed()
print("done")
ev.set()
async def tcp_server():
global ev
ev = asyncio.Event()
server = await asyncio.start_server(handle_connection, "0.0.0.0", PORT)
print("server running")
multitest.next()
async with server:
await asyncio.wait_for(ev.wait(), 10)
async def tcp_client(message):
reader, writer = await asyncio.open_connection(IP, PORT)
print("write:", message.replace(b"\r\n", b""))
writer.write(message)
await writer.drain()
data = await reader.read() # if the client doesn't read exactly or isn't fast
# enough e.g.
# data = await reader.read(11) # this works on unix because is
# fast enough, however esp32 fails.
print("read:", data.replace(b"\r\n", b""))
def instance0():
multitest.globals(IP=multitest.get_network_ip())
asyncio.run(tcp_server())
def instance1():
multitest.next()
asyncio.run(tcp_client(b"client data\r\n")) Without the patch this test fails with Also I'm not sure if this is the right fix or if we should be looking deeper? 🤔 |
Oh, sorry, right! I will take a proper look at it. |
I have tested this patch with my code (and with @Carglglz recent |
Leaving pending bytes at server side will cause the socket to be closed promptly when
Stream.wait_closed
is called which raisesECONNRESET
at client side.The fix is to make sure there is no pending data and then close the socket.