@@ -222,6 +222,22 @@ async def _async_start_kernel(self, kernel_name: t.Optional[str] = None, **kwarg
222
222
223
223
start_kernel = run_sync (_async_start_kernel )
224
224
225
+ async def _shutdown_kernel_when_ready (
226
+ self ,
227
+ kernel_id : str ,
228
+ now : t .Optional [bool ] = False ,
229
+ restart : t .Optional [bool ] = False ,
230
+ ) -> None :
231
+ """Wait for a pending kernel to be ready
232
+ before shutting the kernel down.
233
+ """
234
+ # Only do this if using pending kernels
235
+ if self ._using_pending_kernels ():
236
+ kernel = self ._kernels [kernel_id ]
237
+ await kernel .ready
238
+ # Once out of a pending state, we can call shutdown.
239
+ await ensure_async (self .shutdown_kernel (kernel_id , now = now , restart = restart ))
240
+
225
241
async def _async_shutdown_kernel (
226
242
self ,
227
243
kernel_id : str ,
@@ -243,9 +259,9 @@ async def _async_shutdown_kernel(
243
259
# If we're using pending kernels, block shutdown when a kernel is pending.
244
260
if self ._using_pending_kernels () and kernel_id in self ._pending_kernels :
245
261
raise RuntimeError ("Kernel is in a pending state. Cannot shutdown." )
246
- # If the kernel isn't in a ready state , wait for it to be ready.
247
- elif kernel_id in self ._pending_kernels :
248
- kernel = self ._pending_kernels [kernel_id ]
262
+ # If the kernel is still starting , wait for it to be ready.
263
+ elif kernel_id in self ._starting_kernels :
264
+ kernel = self ._starting_kernels [kernel_id ]
249
265
try :
250
266
await kernel
251
267
except Exception :
@@ -262,6 +278,9 @@ async def _async_shutdown_kernel(
262
278
# Await the kernel if not using pending kernels.
263
279
if not self ._using_pending_kernels ():
264
280
await fut
281
+ # raise an exception if one occurred during kernel shutdown.
282
+ if km .ready .exception ():
283
+ raise km .ready .exception () # type: ignore
265
284
266
285
shutdown_kernel = run_sync (_async_shutdown_kernel )
267
286
@@ -296,9 +315,14 @@ def remove_kernel(self, kernel_id: str) -> KernelManager:
296
315
async def _async_shutdown_all (self , now : bool = False ) -> None :
297
316
"""Shutdown all kernels."""
298
317
kids = self .list_kernel_ids ()
299
- kids += list (self ._starting_kernels )
300
- futs = [ensure_async (self .shutdown_kernel (kid , now = now )) for kid in set (kids )]
318
+ kids += list (self ._pending_kernels )
319
+ futs = [ensure_async (self ._shutdown_kernel_when_ready (kid , now = now )) for kid in set (kids )]
301
320
await asyncio .gather (* futs )
321
+ # When using "shutdown all", all pending kernels
322
+ # should be awaited before exiting this method.
323
+ if self ._using_pending_kernels ():
324
+ for km in self ._kernels .values ():
325
+ await km .ready
302
326
303
327
shutdown_all = run_sync (_async_shutdown_all )
304
328
0 commit comments