aioserial.py icon indicating copy to clipboard operation
aioserial.py copied to clipboard

`cancel_read()` does not work

Open schperplata opened this issue 10 months ago • 0 comments

Seems like aioserial.cancel_read() does not work. It might be that I am not aware of some concurrency rule(s), as I am quite inexperienced with asyncio/aioserial.

Here is the minimum steps to reproduce:

import asyncio
import time

import aioserial


async def read_and_print(port: aioserial.AioSerial):
    while True:
        try:
            print("Reading....")
            data: bytes = await port.read_async()
            print(data, flush=True)
        except asyncio.CancelledError:
            print("Cancelled")
            break
        except Exception:
            print("Other exception?")
            break


async def wait_and_cancel(port: aioserial.AioSerial):
    await asyncio.sleep(1)
    print("Cancel request!")
    port.cancel_read()


async def main():
    port: aioserial.AioSerial = aioserial.AioSerial(port="COM6", baudrate=115200, timeout=5)

    start = time.perf_counter()
    await asyncio.gather(read_and_print(port), wait_and_cancel(port))
    end = time.perf_counter()
    print(f"Duration: {end-start:3f}")


if __name__ == "__main__":
    asyncio.run(main())

Read timeout is intentionally set to 5 sec, while it should be canceled by cancel_read() after 1 sec. I would expect first cancel_read() to throw exception and break out of read_and_print(), something like this:

Reading....
Cancel request!
Cancelled
Duration: 1.001

Instead, nothing happens and loop is continuing:

Reading....
Cancel request!
b''
Reading....
b''
Reading....
b''
Reading....
b''

...

I've tested this with non-async version of the same code, with aioserial (read() running in thread, cancel_read() in main), and it works, so it must be something related to async stuff.

Any help is very appreciated.

schperplata avatar Sep 03 '23 09:09 schperplata