drivers: prevent client crash if GET /drivers is closed from client side

When a HTTP client sends a query but closes the socket before an answer
is received,  aiohttp signals it on the server end by raising an
asyncio.CancelledError in the associated query handler.

By default, when a task is cancelled with asyncio, the task(s) that it
is currently awaiting on are cancelled as well.

The GET handler for /drivers?wait=true awaits on the "list drivers"
task. Therefore, if the GET handler gets cancelled, so will be the "list
drivers" task.

When that happens, any subsequent call to GET /drivers?wait=true will
make the server raise an asyncio.CancelledError because the "list
drivers" task has already been cancelled. This results in:

 * the socket being closed from the server end
 * an aiohttp.client_exceptions.ServerDisconnectedError exception raised
   on the client end. This type of exception is unhandled and makes the
   client crash.

Fixed by preventing the "list drivers" task from being cancelled when
the GET /drivers query handler gets cancelled.

https://bugs.launchpad.net/subiquity/+bug/1968729

Signed-off-by: Olivier Gayot <olivier.gayot@canonical.com>
This commit is contained in:
Olivier Gayot 2022-04-14 15:05:19 +02:00
parent c101e63521
commit bacbe5d4bb
1 changed files with 1 additions and 1 deletions

View File

@ -91,7 +91,7 @@ class DriversController(SubiquityController):
async def GET(self, wait: bool = False) -> DriversResponse:
if wait:
await self._drivers_task
await asyncio.shield(self._drivers_task)
return DriversResponse(install=self.model.do_install,
drivers=self.drivers)