From 5839771a685d08fe71d7aa7fc5f481ebc82814f3 Mon Sep 17 00:00:00 2001 From: Jeremy Tuloup Date: Fri, 9 Apr 2021 13:49:04 +0200 Subject: [PATCH] Fix race condition with async kernel management --- jupyter_server/services/kernels/kernelmanager.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/jupyter_server/services/kernels/kernelmanager.py b/jupyter_server/services/kernels/kernelmanager.py index bb82ee15fc..179a2a5fa3 100644 --- a/jupyter_server/services/kernels/kernelmanager.py +++ b/jupyter_server/services/kernels/kernelmanager.py @@ -313,7 +313,12 @@ def shutdown_kernel(self, kernel_id, now=False, restart=False): type=self._kernels[kernel_id].kernel_name ).dec() - return self.pinned_superclass.shutdown_kernel(self, kernel_id, now=now, restart=restart) + self.pinned_superclass.shutdown_kernel(self, kernel_id, now=now, restart=restart) + # Unlike its async sibling method in AsyncMappingKernelManager, removing the kernel_id + # from the connections dictionary isn't as problematic before the shutdown since the + # method is synchronous. However, we'll keep the relative call orders the same from + # a maintenance perspective. + self._kernel_connections.pop(kernel_id, None) async def restart_kernel(self, kernel_id, now=False): """Restart a kernel by kernel_id""" @@ -388,8 +393,11 @@ def list_kernels(self): kernels = [] kernel_ids = self.pinned_superclass.list_kernel_ids(self) for kernel_id in kernel_ids: - model = self.kernel_model(kernel_id) - kernels.append(model) + try: + model = self.kernel_model(kernel_id) + kernels.append(model) + except (web.HTTPError, KeyError): + pass # Probably due to a (now) non-existent kernel, continue building the list return kernels # override _check_kernel_id to raise 404 instead of KeyError