@@ -304,33 +304,54 @@ def shutdown_kernel(self, kernel_id, now=False, restart=False):
304304
305305 return self .pinned_superclass .shutdown_kernel (self , kernel_id , now = now , restart = restart )
306306
307- async def restart_kernel (self , kernel_id , now = False ):
307+ async def restart_kernel (self , kernel_id , channels , now = False ):
308308 """Restart a kernel by kernel_id"""
309309 self ._check_kernel_id (kernel_id )
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 = self .channels ['shell' ]
314+ iopub_channel = self .channels ['iopub' ]
315+
314316 future = Future ()
317+ info_future = Future ()
318+ iopub_future = Future ()
315319
316320 def finish ():
317- """Common cleanup when restart finishes/fails for any reason."""
318- if not channel .closed ():
319- channel .close ()
321+ """Common cleanup"""
320322 loop .remove_timeout (timeout )
323+ loop .remove_timeout (nudge_handle )
324+ iopub_channel .stop_on_recv ()
325+ shell_channel .stop_on_recv ()
321326 kernel .remove_restart_callback (on_restart_failed , 'dead' )
322327
323- def on_reply (msg ):
324- self .log .debug ("Kernel info reply received: %s" , kernel_id )
325- finish ()
326- if not future .done ():
327- future .set_result (msg )
328+ def on_shell_reply (msg ):
329+ if not info_future .done ():
330+ self .log .debug ("Nudge: shell info reply received: %s" , self .kernel_id )
331+ shell_channel .stop_on_recv ()
332+ self .log .debug ("Nudge: resolving shell future" )
333+ info_future .set_result (msg )
334+ if iopub_future .done ():
335+ finish ()
336+ self .log .debug ("Nudge: resolving main future in shell handler" )
337+ future .set_result (info_future .result ())
338+
339+ def on_iopub (msg ):
340+ if not iopub_future .done ():
341+ self .log .debug ("Nudge: first IOPub received: %s" , self .kernel_id )
342+ iopub_channel .stop_on_recv ()
343+ self .log .debug ("Nudge: resolving iopub future" )
344+ iopub_future .set_result (None )
345+ if info_future .done ():
346+ finish ()
347+ self .log .debug ("Nudge: resolving main future in iopub handler" )
348+ future .set_result (info_future .result ())
328349
329350 def on_timeout ():
330- self .log .warning ("Timeout waiting for kernel_info_reply: %s" , kernel_id )
351+ self .log .warning ("Nudge: Timeout waiting for kernel_info_reply: %s" , self . kernel_id )
331352 finish ()
332353 if not future .done ():
333- future .set_exception (TimeoutError ("Timeout waiting for restart " ))
354+ future .set_exception (TimeoutError ("Timeout waiting for nudge " ))
334355
335356 def on_restart_failed ():
336357 self .log .warning ("Restarting kernel failed: %s" , kernel_id )
@@ -339,10 +360,20 @@ def on_restart_failed():
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+
364+ iopub_channel .on_recv (on_iopub )
365+ shell_channel .on_recv (on_shell_reply )
344366 loop = IOLoop .current ()
345- timeout = loop .add_timeout (loop .time () + self .kernel_info_timeout , on_timeout )
367+
368+ # Nudge the kernel with kernel info requests until we get an IOPub message
369+ def nudge ():
370+ self .log .debug ("Nudge" )
371+ if not future .done ():
372+ self .log .debug ("nudging" )
373+ self .session .send (shell_channel , "kernel_info_request" )
374+ nudge_handle = loop .call_later (0.5 , nudge )
375+ nudge_handle = loop .call_later (0 , nudge )
376+
346377 return future
347378
348379 def notify_connect (self , kernel_id ):
0 commit comments