miguelgrinberg/microdot

When disconnecting from network before request is completed microdot dies hard

Closed this issue · 3 comments

mirko commented

This is happening on ESP32 with micropython - so "network" and "wifi" are used interchangeable.
When I'm disconnecting from WiFi within a microdot-handler, microdot fails live below and does not recover from this (as in: does not serve requests anymore after reconnect):

I (802826) wifi: STA_DISCONNECTED, reason:201
Task exception wasn't retrieved
future: <Task> coro= <generator object 'serve' at 3ffd8c00>
Traceback (most recent call last):
  File "uasyncio/core.py", line 1, in run_until_complete
  File "microdot_asyncio.py", line 268, in serve
  File "microdot_asyncio.py", line 336, in handle_request
  File "microdot_asyncio.py", line 143, in write
  File "uasyncio/stream.py", line 1, in stream_awrite
  File "uasyncio/stream.py", line 1, in write
OSError: [Errno 113] ECONNABORTED
Task exception wasn't retrieved
future: <Task> coro= <generator object 'serve' at 3ffd8910>
Traceback (most recent call last):
  File "uasyncio/core.py", line 1, in run_until_complete
  File "microdot_asyncio.py", line 268, in serve
  File "microdot_asyncio.py", line 336, in handle_request
  File "microdot_asyncio.py", line 157, in write
  File "uasyncio/stream.py", line 1, in stream_awrite
  File "uasyncio/stream.py", line 1, in write
OSError: [Errno 113] ECONNABORTED

When shortly afterwards reconnecting back to WiFi and the device being reachable again, microdot's state doesn't allow to accept further connections anymore.

While I see one shouldn't purposely drop the layer-2 connection within the handler, I do believe this might happen in the wild and microdot should recover and - once l2-connection is re-established - continue serving data.
If that's intended behaviour and one is supposed to restart microdot oneself after l2-reconnects, maybe a note within the docs would help and/or an example on how to best deal with such a situation.

How did you reconnect the device after the failure? Microdot does not handle the networking, it assumes that this is managed by the application. My guess is that the server just errored when the network disappeared, so you could catch the exception, and when you can, reconnect and start the server again.

mirko commented

Use case is, I'm intentionally disconnecting and reconnecting WiFi (to be precide, switching WiFi networks, but staying in the same IP space)..
It's triggered by user action via the webinterface.
And I'd love to see the AJAX request - triggering the WiFi switch/reconnect - being completed.
When catching the WiFi-disconnect/exception and restarting microdot, the entire TCP-session will be lost.
I was hoping for a way microdot being able to deal with this "hiccup" and continue trying to (re)send its response, but dealing with l2-reconnects is probably (way) out of its scope.

And I'd love to see the AJAX request - triggering the WiFi switch/reconnect - being completed.

If the device has no network there is no way to tell it to reconnect, so while this sounds great in practice, it is not possible. The device can attempt to reconnect on its own in a retry loop, I guess, but I want this project to be independent of the underlying networking so I don't see it likely that something like this will be added.

I was hoping for a way microdot being able to deal with this "hiccup" and continue trying to (re)send its response

This is not really in scope for this project. What you want is a network stack that is able to handle disconnections and reconnections internally, without affecting the applications that use it.