Skip to content

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

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

Carglglz
Copy link
Contributor

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.

Copy link

github-actions bot commented Jan 27, 2024

Code size report:

   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:  +120 +0.015% standard[incl +32(data)]
      stm32:   +72 +0.018% PYBV10
     mimxrt:   +80 +0.022% TEENSY40
        rp2:   +72 +0.022% RPI_PICO
       samd:   +76 +0.029% ADAFRUIT_ITSYBITSY_M4_EXPRESS

Copy link

codecov bot commented Jan 27, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 98.36%. Comparing base (4a2e510) to head (e793718).
Report is 1750 commits behind head on master.

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.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Carglglz Carglglz marked this pull request as draft January 28, 2024 03:53
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>
@Carglglz Carglglz force-pushed the asyncio-wait_closed-fix branch from c9dea4d to e793718 Compare January 28, 2024 14:57
@dpgeorge dpgeorge added the extmod Relates to extmod/ directory in source label Jan 29, 2024
@dpgeorge
Copy link
Member

Thanks for the patch.

As per #13478 (comment), this will need a minimal example to show the problem.

@Carglglz
Copy link
Contributor Author

Carglglz commented Jan 29, 2024

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 OSError: [Errno 104] ECONNRESET

Also I'm not sure if this is the right fix or if we should be looking deeper? 🤔

@dpgeorge
Copy link
Member

Yes the example is the test

Oh, sorry, right! I will take a proper look at it.

@bikeNomad
Copy link
Contributor

I have tested this patch with my code (and with @Carglglz recent aiohttp fixes) and it appears to work.

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

Successfully merging this pull request may close these issues.

3 participants
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy