sanic: asyncio.exceptions.CancelledError On Windows OS

The following exception raised when running the hello world example on Windows with Microsoft store version of Python 3.9.

WSL2 environment does not reproduce the issue.

from sanic import Sanic
from sanic.response import json

app = Sanic("My Hello, world app")

@app.route('/')
async def test(request):
    return json({'hello': 'world'})

if __name__ == '__main__':
    app.run()
[2021-06-30 23:00:05 -0700] [12184] [INFO] Goin' Fast @ http://127.0.0.1:8000
[2021-06-30 23:00:06 -0700] [12184] [INFO] Starting worker [12184]
[2021-06-30 23:00:11 -0700] - (sanic.access)[INFO][127.0.0.1:53159]: GET http://127.0.0.1:8000/  200 17
[2021-06-30 23:01:11 -0700] [12184] [ERROR] Exception occurred while handling uri: 'http:///*'
Traceback (most recent call last):
  File "C:\Users\zhiwe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\sanic\http.py", line 126, in http1
    await self.http1_request_header()
  File "C:\Users\zhiwe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\sanic\http.py", line 188, in http1_request_header      
    await self._receive_more()
  File "C:\Users\zhiwe\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.9_qbz5n2kfra8p0\LocalCache\local-packages\Python39\site-packages\sanic\server.py", line 222, in receive_more
    await self._data_received.wait()
  File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.9_3.9.1776.0_x64__qbz5n2kfra8p0\lib\asyncio\locks.py", line 226, in wait
    await fut
asyncio.exceptions.CancelledError
[2021-06-30 23:01:11 -0700] - (sanic.access)[INFO][UNKNOWN]: NONE http:///*  408 664

About this issue

  • Original URL
  • State: closed
  • Created 3 years ago
  • Comments: 15 (15 by maintainers)

Most upvoted comments

Ahh, that might make sense. I’m going to be pushing out a patch in Sunday so I will take a closer look at this.

    def check_timeouts(self):
        """
        Runs itself periodically to enforce any expired timeouts.
        """
        try:
            if not self._task:
                return
            duration = current_time() - self._time
            stage = self._http.stage
            if stage is Stage.IDLE and duration > self.keep_alive_timeout:
                logger.debug("KeepAlive Timeout. Closing connection.")
            elif stage is Stage.REQUEST and duration > self.request_timeout:
                logger.debug("Request Timeout. Closing connection.")
                self._http.exception = RequestTimeout("Request Timeout")
            elif stage is Stage.HANDLER and self._http.upgrade_websocket:
                logger.debug("Handling websocket. Timeouts disabled.")
                return
            elif (
                stage in (Stage.HANDLER, Stage.RESPONSE, Stage.FAILED)
                and duration > self.response_timeout
            ):
                logger.debug("Response Timeout. Closing connection.")
                self._http.exception = ServiceUnavailable("Response Timeout")
            else:
                interval = (
                    min(
                        self.keep_alive_timeout,
                        self.request_timeout,
                        self.response_timeout,
                    )
                    / 2
                )
                self.loop.call_later(max(0.1, interval), self.check_timeouts)
                return
            self._task.cancel()
        except Exception:
            error_logger.exception("protocol.check_timeouts")

server.py runs this background task that runs periodically checks if any timeouts have expired, then cancels self._task that handles the connection (server.py function connection_task that calls http.py and other functions). The connection_task function is supposed to catch and ignore CancelledError, so I would look into why you still get an error message. From the backtrace it looks as if http1_request_header is catching and logging the error, which is probably unintentional.

Happy hacking!