uselect ability to signal socket.close in uasyncio mode

C programming, build, interpreter/VM.
Target audience: MicroPython Developers.
Post Reply
domcharn
Posts: 3
Joined: Fri Nov 17, 2017 6:11 am

uselect ability to signal socket.close in uasyncio mode

Post by domcharn » Thu Oct 25, 2018 6:09 am

Hi, everybody
In uasyncio environment a coro (a) is waiting on Streamreader socket
an other coro (b) closes intentionally Streamreader.s(socket) of coro(a)
the coro (a) remains read-waiting.
in this case neither uselect.POLLHUP nor uselect.POLLERR seams to be fired
For this special configuration is there a way to cancel pending Streamreader: new uselect.mask , other....
Best Regards

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uselect ability to signal socket.close in uasyncio mode

Post by pythoncoder » Thu Oct 25, 2018 10:11 am

The uasyncio code is intended to respond to POLLHUP and POLLERR conditions, rescheduling the stalled IO task which presumably needs to respond appropriately.

To identify where the problem lies it might be worth trying a coro which calls the socket read method directly rather than via a StreamReader to see what happens when another coro closes the socket. It's not clear to me whether the problem is with the socket or the StreamReader.
Peter Hinch
Index to my micropython libraries.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uselect ability to signal socket.close in uasyncio mode

Post by pythoncoder » Fri Nov 02, 2018 1:19 pm

I have now looked at this further. The following produces and traps an OSError if another task closes the socket.

Code: Select all

async def run1():
    global s  # Socket connected to a SOCK_STREAM server
    s.setblocking(False)
    try:
        while True:
            r = s.readline()
            if r is not None:
                print(r)  # When socket closed got OSError: [Errno 9] EBADF
            await asyncio.sleep(0)
    except OSError:
        print('Socket was closed.')  # Prints as expected
However when I use the select mechanism it seems impossible to detect the fact that the socket has been closed. This explains why the StreamReader hangs. I'd appreciate comments from those more experienced with select on whether this is in fact a bug. Here is the test coro (another closes the socket after a period).

Code: Select all

poller = select.poll()
poller.register(s, select.POLLIN)  # s is a socket connected to a SOCK_STREAM server
s.setblocking(False)

async def run():
    global poller
    try:
        while True:
            res = poller.ipoll(10)
            for sock, ev in res:
                if ev & select.POLLIN:
                    r = sock.readline()
                    print(ev, r)  # ev is always 1
                else:  # Hoping to see POLLHUP or POLLERR but it
                    print(ev)  # never happens even if I kill server
            await asyncio.sleep(0)
    except OSError:
        print('Socket was closed.')  # Never happens
I can post the server code and the complete test if anyone wants to play.

I am keen to see StreamReader and StreamWriter respond to exceptions for my own purposes.
Peter Hinch
Index to my micropython libraries.

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: uselect ability to signal socket.close in uasyncio mode

Post by pythoncoder » Sat Nov 03, 2018 10:44 am

I've now done further testing and have formed the view that the ustream poll object is behaving inconsistently and is not behaving in the way expected by uasyncio. This is causing the hang. I've raised this issue.

This isn't to say that fixing poll will fix the issue: testing uasyncio is impracticable while this is unresolved.
Peter Hinch
Index to my micropython libraries.

Post Reply