@@ -310,37 +310,62 @@ async def restart_kernel(self, kernel_id, now=False):
310310 await maybe_future (self .pinned_superclass .restart_kernel (self , kernel_id , now = now ))
311311 kernel = self .get_kernel (kernel_id )
312312 # return a Future that will resolve when the kernel has successfully restarted
313- channel = kernel .connect_shell ()
313+ shell_channel = kernel .connect_shell ()
314+ iopub_channel = kernel .connect_iopub ()
314315 future = Future ()
316+ info_future = Future ()
317+ iopub_future = Future ()
315318
316319 def finish ():
317320 """Common cleanup when restart finishes/fails for any reason."""
318- if not channel .closed ():
319- channel .close ()
320321 loop .remove_timeout (timeout )
321322 kernel .remove_restart_callback (on_restart_failed , 'dead' )
322323
323- def on_reply (msg ):
324+ def on_shell_reply (msg ):
324325 self .log .debug ("Kernel info reply received: %s" , kernel_id )
325- finish ()
326- if not future .done ():
327- future .set_result (msg )
326+ shell_channel .close ()
327+ if not info_future .done ():
328+ info_future .set_result (msg )
329+ if iopub_future .done ():
330+ finish ()
331+ future .set_result (info_future .result ())
332+
333+ def on_iopub (msg ):
334+ self .log .debug ("first IOPub received: %s" , kernel_id )
335+ iopub_channel .close ()
336+ if not iopub_future .done ():
337+ iopub_future .set_result (None )
338+ if info_future .done ():
339+ finish ()
340+ future .set_result (info_future .result ())
328341
329342 def on_timeout ():
330343 self .log .warning ("Timeout waiting for kernel_info_reply: %s" , kernel_id )
344+ if not shell_channel .closed ():
345+ shell_channel .close ()
346+ if not iopub_channel .closed ():
347+ iopub_channel .close ()
331348 finish ()
332349 if not future .done ():
333350 future .set_exception (TimeoutError ("Timeout waiting for restart" ))
334351
335352 def on_restart_failed ():
336353 self .log .warning ("Restarting kernel failed: %s" , kernel_id )
354+ if not shell_channel .closed ():
355+ shell_channel .close ()
356+ if not iopub_channel .closed ():
357+ iopub_channel .close ()
337358 finish ()
338359 if not future .done ():
339360 future .set_exception (RuntimeError ("Restart failed" ))
340361
341362 kernel .add_restart_callback (on_restart_failed , 'dead' )
342- kernel .session .send (channel , "kernel_info_request" )
343- channel .on_recv (on_reply )
363+ iopub_channel .on_recv (on_iopub )
364+ shell_channel .on_recv (on_shell_reply )
365+ while not future .done ():
366+ time .sleep (0.2 )
367+ # Nudge the kernel with kernel info requests until we get an IOPub message
368+ kernel .session .send (shell_channel , "kernel_info_request" )
344369 loop = IOLoop .current ()
345370 timeout = loop .add_timeout (loop .time () + self .kernel_info_timeout , on_timeout )
346371 return future
0 commit comments